119faf6fdSDavid Matlack /* SPDX-License-Identifier: GPL-2.0-only */
219faf6fdSDavid Matlack #ifndef SELFTESTS_VFIO_LIB_INCLUDE_VFIO_UTIL_H
319faf6fdSDavid Matlack #define SELFTESTS_VFIO_LIB_INCLUDE_VFIO_UTIL_H
419faf6fdSDavid Matlack
592494780SDavid Matlack #include <fcntl.h>
619faf6fdSDavid Matlack #include <string.h>
719faf6fdSDavid Matlack #include <linux/vfio.h>
819faf6fdSDavid Matlack #include <linux/list.h>
919faf6fdSDavid Matlack #include <linux/pci_regs.h>
1019faf6fdSDavid Matlack
1119faf6fdSDavid Matlack #include "../../../kselftest.h"
1219faf6fdSDavid Matlack
1319faf6fdSDavid Matlack #define VFIO_LOG_AND_EXIT(...) do { \
1419faf6fdSDavid Matlack fprintf(stderr, " " __VA_ARGS__); \
1519faf6fdSDavid Matlack fprintf(stderr, "\n"); \
1619faf6fdSDavid Matlack exit(KSFT_FAIL); \
1719faf6fdSDavid Matlack } while (0)
1819faf6fdSDavid Matlack
1919faf6fdSDavid Matlack #define VFIO_ASSERT_OP(_lhs, _rhs, _op, ...) do { \
2019faf6fdSDavid Matlack typeof(_lhs) __lhs = (_lhs); \
2119faf6fdSDavid Matlack typeof(_rhs) __rhs = (_rhs); \
2219faf6fdSDavid Matlack \
2319faf6fdSDavid Matlack if (__lhs _op __rhs) \
2419faf6fdSDavid Matlack break; \
2519faf6fdSDavid Matlack \
2619faf6fdSDavid Matlack fprintf(stderr, "%s:%u: Assertion Failure\n\n", __FILE__, __LINE__); \
2719faf6fdSDavid Matlack fprintf(stderr, " Expression: " #_lhs " " #_op " " #_rhs "\n"); \
2819faf6fdSDavid Matlack fprintf(stderr, " Observed: %#lx %s %#lx\n", \
2919faf6fdSDavid Matlack (u64)__lhs, #_op, (u64)__rhs); \
3019faf6fdSDavid Matlack fprintf(stderr, " [errno: %d - %s]\n", errno, strerror(errno)); \
3119faf6fdSDavid Matlack VFIO_LOG_AND_EXIT(__VA_ARGS__); \
3219faf6fdSDavid Matlack } while (0)
3319faf6fdSDavid Matlack
3419faf6fdSDavid Matlack #define VFIO_ASSERT_EQ(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, ==, ##__VA_ARGS__)
3519faf6fdSDavid Matlack #define VFIO_ASSERT_NE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, !=, ##__VA_ARGS__)
3619faf6fdSDavid Matlack #define VFIO_ASSERT_LT(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, <, ##__VA_ARGS__)
3719faf6fdSDavid Matlack #define VFIO_ASSERT_LE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, <=, ##__VA_ARGS__)
3819faf6fdSDavid Matlack #define VFIO_ASSERT_GT(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, >, ##__VA_ARGS__)
3919faf6fdSDavid Matlack #define VFIO_ASSERT_GE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, >=, ##__VA_ARGS__)
4019faf6fdSDavid Matlack #define VFIO_ASSERT_TRUE(_a, ...) VFIO_ASSERT_NE(false, (_a), ##__VA_ARGS__)
4119faf6fdSDavid Matlack #define VFIO_ASSERT_FALSE(_a, ...) VFIO_ASSERT_EQ(false, (_a), ##__VA_ARGS__)
4219faf6fdSDavid Matlack #define VFIO_ASSERT_NULL(_a, ...) VFIO_ASSERT_EQ(NULL, _a, ##__VA_ARGS__)
4319faf6fdSDavid Matlack #define VFIO_ASSERT_NOT_NULL(_a, ...) VFIO_ASSERT_NE(NULL, _a, ##__VA_ARGS__)
4419faf6fdSDavid Matlack
4519faf6fdSDavid Matlack #define VFIO_FAIL(_fmt, ...) do { \
4619faf6fdSDavid Matlack fprintf(stderr, "%s:%u: FAIL\n\n", __FILE__, __LINE__); \
4719faf6fdSDavid Matlack VFIO_LOG_AND_EXIT(_fmt, ##__VA_ARGS__); \
4819faf6fdSDavid Matlack } while (0)
4919faf6fdSDavid Matlack
505df9bd62SDavid Matlack struct vfio_iommu_mode {
515df9bd62SDavid Matlack const char *name;
525df9bd62SDavid Matlack const char *container_path;
535df9bd62SDavid Matlack unsigned long iommu_type;
545df9bd62SDavid Matlack };
555df9bd62SDavid Matlack
56892aff14SDavid Matlack /*
57892aff14SDavid Matlack * Generator for VFIO selftests fixture variants that replicate across all
58892aff14SDavid Matlack * possible IOMMU modes. Tests must define FIXTURE_VARIANT_ADD_IOMMU_MODE()
59892aff14SDavid Matlack * which should then use FIXTURE_VARIANT_ADD() to create the variant.
60892aff14SDavid Matlack */
61892aff14SDavid Matlack #define FIXTURE_VARIANT_ADD_ALL_IOMMU_MODES(...) \
620969c685SDavid Matlack FIXTURE_VARIANT_ADD_IOMMU_MODE(vfio_type1_iommu, ##__VA_ARGS__); \
63d1a17495SDavid Matlack FIXTURE_VARIANT_ADD_IOMMU_MODE(vfio_type1v2_iommu, ##__VA_ARGS__); \
64d1a17495SDavid Matlack FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd_compat_type1, ##__VA_ARGS__); \
6561cbfe50SDavid Matlack FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd_compat_type1v2, ##__VA_ARGS__); \
6661cbfe50SDavid Matlack FIXTURE_VARIANT_ADD_IOMMU_MODE(iommufd, ##__VA_ARGS__)
67892aff14SDavid Matlack
6819faf6fdSDavid Matlack struct vfio_pci_bar {
6919faf6fdSDavid Matlack struct vfio_region_info info;
7019faf6fdSDavid Matlack void *vaddr;
7119faf6fdSDavid Matlack };
7219faf6fdSDavid Matlack
73346cd58fSDavid Matlack typedef u64 iova_t;
74346cd58fSDavid Matlack
75346cd58fSDavid Matlack #define INVALID_IOVA UINT64_MAX
76346cd58fSDavid Matlack
77346cd58fSDavid Matlack struct vfio_dma_region {
78346cd58fSDavid Matlack struct list_head link;
79346cd58fSDavid Matlack void *vaddr;
80346cd58fSDavid Matlack iova_t iova;
81346cd58fSDavid Matlack u64 size;
82346cd58fSDavid Matlack };
83346cd58fSDavid Matlack
841b197032SDavid Matlack struct vfio_pci_device;
851b197032SDavid Matlack
861b197032SDavid Matlack struct vfio_pci_driver_ops {
871b197032SDavid Matlack const char *name;
881b197032SDavid Matlack
891b197032SDavid Matlack /**
901b197032SDavid Matlack * @probe() - Check if the driver supports the given device.
911b197032SDavid Matlack *
921b197032SDavid Matlack * Return: 0 on success, non-0 on failure.
931b197032SDavid Matlack */
941b197032SDavid Matlack int (*probe)(struct vfio_pci_device *device);
951b197032SDavid Matlack
961b197032SDavid Matlack /**
971b197032SDavid Matlack * @init() - Initialize the driver for @device.
981b197032SDavid Matlack *
991b197032SDavid Matlack * Must be called after device->driver.region has been initialized.
1001b197032SDavid Matlack */
1011b197032SDavid Matlack void (*init)(struct vfio_pci_device *device);
1021b197032SDavid Matlack
1031b197032SDavid Matlack /**
1041b197032SDavid Matlack * remove() - Deinitialize the driver for @device.
1051b197032SDavid Matlack */
1061b197032SDavid Matlack void (*remove)(struct vfio_pci_device *device);
1071b197032SDavid Matlack
1081b197032SDavid Matlack /**
1091b197032SDavid Matlack * memcpy_start() - Kick off @count repeated memcpy operations from
1101b197032SDavid Matlack * [@src, @src + @size) to [@dst, @dst + @size).
1111b197032SDavid Matlack *
1121b197032SDavid Matlack * Guarantees:
1131b197032SDavid Matlack * - The device will attempt DMA reads on [src, src + size).
1141b197032SDavid Matlack * - The device will attempt DMA writes on [dst, dst + size).
1151b197032SDavid Matlack * - The device will not generate any interrupts.
1161b197032SDavid Matlack *
1171b197032SDavid Matlack * memcpy_start() returns immediately, it does not wait for the
1181b197032SDavid Matlack * copies to complete.
1191b197032SDavid Matlack */
1201b197032SDavid Matlack void (*memcpy_start)(struct vfio_pci_device *device,
1211b197032SDavid Matlack iova_t src, iova_t dst, u64 size, u64 count);
1221b197032SDavid Matlack
1231b197032SDavid Matlack /**
1241b197032SDavid Matlack * memcpy_wait() - Wait until the memcpy operations started by
1251b197032SDavid Matlack * memcpy_start() have finished.
1261b197032SDavid Matlack *
1271b197032SDavid Matlack * Guarantees:
1281b197032SDavid Matlack * - All in-flight DMAs initiated by memcpy_start() are fully complete
1291b197032SDavid Matlack * before memcpy_wait() returns.
1301b197032SDavid Matlack *
1311b197032SDavid Matlack * Returns non-0 if the driver detects that an error occurred during the
1321b197032SDavid Matlack * memcpy, 0 otherwise.
1331b197032SDavid Matlack */
1341b197032SDavid Matlack int (*memcpy_wait)(struct vfio_pci_device *device);
1351b197032SDavid Matlack
1361b197032SDavid Matlack /**
1371b197032SDavid Matlack * send_msi() - Make the device send the MSI device->driver.msi.
1381b197032SDavid Matlack *
1391b197032SDavid Matlack * Guarantees:
1401b197032SDavid Matlack * - The device will send the MSI once.
1411b197032SDavid Matlack */
1421b197032SDavid Matlack void (*send_msi)(struct vfio_pci_device *device);
1431b197032SDavid Matlack };
1441b197032SDavid Matlack
1451b197032SDavid Matlack struct vfio_pci_driver {
1461b197032SDavid Matlack const struct vfio_pci_driver_ops *ops;
1471b197032SDavid Matlack bool initialized;
1481b197032SDavid Matlack bool memcpy_in_progress;
1491b197032SDavid Matlack
1501b197032SDavid Matlack /* Region to be used by the driver (e.g. for in-memory descriptors) */
1511b197032SDavid Matlack struct vfio_dma_region region;
1521b197032SDavid Matlack
1531b197032SDavid Matlack /* The maximum size that can be passed to memcpy_start(). */
1541b197032SDavid Matlack u64 max_memcpy_size;
1551b197032SDavid Matlack
1561b197032SDavid Matlack /* The maximum count that can be passed to memcpy_start(). */
1571b197032SDavid Matlack u64 max_memcpy_count;
1581b197032SDavid Matlack
1591b197032SDavid Matlack /* The MSI vector the device will signal in ops->send_msi(). */
1601b197032SDavid Matlack int msi;
1611b197032SDavid Matlack };
1621b197032SDavid Matlack
16319faf6fdSDavid Matlack struct vfio_pci_device {
16419faf6fdSDavid Matlack int fd;
1655df9bd62SDavid Matlack
1665df9bd62SDavid Matlack const struct vfio_iommu_mode *iommu_mode;
16719faf6fdSDavid Matlack int group_fd;
16819faf6fdSDavid Matlack int container_fd;
16919faf6fdSDavid Matlack
17061cbfe50SDavid Matlack int iommufd;
17161cbfe50SDavid Matlack u32 ioas_id;
17261cbfe50SDavid Matlack
17319faf6fdSDavid Matlack struct vfio_device_info info;
17419faf6fdSDavid Matlack struct vfio_region_info config_space;
17519faf6fdSDavid Matlack struct vfio_pci_bar bars[PCI_STD_NUM_BARS];
17619faf6fdSDavid Matlack
17719faf6fdSDavid Matlack struct vfio_irq_info msi_info;
17819faf6fdSDavid Matlack struct vfio_irq_info msix_info;
17919faf6fdSDavid Matlack
180346cd58fSDavid Matlack struct list_head dma_regions;
181346cd58fSDavid Matlack
18219faf6fdSDavid Matlack /* eventfds for MSI and MSI-x interrupts */
18319faf6fdSDavid Matlack int msi_eventfds[PCI_MSIX_FLAGS_QSIZE + 1];
1841b197032SDavid Matlack
1851b197032SDavid Matlack struct vfio_pci_driver driver;
18619faf6fdSDavid Matlack };
18719faf6fdSDavid Matlack
18819faf6fdSDavid Matlack /*
18919faf6fdSDavid Matlack * Return the BDF string of the device that the test should use.
19019faf6fdSDavid Matlack *
19119faf6fdSDavid Matlack * If a BDF string is provided by the user on the command line (as the last
19219faf6fdSDavid Matlack * element of argv[]), then this function will return that and decrement argc
19319faf6fdSDavid Matlack * by 1.
19419faf6fdSDavid Matlack *
19519faf6fdSDavid Matlack * Otherwise this function will attempt to use the environment variable
19619faf6fdSDavid Matlack * $VFIO_SELFTESTS_BDF.
19719faf6fdSDavid Matlack *
19819faf6fdSDavid Matlack * If BDF cannot be determined then the test will exit with KSFT_SKIP.
19919faf6fdSDavid Matlack */
20019faf6fdSDavid Matlack const char *vfio_selftests_get_bdf(int *argc, char *argv[]);
201118e073eSDavid Matlack const char *vfio_pci_get_cdev_path(const char *bdf);
20219faf6fdSDavid Matlack
2035df9bd62SDavid Matlack extern const char *default_iommu_mode;
2045df9bd62SDavid Matlack
2055df9bd62SDavid Matlack struct vfio_pci_device *vfio_pci_device_init(const char *bdf, const char *iommu_mode);
20619faf6fdSDavid Matlack void vfio_pci_device_cleanup(struct vfio_pci_device *device);
207a0fd0af5SJosh Hilke void vfio_pci_device_reset(struct vfio_pci_device *device);
20819faf6fdSDavid Matlack
209*16950b60SAlex Mastro int __vfio_pci_dma_map(struct vfio_pci_device *device,
210346cd58fSDavid Matlack struct vfio_dma_region *region);
211*16950b60SAlex Mastro int __vfio_pci_dma_unmap(struct vfio_pci_device *device,
212*16950b60SAlex Mastro struct vfio_dma_region *region,
213*16950b60SAlex Mastro u64 *unmapped);
214*16950b60SAlex Mastro int __vfio_pci_dma_unmap_all(struct vfio_pci_device *device, u64 *unmapped);
215*16950b60SAlex Mastro
vfio_pci_dma_map(struct vfio_pci_device * device,struct vfio_dma_region * region)216*16950b60SAlex Mastro static inline void vfio_pci_dma_map(struct vfio_pci_device *device,
217*16950b60SAlex Mastro struct vfio_dma_region *region)
218*16950b60SAlex Mastro {
219*16950b60SAlex Mastro VFIO_ASSERT_EQ(__vfio_pci_dma_map(device, region), 0);
220*16950b60SAlex Mastro }
221*16950b60SAlex Mastro
vfio_pci_dma_unmap(struct vfio_pci_device * device,struct vfio_dma_region * region)222*16950b60SAlex Mastro static inline void vfio_pci_dma_unmap(struct vfio_pci_device *device,
223*16950b60SAlex Mastro struct vfio_dma_region *region)
224*16950b60SAlex Mastro {
225*16950b60SAlex Mastro VFIO_ASSERT_EQ(__vfio_pci_dma_unmap(device, region, NULL), 0);
226*16950b60SAlex Mastro }
227*16950b60SAlex Mastro
vfio_pci_dma_unmap_all(struct vfio_pci_device * device)228*16950b60SAlex Mastro static inline void vfio_pci_dma_unmap_all(struct vfio_pci_device *device)
229*16950b60SAlex Mastro {
230*16950b60SAlex Mastro VFIO_ASSERT_EQ(__vfio_pci_dma_unmap_all(device, NULL), 0);
231*16950b60SAlex Mastro }
23219faf6fdSDavid Matlack
23319faf6fdSDavid Matlack void vfio_pci_config_access(struct vfio_pci_device *device, bool write,
23419faf6fdSDavid Matlack size_t config, size_t size, void *data);
23519faf6fdSDavid Matlack
23619faf6fdSDavid Matlack #define vfio_pci_config_read(_device, _offset, _type) ({ \
23719faf6fdSDavid Matlack _type __data; \
23819faf6fdSDavid Matlack vfio_pci_config_access((_device), false, _offset, sizeof(__data), &__data); \
23919faf6fdSDavid Matlack __data; \
24019faf6fdSDavid Matlack })
24119faf6fdSDavid Matlack
24219faf6fdSDavid Matlack #define vfio_pci_config_readb(_d, _o) vfio_pci_config_read(_d, _o, u8)
24319faf6fdSDavid Matlack #define vfio_pci_config_readw(_d, _o) vfio_pci_config_read(_d, _o, u16)
24419faf6fdSDavid Matlack #define vfio_pci_config_readl(_d, _o) vfio_pci_config_read(_d, _o, u32)
24519faf6fdSDavid Matlack
24619faf6fdSDavid Matlack #define vfio_pci_config_write(_device, _offset, _value, _type) do { \
24719faf6fdSDavid Matlack _type __data = (_value); \
24819faf6fdSDavid Matlack vfio_pci_config_access((_device), true, _offset, sizeof(_type), &__data); \
24919faf6fdSDavid Matlack } while (0)
25019faf6fdSDavid Matlack
25119faf6fdSDavid Matlack #define vfio_pci_config_writeb(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u8)
25219faf6fdSDavid Matlack #define vfio_pci_config_writew(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u16)
25319faf6fdSDavid Matlack #define vfio_pci_config_writel(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u32)
25419faf6fdSDavid Matlack
25519faf6fdSDavid Matlack void vfio_pci_irq_enable(struct vfio_pci_device *device, u32 index,
25619faf6fdSDavid Matlack u32 vector, int count);
25719faf6fdSDavid Matlack void vfio_pci_irq_disable(struct vfio_pci_device *device, u32 index);
25819faf6fdSDavid Matlack void vfio_pci_irq_trigger(struct vfio_pci_device *device, u32 index, u32 vector);
25919faf6fdSDavid Matlack
fcntl_set_nonblock(int fd)26092494780SDavid Matlack static inline void fcntl_set_nonblock(int fd)
26192494780SDavid Matlack {
26292494780SDavid Matlack int r;
26392494780SDavid Matlack
26492494780SDavid Matlack r = fcntl(fd, F_GETFL, 0);
26592494780SDavid Matlack VFIO_ASSERT_NE(r, -1, "F_GETFL failed for fd %d\n", fd);
26692494780SDavid Matlack
26792494780SDavid Matlack r = fcntl(fd, F_SETFL, r | O_NONBLOCK);
26892494780SDavid Matlack VFIO_ASSERT_NE(r, -1, "F_SETFL O_NONBLOCK failed for fd %d\n", fd);
26992494780SDavid Matlack }
27092494780SDavid Matlack
vfio_pci_msi_enable(struct vfio_pci_device * device,u32 vector,int count)27119faf6fdSDavid Matlack static inline void vfio_pci_msi_enable(struct vfio_pci_device *device,
27219faf6fdSDavid Matlack u32 vector, int count)
27319faf6fdSDavid Matlack {
27419faf6fdSDavid Matlack vfio_pci_irq_enable(device, VFIO_PCI_MSI_IRQ_INDEX, vector, count);
27519faf6fdSDavid Matlack }
27619faf6fdSDavid Matlack
vfio_pci_msi_disable(struct vfio_pci_device * device)27719faf6fdSDavid Matlack static inline void vfio_pci_msi_disable(struct vfio_pci_device *device)
27819faf6fdSDavid Matlack {
27919faf6fdSDavid Matlack vfio_pci_irq_disable(device, VFIO_PCI_MSI_IRQ_INDEX);
28019faf6fdSDavid Matlack }
28119faf6fdSDavid Matlack
vfio_pci_msix_enable(struct vfio_pci_device * device,u32 vector,int count)28219faf6fdSDavid Matlack static inline void vfio_pci_msix_enable(struct vfio_pci_device *device,
28319faf6fdSDavid Matlack u32 vector, int count)
28419faf6fdSDavid Matlack {
28519faf6fdSDavid Matlack vfio_pci_irq_enable(device, VFIO_PCI_MSIX_IRQ_INDEX, vector, count);
28619faf6fdSDavid Matlack }
28719faf6fdSDavid Matlack
vfio_pci_msix_disable(struct vfio_pci_device * device)28819faf6fdSDavid Matlack static inline void vfio_pci_msix_disable(struct vfio_pci_device *device)
28919faf6fdSDavid Matlack {
29019faf6fdSDavid Matlack vfio_pci_irq_disable(device, VFIO_PCI_MSIX_IRQ_INDEX);
29119faf6fdSDavid Matlack }
29219faf6fdSDavid Matlack
293346cd58fSDavid Matlack iova_t __to_iova(struct vfio_pci_device *device, void *vaddr);
294346cd58fSDavid Matlack iova_t to_iova(struct vfio_pci_device *device, void *vaddr);
295346cd58fSDavid Matlack
vfio_pci_device_match(struct vfio_pci_device * device,u16 vendor_id,u16 device_id)29650d8fe80SDavid Matlack static inline bool vfio_pci_device_match(struct vfio_pci_device *device,
29750d8fe80SDavid Matlack u16 vendor_id, u16 device_id)
29850d8fe80SDavid Matlack {
29950d8fe80SDavid Matlack return (vendor_id == vfio_pci_config_readw(device, PCI_VENDOR_ID)) &&
30050d8fe80SDavid Matlack (device_id == vfio_pci_config_readw(device, PCI_DEVICE_ID));
30150d8fe80SDavid Matlack }
30250d8fe80SDavid Matlack
3031b197032SDavid Matlack void vfio_pci_driver_probe(struct vfio_pci_device *device);
3041b197032SDavid Matlack void vfio_pci_driver_init(struct vfio_pci_device *device);
3051b197032SDavid Matlack void vfio_pci_driver_remove(struct vfio_pci_device *device);
3061b197032SDavid Matlack int vfio_pci_driver_memcpy(struct vfio_pci_device *device,
3071b197032SDavid Matlack iova_t src, iova_t dst, u64 size);
3081b197032SDavid Matlack void vfio_pci_driver_memcpy_start(struct vfio_pci_device *device,
3091b197032SDavid Matlack iova_t src, iova_t dst, u64 size,
3101b197032SDavid Matlack u64 count);
3111b197032SDavid Matlack int vfio_pci_driver_memcpy_wait(struct vfio_pci_device *device);
3121b197032SDavid Matlack void vfio_pci_driver_send_msi(struct vfio_pci_device *device);
3131b197032SDavid Matlack
31419faf6fdSDavid Matlack #endif /* SELFTESTS_VFIO_LIB_INCLUDE_VFIO_UTIL_H */
315