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