Skip to content

Commit 5fabc49

Browse files
dmatlackawilliam
authored andcommitted
vfio: selftests: Split libvfio.h into separate header files
Split out the contents of libvfio.h into separate header files, but keep libvfio.h as the top-level include that all tests can use. Put all new header files into a libvfio/ subdirectory to avoid future name conflicts in include paths when libvfio is used by other selftests like KVM. No functional change intended. Reviewed-by: Alex Mastro <amastro@fb.com> Tested-by: Alex Mastro <amastro@fb.com> Reviewed-by: Raghavendra Rao Ananta <rananta@google.com> Signed-off-by: David Matlack <dmatlack@google.com> Link: https://lore.kernel.org/r/20251126231733.3302983-17-dmatlack@google.com Signed-off-by: Alex Williamson <alex@shazbot.org>
1 parent 19cf492 commit 5fabc49

6 files changed

Lines changed: 381 additions & 334 deletions

File tree

tools/testing/selftests/vfio/lib/include/libvfio.h

Lines changed: 5 additions & 334 deletions
Original file line numberDiff line numberDiff line change
@@ -2,210 +2,11 @@
22
#ifndef SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_H
33
#define SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_H
44

5-
#include <fcntl.h>
6-
#include <string.h>
7-
8-
#include <uapi/linux/types.h>
9-
#include <linux/iommufd.h>
10-
#include <linux/list.h>
11-
#include <linux/pci_regs.h>
12-
#include <linux/vfio.h>
13-
14-
#include "../../../kselftest.h"
15-
16-
#define VFIO_LOG_AND_EXIT(...) do { \
17-
fprintf(stderr, " " __VA_ARGS__); \
18-
fprintf(stderr, "\n"); \
19-
exit(KSFT_FAIL); \
20-
} while (0)
21-
22-
#define VFIO_ASSERT_OP(_lhs, _rhs, _op, ...) do { \
23-
typeof(_lhs) __lhs = (_lhs); \
24-
typeof(_rhs) __rhs = (_rhs); \
25-
\
26-
if (__lhs _op __rhs) \
27-
break; \
28-
\
29-
fprintf(stderr, "%s:%u: Assertion Failure\n\n", __FILE__, __LINE__); \
30-
fprintf(stderr, " Expression: " #_lhs " " #_op " " #_rhs "\n"); \
31-
fprintf(stderr, " Observed: %#lx %s %#lx\n", \
32-
(u64)__lhs, #_op, (u64)__rhs); \
33-
fprintf(stderr, " [errno: %d - %s]\n", errno, strerror(errno)); \
34-
VFIO_LOG_AND_EXIT(__VA_ARGS__); \
35-
} while (0)
36-
37-
#define VFIO_ASSERT_EQ(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, ==, ##__VA_ARGS__)
38-
#define VFIO_ASSERT_NE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, !=, ##__VA_ARGS__)
39-
#define VFIO_ASSERT_LT(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, <, ##__VA_ARGS__)
40-
#define VFIO_ASSERT_LE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, <=, ##__VA_ARGS__)
41-
#define VFIO_ASSERT_GT(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, >, ##__VA_ARGS__)
42-
#define VFIO_ASSERT_GE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, >=, ##__VA_ARGS__)
43-
#define VFIO_ASSERT_TRUE(_a, ...) VFIO_ASSERT_NE(false, (_a), ##__VA_ARGS__)
44-
#define VFIO_ASSERT_FALSE(_a, ...) VFIO_ASSERT_EQ(false, (_a), ##__VA_ARGS__)
45-
#define VFIO_ASSERT_NULL(_a, ...) VFIO_ASSERT_EQ(NULL, _a, ##__VA_ARGS__)
46-
#define VFIO_ASSERT_NOT_NULL(_a, ...) VFIO_ASSERT_NE(NULL, _a, ##__VA_ARGS__)
47-
48-
#define VFIO_FAIL(_fmt, ...) do { \
49-
fprintf(stderr, "%s:%u: FAIL\n\n", __FILE__, __LINE__); \
50-
VFIO_LOG_AND_EXIT(_fmt, ##__VA_ARGS__); \
51-
} while (0)
52-
53-
#define ioctl_assert(_fd, _op, _arg) do { \
54-
void *__arg = (_arg); \
55-
int __ret = ioctl((_fd), (_op), (__arg)); \
56-
VFIO_ASSERT_EQ(__ret, 0, "ioctl(%s, %s, %s) returned %d\n", #_fd, #_op, #_arg, __ret); \
57-
} while (0)
58-
59-
#define dev_info(_dev, _fmt, ...) printf("%s: " _fmt, (_dev)->bdf, ##__VA_ARGS__)
60-
#define dev_err(_dev, _fmt, ...) fprintf(stderr, "%s: " _fmt, (_dev)->bdf, ##__VA_ARGS__)
61-
62-
struct iommu_mode {
63-
const char *name;
64-
const char *container_path;
65-
unsigned long iommu_type;
66-
};
67-
68-
/*
69-
* Generator for VFIO selftests fixture variants that replicate across all
70-
* possible IOMMU modes. Tests must define FIXTURE_VARIANT_ADD_IOMMU_MODE()
71-
* which should then use FIXTURE_VARIANT_ADD() to create the variant.
72-
*/
73-
#define FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(...) \
74-
FIXTURE_VARIANT_ADD_IOMMU_MODE(vfio_type1_iommu, ##__VA_ARGS__); \
75-
FIXTURE_VARIANT_ADD_IOMMU_MODE(vfio_type1v2_iommu, ##__VA_ARGS__); \
76-
FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd_compat_type1, ##__VA_ARGS__); \
77-
FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd_compat_type1v2, ##__VA_ARGS__); \
78-
FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd, ##__VA_ARGS__)
79-
80-
struct vfio_pci_bar {
81-
struct vfio_region_info info;
82-
void *vaddr;
83-
};
84-
85-
typedef u64 iova_t;
86-
87-
#define INVALID_IOVA UINT64_MAX
88-
89-
struct dma_region {
90-
struct list_head link;
91-
void *vaddr;
92-
iova_t iova;
93-
u64 size;
94-
};
95-
96-
struct vfio_pci_device;
97-
98-
struct vfio_pci_driver_ops {
99-
const char *name;
100-
101-
/**
102-
* @probe() - Check if the driver supports the given device.
103-
*
104-
* Return: 0 on success, non-0 on failure.
105-
*/
106-
int (*probe)(struct vfio_pci_device *device);
107-
108-
/**
109-
* @init() - Initialize the driver for @device.
110-
*
111-
* Must be called after device->driver.region has been initialized.
112-
*/
113-
void (*init)(struct vfio_pci_device *device);
114-
115-
/**
116-
* remove() - Deinitialize the driver for @device.
117-
*/
118-
void (*remove)(struct vfio_pci_device *device);
119-
120-
/**
121-
* memcpy_start() - Kick off @count repeated memcpy operations from
122-
* [@src, @src + @size) to [@dst, @dst + @size).
123-
*
124-
* Guarantees:
125-
* - The device will attempt DMA reads on [src, src + size).
126-
* - The device will attempt DMA writes on [dst, dst + size).
127-
* - The device will not generate any interrupts.
128-
*
129-
* memcpy_start() returns immediately, it does not wait for the
130-
* copies to complete.
131-
*/
132-
void (*memcpy_start)(struct vfio_pci_device *device,
133-
iova_t src, iova_t dst, u64 size, u64 count);
134-
135-
/**
136-
* memcpy_wait() - Wait until the memcpy operations started by
137-
* memcpy_start() have finished.
138-
*
139-
* Guarantees:
140-
* - All in-flight DMAs initiated by memcpy_start() are fully complete
141-
* before memcpy_wait() returns.
142-
*
143-
* Returns non-0 if the driver detects that an error occurred during the
144-
* memcpy, 0 otherwise.
145-
*/
146-
int (*memcpy_wait)(struct vfio_pci_device *device);
147-
148-
/**
149-
* send_msi() - Make the device send the MSI device->driver.msi.
150-
*
151-
* Guarantees:
152-
* - The device will send the MSI once.
153-
*/
154-
void (*send_msi)(struct vfio_pci_device *device);
155-
};
156-
157-
struct vfio_pci_driver {
158-
const struct vfio_pci_driver_ops *ops;
159-
bool initialized;
160-
bool memcpy_in_progress;
161-
162-
/* Region to be used by the driver (e.g. for in-memory descriptors) */
163-
struct dma_region region;
164-
165-
/* The maximum size that can be passed to memcpy_start(). */
166-
u64 max_memcpy_size;
167-
168-
/* The maximum count that can be passed to memcpy_start(). */
169-
u64 max_memcpy_count;
170-
171-
/* The MSI vector the device will signal in ops->send_msi(). */
172-
int msi;
173-
};
174-
175-
struct iommu {
176-
const struct iommu_mode *mode;
177-
int container_fd;
178-
int iommufd;
179-
u32 ioas_id;
180-
struct list_head dma_regions;
181-
};
182-
183-
struct vfio_pci_device {
184-
const char *bdf;
185-
int fd;
186-
int group_fd;
187-
188-
struct iommu *iommu;
189-
190-
struct vfio_device_info info;
191-
struct vfio_region_info config_space;
192-
struct vfio_pci_bar bars[PCI_STD_NUM_BARS];
193-
194-
struct vfio_irq_info msi_info;
195-
struct vfio_irq_info msix_info;
196-
197-
/* eventfds for MSI and MSI-x interrupts */
198-
int msi_eventfds[PCI_MSIX_FLAGS_QSIZE + 1];
199-
200-
struct vfio_pci_driver driver;
201-
};
202-
203-
struct iova_allocator {
204-
struct iommu_iova_range *ranges;
205-
u32 nranges;
206-
u32 range_idx;
207-
u64 range_offset;
208-
};
5+
#include <libvfio/assert.h>
6+
#include <libvfio/iommu.h>
7+
#include <libvfio/iova_allocator.h>
8+
#include <libvfio/vfio_pci_device.h>
9+
#include <libvfio/vfio_pci_driver.h>
20910

21011
/*
21112
* Return the BDF string of the device that the test should use.
@@ -222,134 +23,4 @@ struct iova_allocator {
22223
const char *vfio_selftests_get_bdf(int *argc, char *argv[]);
22324
char **vfio_selftests_get_bdfs(int *argc, char *argv[], int *nr_bdfs);
22425

225-
const char *vfio_pci_get_cdev_path(const char *bdf);
226-
227-
extern const char *default_iommu_mode;
228-
229-
struct iommu *iommu_init(const char *iommu_mode);
230-
void iommu_cleanup(struct iommu *iommu);
231-
232-
int __iommu_map(struct iommu *iommu, struct dma_region *region);
233-
234-
static inline void iommu_map(struct iommu *iommu, struct dma_region *region)
235-
{
236-
VFIO_ASSERT_EQ(__iommu_map(iommu, region), 0);
237-
}
238-
239-
int __iommu_unmap(struct iommu *iommu, struct dma_region *region, u64 *unmapped);
240-
241-
static inline void iommu_unmap(struct iommu *iommu, struct dma_region *region)
242-
{
243-
VFIO_ASSERT_EQ(__iommu_unmap(iommu, region, NULL), 0);
244-
}
245-
246-
int __iommu_unmap_all(struct iommu *iommu, u64 *unmapped);
247-
248-
static inline void iommu_unmap_all(struct iommu *iommu)
249-
{
250-
VFIO_ASSERT_EQ(__iommu_unmap_all(iommu, NULL), 0);
251-
}
252-
253-
iova_t __iommu_hva2iova(struct iommu *iommu, void *vaddr);
254-
iova_t iommu_hva2iova(struct iommu *iommu, void *vaddr);
255-
256-
struct iommu_iova_range *iommu_iova_ranges(struct iommu *iommu, u32 *nranges);
257-
258-
struct vfio_pci_device *vfio_pci_device_init(const char *bdf, struct iommu *iommu);
259-
void vfio_pci_device_cleanup(struct vfio_pci_device *device);
260-
261-
void vfio_pci_device_reset(struct vfio_pci_device *device);
262-
263-
struct iova_allocator *iova_allocator_init(struct iommu *iommu);
264-
void iova_allocator_cleanup(struct iova_allocator *allocator);
265-
iova_t iova_allocator_alloc(struct iova_allocator *allocator, size_t size);
266-
267-
void vfio_pci_config_access(struct vfio_pci_device *device, bool write,
268-
size_t config, size_t size, void *data);
269-
270-
#define vfio_pci_config_read(_device, _offset, _type) ({ \
271-
_type __data; \
272-
vfio_pci_config_access((_device), false, _offset, sizeof(__data), &__data); \
273-
__data; \
274-
})
275-
276-
#define vfio_pci_config_readb(_d, _o) vfio_pci_config_read(_d, _o, u8)
277-
#define vfio_pci_config_readw(_d, _o) vfio_pci_config_read(_d, _o, u16)
278-
#define vfio_pci_config_readl(_d, _o) vfio_pci_config_read(_d, _o, u32)
279-
280-
#define vfio_pci_config_write(_device, _offset, _value, _type) do { \
281-
_type __data = (_value); \
282-
vfio_pci_config_access((_device), true, _offset, sizeof(_type), &__data); \
283-
} while (0)
284-
285-
#define vfio_pci_config_writeb(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u8)
286-
#define vfio_pci_config_writew(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u16)
287-
#define vfio_pci_config_writel(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u32)
288-
289-
void vfio_pci_irq_enable(struct vfio_pci_device *device, u32 index,
290-
u32 vector, int count);
291-
void vfio_pci_irq_disable(struct vfio_pci_device *device, u32 index);
292-
void vfio_pci_irq_trigger(struct vfio_pci_device *device, u32 index, u32 vector);
293-
294-
static inline void fcntl_set_nonblock(int fd)
295-
{
296-
int r;
297-
298-
r = fcntl(fd, F_GETFL, 0);
299-
VFIO_ASSERT_NE(r, -1, "F_GETFL failed for fd %d\n", fd);
300-
301-
r = fcntl(fd, F_SETFL, r | O_NONBLOCK);
302-
VFIO_ASSERT_NE(r, -1, "F_SETFL O_NONBLOCK failed for fd %d\n", fd);
303-
}
304-
305-
static inline void vfio_pci_msi_enable(struct vfio_pci_device *device,
306-
u32 vector, int count)
307-
{
308-
vfio_pci_irq_enable(device, VFIO_PCI_MSI_IRQ_INDEX, vector, count);
309-
}
310-
311-
static inline void vfio_pci_msi_disable(struct vfio_pci_device *device)
312-
{
313-
vfio_pci_irq_disable(device, VFIO_PCI_MSI_IRQ_INDEX);
314-
}
315-
316-
static inline void vfio_pci_msix_enable(struct vfio_pci_device *device,
317-
u32 vector, int count)
318-
{
319-
vfio_pci_irq_enable(device, VFIO_PCI_MSIX_IRQ_INDEX, vector, count);
320-
}
321-
322-
static inline void vfio_pci_msix_disable(struct vfio_pci_device *device)
323-
{
324-
vfio_pci_irq_disable(device, VFIO_PCI_MSIX_IRQ_INDEX);
325-
}
326-
327-
static inline iova_t __to_iova(struct vfio_pci_device *device, void *vaddr)
328-
{
329-
return __iommu_hva2iova(device->iommu, vaddr);
330-
}
331-
332-
static inline iova_t to_iova(struct vfio_pci_device *device, void *vaddr)
333-
{
334-
return iommu_hva2iova(device->iommu, vaddr);
335-
}
336-
337-
static inline bool vfio_pci_device_match(struct vfio_pci_device *device,
338-
u16 vendor_id, u16 device_id)
339-
{
340-
return (vendor_id == vfio_pci_config_readw(device, PCI_VENDOR_ID)) &&
341-
(device_id == vfio_pci_config_readw(device, PCI_DEVICE_ID));
342-
}
343-
344-
void vfio_pci_driver_probe(struct vfio_pci_device *device);
345-
void vfio_pci_driver_init(struct vfio_pci_device *device);
346-
void vfio_pci_driver_remove(struct vfio_pci_device *device);
347-
int vfio_pci_driver_memcpy(struct vfio_pci_device *device,
348-
iova_t src, iova_t dst, u64 size);
349-
void vfio_pci_driver_memcpy_start(struct vfio_pci_device *device,
350-
iova_t src, iova_t dst, u64 size,
351-
u64 count);
352-
int vfio_pci_driver_memcpy_wait(struct vfio_pci_device *device);
353-
void vfio_pci_driver_send_msi(struct vfio_pci_device *device);
354-
35526
#endif /* SELFTESTS_VFIO_LIB_INCLUDE_LIBVFIO_H */

0 commit comments

Comments
 (0)