1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 #ifndef SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_VFIO_PCI_DEVICE_H 3 #define SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_VFIO_PCI_DEVICE_H 4 5 #include <fcntl.h> 6 #include <linux/vfio.h> 7 #include <linux/pci_regs.h> 8 9 #include <libvfio/assert.h> 10 #include <libvfio/iommu.h> 11 #include <libvfio/vfio_pci_driver.h> 12 13 struct vfio_pci_bar { 14 struct vfio_region_info info; 15 void *vaddr; 16 }; 17 18 struct vfio_pci_device { 19 const char *bdf; 20 int fd; 21 int group_fd; 22 23 struct iommu *iommu; 24 25 struct vfio_device_info info; 26 struct vfio_region_info config_space; 27 struct vfio_pci_bar bars[PCI_STD_NUM_BARS]; 28 29 struct vfio_irq_info msi_info; 30 struct vfio_irq_info msix_info; 31 32 /* eventfds for MSI and MSI-x interrupts */ 33 int msi_eventfds[PCI_MSIX_FLAGS_QSIZE + 1]; 34 35 struct vfio_pci_driver driver; 36 }; 37 38 #define dev_info(_dev, _fmt, ...) printf("%s: " _fmt, (_dev)->bdf, ##__VA_ARGS__) 39 #define dev_err(_dev, _fmt, ...) fprintf(stderr, "%s: " _fmt, (_dev)->bdf, ##__VA_ARGS__) 40 41 struct vfio_pci_device *vfio_pci_device_alloc(const char *bdf, struct iommu *iommu); 42 void vfio_pci_device_free(struct vfio_pci_device *device); 43 struct vfio_pci_device *vfio_pci_device_init(const char *bdf, struct iommu *iommu); 44 void vfio_pci_device_cleanup(struct vfio_pci_device *device); 45 46 void vfio_pci_device_reset(struct vfio_pci_device *device); 47 48 void vfio_pci_config_access(struct vfio_pci_device *device, bool write, 49 size_t config, size_t size, void *data); 50 51 #define vfio_pci_config_read(_device, _offset, _type) ({ \ 52 _type __data; \ 53 vfio_pci_config_access((_device), false, _offset, sizeof(__data), &__data); \ 54 __data; \ 55 }) 56 57 #define vfio_pci_config_readb(_d, _o) vfio_pci_config_read(_d, _o, u8) 58 #define vfio_pci_config_readw(_d, _o) vfio_pci_config_read(_d, _o, u16) 59 #define vfio_pci_config_readl(_d, _o) vfio_pci_config_read(_d, _o, u32) 60 61 #define vfio_pci_config_write(_device, _offset, _value, _type) do { \ 62 _type __data = (_value); \ 63 vfio_pci_config_access((_device), true, _offset, sizeof(_type), &__data); \ 64 } while (0) 65 66 #define vfio_pci_config_writeb(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u8) 67 #define vfio_pci_config_writew(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u16) 68 #define vfio_pci_config_writel(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u32) 69 70 void vfio_pci_irq_enable(struct vfio_pci_device *device, u32 index, 71 u32 vector, int count); 72 void vfio_pci_irq_disable(struct vfio_pci_device *device, u32 index); 73 void vfio_pci_irq_trigger(struct vfio_pci_device *device, u32 index, u32 vector); 74 75 static inline void fcntl_set_nonblock(int fd) 76 { 77 int r; 78 79 r = fcntl(fd, F_GETFL, 0); 80 VFIO_ASSERT_NE(r, -1, "F_GETFL failed for fd %d\n", fd); 81 82 r = fcntl(fd, F_SETFL, r | O_NONBLOCK); 83 VFIO_ASSERT_NE(r, -1, "F_SETFL O_NONBLOCK failed for fd %d\n", fd); 84 } 85 86 static inline void vfio_pci_msi_enable(struct vfio_pci_device *device, 87 u32 vector, int count) 88 { 89 vfio_pci_irq_enable(device, VFIO_PCI_MSI_IRQ_INDEX, vector, count); 90 } 91 92 static inline void vfio_pci_msi_disable(struct vfio_pci_device *device) 93 { 94 vfio_pci_irq_disable(device, VFIO_PCI_MSI_IRQ_INDEX); 95 } 96 97 static inline void vfio_pci_msix_enable(struct vfio_pci_device *device, 98 u32 vector, int count) 99 { 100 vfio_pci_irq_enable(device, VFIO_PCI_MSIX_IRQ_INDEX, vector, count); 101 } 102 103 static inline void vfio_pci_msix_disable(struct vfio_pci_device *device) 104 { 105 vfio_pci_irq_disable(device, VFIO_PCI_MSIX_IRQ_INDEX); 106 } 107 108 static inline int __to_iova(struct vfio_pci_device *device, void *vaddr, iova_t *iova) 109 { 110 return __iommu_hva2iova(device->iommu, vaddr, iova); 111 } 112 113 static inline iova_t to_iova(struct vfio_pci_device *device, void *vaddr) 114 { 115 return iommu_hva2iova(device->iommu, vaddr); 116 } 117 118 static inline bool vfio_pci_device_match(struct vfio_pci_device *device, 119 u16 vendor_id, u16 device_id) 120 { 121 return (vendor_id == vfio_pci_config_readw(device, PCI_VENDOR_ID)) && 122 (device_id == vfio_pci_config_readw(device, PCI_DEVICE_ID)); 123 } 124 125 const char *vfio_pci_get_cdev_path(const char *bdf); 126 127 void vfio_pci_group_setup(struct vfio_pci_device *device, const char *bdf); 128 void __vfio_pci_group_get_device_fd(struct vfio_pci_device *device, 129 const char *bdf, const char *vf_token); 130 void vfio_container_set_iommu(struct vfio_pci_device *device); 131 void vfio_pci_cdev_open(struct vfio_pci_device *device, const char *bdf); 132 int __vfio_device_bind_iommufd(int device_fd, int iommufd, const char *vf_token); 133 134 void vfio_device_set_vf_token(int fd, const char *vf_token); 135 136 #endif /* SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_VFIO_PCI_DEVICE_H */ 137