18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
48c2ecf20Sopenharmony_ci *     Author: Alex Williamson <alex.williamson@redhat.com>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Derived from original vfio:
78c2ecf20Sopenharmony_ci * Copyright 2010 Cisco Systems, Inc.  All rights reserved.
88c2ecf20Sopenharmony_ci * Author: Tom Lyon, pugs@cisco.com
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/mutex.h>
128c2ecf20Sopenharmony_ci#include <linux/pci.h>
138c2ecf20Sopenharmony_ci#include <linux/irqbypass.h>
148c2ecf20Sopenharmony_ci#include <linux/types.h>
158c2ecf20Sopenharmony_ci#include <linux/uuid.h>
168c2ecf20Sopenharmony_ci#include <linux/notifier.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#ifndef VFIO_PCI_PRIVATE_H
198c2ecf20Sopenharmony_ci#define VFIO_PCI_PRIVATE_H
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#define VFIO_PCI_OFFSET_SHIFT   40
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define VFIO_PCI_OFFSET_TO_INDEX(off)	(off >> VFIO_PCI_OFFSET_SHIFT)
248c2ecf20Sopenharmony_ci#define VFIO_PCI_INDEX_TO_OFFSET(index)	((u64)(index) << VFIO_PCI_OFFSET_SHIFT)
258c2ecf20Sopenharmony_ci#define VFIO_PCI_OFFSET_MASK	(((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1)
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* Special capability IDs predefined access */
288c2ecf20Sopenharmony_ci#define PCI_CAP_ID_INVALID		0xFF	/* default raw access */
298c2ecf20Sopenharmony_ci#define PCI_CAP_ID_INVALID_VIRT		0xFE	/* default virt access */
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci/* Cap maximum number of ioeventfds per device (arbitrary) */
328c2ecf20Sopenharmony_ci#define VFIO_PCI_IOEVENTFD_MAX		1000
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_cistruct vfio_pci_ioeventfd {
358c2ecf20Sopenharmony_ci	struct list_head	next;
368c2ecf20Sopenharmony_ci	struct vfio_pci_device	*vdev;
378c2ecf20Sopenharmony_ci	struct virqfd		*virqfd;
388c2ecf20Sopenharmony_ci	void __iomem		*addr;
398c2ecf20Sopenharmony_ci	uint64_t		data;
408c2ecf20Sopenharmony_ci	loff_t			pos;
418c2ecf20Sopenharmony_ci	int			bar;
428c2ecf20Sopenharmony_ci	int			count;
438c2ecf20Sopenharmony_ci	bool			test_mem;
448c2ecf20Sopenharmony_ci};
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistruct vfio_pci_irq_ctx {
478c2ecf20Sopenharmony_ci	struct eventfd_ctx	*trigger;
488c2ecf20Sopenharmony_ci	struct virqfd		*unmask;
498c2ecf20Sopenharmony_ci	struct virqfd		*mask;
508c2ecf20Sopenharmony_ci	char			*name;
518c2ecf20Sopenharmony_ci	bool			masked;
528c2ecf20Sopenharmony_ci	struct irq_bypass_producer	producer;
538c2ecf20Sopenharmony_ci};
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistruct vfio_pci_device;
568c2ecf20Sopenharmony_cistruct vfio_pci_region;
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistruct vfio_pci_regops {
598c2ecf20Sopenharmony_ci	size_t	(*rw)(struct vfio_pci_device *vdev, char __user *buf,
608c2ecf20Sopenharmony_ci		      size_t count, loff_t *ppos, bool iswrite);
618c2ecf20Sopenharmony_ci	void	(*release)(struct vfio_pci_device *vdev,
628c2ecf20Sopenharmony_ci			   struct vfio_pci_region *region);
638c2ecf20Sopenharmony_ci	int	(*mmap)(struct vfio_pci_device *vdev,
648c2ecf20Sopenharmony_ci			struct vfio_pci_region *region,
658c2ecf20Sopenharmony_ci			struct vm_area_struct *vma);
668c2ecf20Sopenharmony_ci	int	(*add_capability)(struct vfio_pci_device *vdev,
678c2ecf20Sopenharmony_ci				  struct vfio_pci_region *region,
688c2ecf20Sopenharmony_ci				  struct vfio_info_cap *caps);
698c2ecf20Sopenharmony_ci};
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistruct vfio_pci_region {
728c2ecf20Sopenharmony_ci	u32				type;
738c2ecf20Sopenharmony_ci	u32				subtype;
748c2ecf20Sopenharmony_ci	const struct vfio_pci_regops	*ops;
758c2ecf20Sopenharmony_ci	void				*data;
768c2ecf20Sopenharmony_ci	size_t				size;
778c2ecf20Sopenharmony_ci	u32				flags;
788c2ecf20Sopenharmony_ci};
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistruct vfio_pci_dummy_resource {
818c2ecf20Sopenharmony_ci	struct resource		resource;
828c2ecf20Sopenharmony_ci	int			index;
838c2ecf20Sopenharmony_ci	struct list_head	res_next;
848c2ecf20Sopenharmony_ci};
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_cistruct vfio_pci_reflck {
878c2ecf20Sopenharmony_ci	struct kref		kref;
888c2ecf20Sopenharmony_ci	struct mutex		lock;
898c2ecf20Sopenharmony_ci};
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_cistruct vfio_pci_vf_token {
928c2ecf20Sopenharmony_ci	struct mutex		lock;
938c2ecf20Sopenharmony_ci	uuid_t			uuid;
948c2ecf20Sopenharmony_ci	int			users;
958c2ecf20Sopenharmony_ci};
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistruct vfio_pci_mmap_vma {
988c2ecf20Sopenharmony_ci	struct vm_area_struct	*vma;
998c2ecf20Sopenharmony_ci	struct list_head	vma_next;
1008c2ecf20Sopenharmony_ci};
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistruct vfio_pci_device {
1038c2ecf20Sopenharmony_ci	struct pci_dev		*pdev;
1048c2ecf20Sopenharmony_ci	void __iomem		*barmap[PCI_STD_NUM_BARS];
1058c2ecf20Sopenharmony_ci	bool			bar_mmap_supported[PCI_STD_NUM_BARS];
1068c2ecf20Sopenharmony_ci	u8			*pci_config_map;
1078c2ecf20Sopenharmony_ci	u8			*vconfig;
1088c2ecf20Sopenharmony_ci	struct perm_bits	*msi_perm;
1098c2ecf20Sopenharmony_ci	spinlock_t		irqlock;
1108c2ecf20Sopenharmony_ci	struct mutex		igate;
1118c2ecf20Sopenharmony_ci	struct vfio_pci_irq_ctx	*ctx;
1128c2ecf20Sopenharmony_ci	int			num_ctx;
1138c2ecf20Sopenharmony_ci	int			irq_type;
1148c2ecf20Sopenharmony_ci	int			num_regions;
1158c2ecf20Sopenharmony_ci	struct vfio_pci_region	*region;
1168c2ecf20Sopenharmony_ci	u8			msi_qmax;
1178c2ecf20Sopenharmony_ci	u8			msix_bar;
1188c2ecf20Sopenharmony_ci	u16			msix_size;
1198c2ecf20Sopenharmony_ci	u32			msix_offset;
1208c2ecf20Sopenharmony_ci	u32			rbar[7];
1218c2ecf20Sopenharmony_ci	bool			pci_2_3;
1228c2ecf20Sopenharmony_ci	bool			virq_disabled;
1238c2ecf20Sopenharmony_ci	bool			reset_works;
1248c2ecf20Sopenharmony_ci	bool			extended_caps;
1258c2ecf20Sopenharmony_ci	bool			bardirty;
1268c2ecf20Sopenharmony_ci	bool			has_vga;
1278c2ecf20Sopenharmony_ci	bool			needs_reset;
1288c2ecf20Sopenharmony_ci	bool			nointx;
1298c2ecf20Sopenharmony_ci	bool			needs_pm_restore;
1308c2ecf20Sopenharmony_ci	struct pci_saved_state	*pci_saved_state;
1318c2ecf20Sopenharmony_ci	struct pci_saved_state	*pm_save;
1328c2ecf20Sopenharmony_ci	struct vfio_pci_reflck	*reflck;
1338c2ecf20Sopenharmony_ci	int			refcnt;
1348c2ecf20Sopenharmony_ci	int			ioeventfds_nr;
1358c2ecf20Sopenharmony_ci	struct eventfd_ctx	*err_trigger;
1368c2ecf20Sopenharmony_ci	struct eventfd_ctx	*req_trigger;
1378c2ecf20Sopenharmony_ci	struct list_head	dummy_resources_list;
1388c2ecf20Sopenharmony_ci	struct mutex		ioeventfds_lock;
1398c2ecf20Sopenharmony_ci	struct list_head	ioeventfds_list;
1408c2ecf20Sopenharmony_ci	struct vfio_pci_vf_token	*vf_token;
1418c2ecf20Sopenharmony_ci	struct notifier_block	nb;
1428c2ecf20Sopenharmony_ci	struct mutex		vma_lock;
1438c2ecf20Sopenharmony_ci	struct list_head	vma_list;
1448c2ecf20Sopenharmony_ci	struct rw_semaphore	memory_lock;
1458c2ecf20Sopenharmony_ci};
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci#define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX)
1488c2ecf20Sopenharmony_ci#define is_msi(vdev) (vdev->irq_type == VFIO_PCI_MSI_IRQ_INDEX)
1498c2ecf20Sopenharmony_ci#define is_msix(vdev) (vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX)
1508c2ecf20Sopenharmony_ci#define is_irq_none(vdev) (!(is_intx(vdev) || is_msi(vdev) || is_msix(vdev)))
1518c2ecf20Sopenharmony_ci#define irq_is(vdev, type) (vdev->irq_type == type)
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ciextern void vfio_pci_intx_mask(struct vfio_pci_device *vdev);
1548c2ecf20Sopenharmony_ciextern void vfio_pci_intx_unmask(struct vfio_pci_device *vdev);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ciextern int vfio_pci_set_irqs_ioctl(struct vfio_pci_device *vdev,
1578c2ecf20Sopenharmony_ci				   uint32_t flags, unsigned index,
1588c2ecf20Sopenharmony_ci				   unsigned start, unsigned count, void *data);
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ciextern ssize_t vfio_pci_config_rw(struct vfio_pci_device *vdev,
1618c2ecf20Sopenharmony_ci				  char __user *buf, size_t count,
1628c2ecf20Sopenharmony_ci				  loff_t *ppos, bool iswrite);
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ciextern ssize_t vfio_pci_bar_rw(struct vfio_pci_device *vdev, char __user *buf,
1658c2ecf20Sopenharmony_ci			       size_t count, loff_t *ppos, bool iswrite);
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ciextern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
1688c2ecf20Sopenharmony_ci			       size_t count, loff_t *ppos, bool iswrite);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ciextern long vfio_pci_ioeventfd(struct vfio_pci_device *vdev, loff_t offset,
1718c2ecf20Sopenharmony_ci			       uint64_t data, int count, int fd);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ciextern int vfio_pci_init_perm_bits(void);
1748c2ecf20Sopenharmony_ciextern void vfio_pci_uninit_perm_bits(void);
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ciextern int vfio_config_init(struct vfio_pci_device *vdev);
1778c2ecf20Sopenharmony_ciextern void vfio_config_free(struct vfio_pci_device *vdev);
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_ciextern int vfio_pci_register_dev_region(struct vfio_pci_device *vdev,
1808c2ecf20Sopenharmony_ci					unsigned int type, unsigned int subtype,
1818c2ecf20Sopenharmony_ci					const struct vfio_pci_regops *ops,
1828c2ecf20Sopenharmony_ci					size_t size, u32 flags, void *data);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ciextern int vfio_pci_set_power_state(struct vfio_pci_device *vdev,
1858c2ecf20Sopenharmony_ci				    pci_power_t state);
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ciextern bool __vfio_pci_memory_enabled(struct vfio_pci_device *vdev);
1888c2ecf20Sopenharmony_ciextern void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_device
1898c2ecf20Sopenharmony_ci						    *vdev);
1908c2ecf20Sopenharmony_ciextern u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_device *vdev);
1918c2ecf20Sopenharmony_ciextern void vfio_pci_memory_unlock_and_restore(struct vfio_pci_device *vdev,
1928c2ecf20Sopenharmony_ci					       u16 cmd);
1938c2ecf20Sopenharmony_ci
1948c2ecf20Sopenharmony_ci#ifdef CONFIG_VFIO_PCI_IGD
1958c2ecf20Sopenharmony_ciextern int vfio_pci_igd_init(struct vfio_pci_device *vdev);
1968c2ecf20Sopenharmony_ci#else
1978c2ecf20Sopenharmony_cistatic inline int vfio_pci_igd_init(struct vfio_pci_device *vdev)
1988c2ecf20Sopenharmony_ci{
1998c2ecf20Sopenharmony_ci	return -ENODEV;
2008c2ecf20Sopenharmony_ci}
2018c2ecf20Sopenharmony_ci#endif
2028c2ecf20Sopenharmony_ci#ifdef CONFIG_VFIO_PCI_NVLINK2
2038c2ecf20Sopenharmony_ciextern int vfio_pci_nvdia_v100_nvlink2_init(struct vfio_pci_device *vdev);
2048c2ecf20Sopenharmony_ciextern int vfio_pci_ibm_npu2_init(struct vfio_pci_device *vdev);
2058c2ecf20Sopenharmony_ci#else
2068c2ecf20Sopenharmony_cistatic inline int vfio_pci_nvdia_v100_nvlink2_init(struct vfio_pci_device *vdev)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	return -ENODEV;
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_cistatic inline int vfio_pci_ibm_npu2_init(struct vfio_pci_device *vdev)
2128c2ecf20Sopenharmony_ci{
2138c2ecf20Sopenharmony_ci	return -ENODEV;
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci#endif
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci#ifdef CONFIG_VFIO_PCI_ZDEV
2188c2ecf20Sopenharmony_ciextern int vfio_pci_info_zdev_add_caps(struct vfio_pci_device *vdev,
2198c2ecf20Sopenharmony_ci				       struct vfio_info_cap *caps);
2208c2ecf20Sopenharmony_ci#else
2218c2ecf20Sopenharmony_cistatic inline int vfio_pci_info_zdev_add_caps(struct vfio_pci_device *vdev,
2228c2ecf20Sopenharmony_ci					      struct vfio_info_cap *caps)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	return -ENODEV;
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci#endif
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci#endif /* VFIO_PCI_PRIVATE_H */
229