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 int __vfio_pci_device_reset(struct vfio_pci_device *device);
47 void vfio_pci_device_reset(struct vfio_pci_device *device);
48
49 void vfio_pci_config_access(struct vfio_pci_device *device, bool write,
50 size_t config, size_t size, void *data);
51
52 #define vfio_pci_config_read(_device, _offset, _type) ({ \
53 _type __data; \
54 vfio_pci_config_access((_device), false, _offset, sizeof(__data), &__data); \
55 __data; \
56 })
57
58 #define vfio_pci_config_readb(_d, _o) vfio_pci_config_read(_d, _o, u8)
59 #define vfio_pci_config_readw(_d, _o) vfio_pci_config_read(_d, _o, u16)
60 #define vfio_pci_config_readl(_d, _o) vfio_pci_config_read(_d, _o, u32)
61
62 #define vfio_pci_config_write(_device, _offset, _value, _type) do { \
63 _type __data = (_value); \
64 vfio_pci_config_access((_device), true, _offset, sizeof(_type), &__data); \
65 } while (0)
66
67 #define vfio_pci_config_writeb(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u8)
68 #define vfio_pci_config_writew(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u16)
69 #define vfio_pci_config_writel(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u32)
70
vfio_pci_cmd_set(struct vfio_pci_device * device,u16 bits)71 static inline void vfio_pci_cmd_set(struct vfio_pci_device *device, u16 bits)
72 {
73 u16 cmd = vfio_pci_config_readw(device, PCI_COMMAND);
74
75 vfio_pci_config_writew(device, PCI_COMMAND, cmd | bits);
76 }
77
vfio_pci_cmd_clear(struct vfio_pci_device * device,u16 bits)78 static inline void vfio_pci_cmd_clear(struct vfio_pci_device *device, u16 bits)
79 {
80 u16 cmd = vfio_pci_config_readw(device, PCI_COMMAND);
81
82 vfio_pci_config_writew(device, PCI_COMMAND, cmd & ~bits);
83 }
84
85 void vfio_pci_irq_enable(struct vfio_pci_device *device, u32 index,
86 u32 vector, int count);
87 void vfio_pci_irq_disable(struct vfio_pci_device *device, u32 index);
88 void vfio_pci_irq_reenable(struct vfio_pci_device *device, u32 index,
89 u32 vector, int count);
90 void vfio_pci_irq_trigger(struct vfio_pci_device *device, u32 index, u32 vector);
91
fcntl_set_nonblock(int fd)92 static inline void fcntl_set_nonblock(int fd)
93 {
94 int r;
95
96 r = fcntl(fd, F_GETFL, 0);
97 VFIO_ASSERT_NE(r, -1, "F_GETFL failed for fd %d\n", fd);
98
99 r = fcntl(fd, F_SETFL, r | O_NONBLOCK);
100 VFIO_ASSERT_NE(r, -1, "F_SETFL O_NONBLOCK failed for fd %d\n", fd);
101 }
102
vfio_pci_msi_enable(struct vfio_pci_device * device,u32 vector,int count)103 static inline void vfio_pci_msi_enable(struct vfio_pci_device *device,
104 u32 vector, int count)
105 {
106 vfio_pci_irq_enable(device, VFIO_PCI_MSI_IRQ_INDEX, vector, count);
107 }
108
vfio_pci_msi_disable(struct vfio_pci_device * device)109 static inline void vfio_pci_msi_disable(struct vfio_pci_device *device)
110 {
111 vfio_pci_irq_disable(device, VFIO_PCI_MSI_IRQ_INDEX);
112 }
113
vfio_pci_msi_reenable(struct vfio_pci_device * device,u32 vector,int count)114 static inline void vfio_pci_msi_reenable(struct vfio_pci_device *device,
115 u32 vector, int count)
116 {
117 vfio_pci_irq_reenable(device, VFIO_PCI_MSI_IRQ_INDEX, vector, count);
118 }
119
vfio_pci_msix_enable(struct vfio_pci_device * device,u32 vector,int count)120 static inline void vfio_pci_msix_enable(struct vfio_pci_device *device,
121 u32 vector, int count)
122 {
123 vfio_pci_irq_enable(device, VFIO_PCI_MSIX_IRQ_INDEX, vector, count);
124 }
125
vfio_pci_msix_disable(struct vfio_pci_device * device)126 static inline void vfio_pci_msix_disable(struct vfio_pci_device *device)
127 {
128 vfio_pci_irq_disable(device, VFIO_PCI_MSIX_IRQ_INDEX);
129 }
130
vfio_pci_msix_reenable(struct vfio_pci_device * device,u32 vector,int count)131 static inline void vfio_pci_msix_reenable(struct vfio_pci_device *device,
132 u32 vector, int count)
133 {
134 vfio_pci_irq_reenable(device, VFIO_PCI_MSIX_IRQ_INDEX, vector, count);
135 }
136
__to_iova(struct vfio_pci_device * device,void * vaddr,iova_t * iova)137 static inline int __to_iova(struct vfio_pci_device *device, void *vaddr, iova_t *iova)
138 {
139 return __iommu_hva2iova(device->iommu, vaddr, iova);
140 }
141
to_iova(struct vfio_pci_device * device,void * vaddr)142 static inline iova_t to_iova(struct vfio_pci_device *device, void *vaddr)
143 {
144 return iommu_hva2iova(device->iommu, vaddr);
145 }
146
vfio_pci_device_match(struct vfio_pci_device * device,u16 vendor_id,u16 device_id)147 static inline bool vfio_pci_device_match(struct vfio_pci_device *device,
148 u16 vendor_id, u16 device_id)
149 {
150 return (vendor_id == vfio_pci_config_readw(device, PCI_VENDOR_ID)) &&
151 (device_id == vfio_pci_config_readw(device, PCI_DEVICE_ID));
152 }
153
154 const char *vfio_pci_get_cdev_path(const char *bdf);
155
156 void vfio_pci_group_setup(struct vfio_pci_device *device, const char *bdf);
157 void __vfio_pci_group_get_device_fd(struct vfio_pci_device *device,
158 const char *bdf, const char *vf_token);
159 void vfio_container_set_iommu(struct vfio_pci_device *device);
160 void vfio_pci_cdev_open(struct vfio_pci_device *device, const char *bdf);
161 int __vfio_device_bind_iommufd(int device_fd, int iommufd, const char *vf_token);
162
163 void vfio_device_set_vf_token(int fd, const char *vf_token);
164
165 #endif /* SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_VFIO_PCI_DEVICE_H */
166