xref: /linux/tools/testing/selftests/vfio/lib/include/vfio_util.h (revision 19faf6fd969c21589b6dd40c35255e4d00d427f8)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #ifndef SELFTESTS_VFIO_LIB_INCLUDE_VFIO_UTIL_H
3 #define SELFTESTS_VFIO_LIB_INCLUDE_VFIO_UTIL_H
4 
5 #include <string.h>
6 #include <linux/vfio.h>
7 #include <linux/list.h>
8 #include <linux/pci_regs.h>
9 
10 #include "../../../kselftest.h"
11 
12 #define VFIO_LOG_AND_EXIT(...) do {		\
13 	fprintf(stderr, "  " __VA_ARGS__);	\
14 	fprintf(stderr, "\n");			\
15 	exit(KSFT_FAIL);			\
16 } while (0)
17 
18 #define VFIO_ASSERT_OP(_lhs, _rhs, _op, ...) do {				\
19 	typeof(_lhs) __lhs = (_lhs);						\
20 	typeof(_rhs) __rhs = (_rhs);						\
21 										\
22 	if (__lhs _op __rhs)							\
23 		break;								\
24 										\
25 	fprintf(stderr, "%s:%u: Assertion Failure\n\n", __FILE__, __LINE__);	\
26 	fprintf(stderr, "  Expression: " #_lhs " " #_op " " #_rhs "\n");	\
27 	fprintf(stderr, "  Observed: %#lx %s %#lx\n",				\
28 			(u64)__lhs, #_op, (u64)__rhs);				\
29 	fprintf(stderr, "  [errno: %d - %s]\n", errno, strerror(errno));	\
30 	VFIO_LOG_AND_EXIT(__VA_ARGS__);						\
31 } while (0)
32 
33 #define VFIO_ASSERT_EQ(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, ==, ##__VA_ARGS__)
34 #define VFIO_ASSERT_NE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, !=, ##__VA_ARGS__)
35 #define VFIO_ASSERT_LT(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, <, ##__VA_ARGS__)
36 #define VFIO_ASSERT_LE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, <=, ##__VA_ARGS__)
37 #define VFIO_ASSERT_GT(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, >, ##__VA_ARGS__)
38 #define VFIO_ASSERT_GE(_a, _b, ...) VFIO_ASSERT_OP(_a, _b, >=, ##__VA_ARGS__)
39 #define VFIO_ASSERT_TRUE(_a, ...) VFIO_ASSERT_NE(false, (_a), ##__VA_ARGS__)
40 #define VFIO_ASSERT_FALSE(_a, ...) VFIO_ASSERT_EQ(false, (_a), ##__VA_ARGS__)
41 #define VFIO_ASSERT_NULL(_a, ...) VFIO_ASSERT_EQ(NULL, _a, ##__VA_ARGS__)
42 #define VFIO_ASSERT_NOT_NULL(_a, ...) VFIO_ASSERT_NE(NULL, _a, ##__VA_ARGS__)
43 
44 #define VFIO_FAIL(_fmt, ...) do {				\
45 	fprintf(stderr, "%s:%u: FAIL\n\n", __FILE__, __LINE__);	\
46 	VFIO_LOG_AND_EXIT(_fmt, ##__VA_ARGS__);			\
47 } while (0)
48 
49 struct vfio_pci_bar {
50 	struct vfio_region_info info;
51 	void *vaddr;
52 };
53 
54 struct vfio_pci_device {
55 	int fd;
56 	int group_fd;
57 	int container_fd;
58 
59 	struct vfio_device_info info;
60 	struct vfio_region_info config_space;
61 	struct vfio_pci_bar bars[PCI_STD_NUM_BARS];
62 
63 	struct vfio_irq_info msi_info;
64 	struct vfio_irq_info msix_info;
65 
66 	/* eventfds for MSI and MSI-x interrupts */
67 	int msi_eventfds[PCI_MSIX_FLAGS_QSIZE + 1];
68 };
69 
70 /*
71  * Return the BDF string of the device that the test should use.
72  *
73  * If a BDF string is provided by the user on the command line (as the last
74  * element of argv[]), then this function will return that and decrement argc
75  * by 1.
76  *
77  * Otherwise this function will attempt to use the environment variable
78  * $VFIO_SELFTESTS_BDF.
79  *
80  * If BDF cannot be determined then the test will exit with KSFT_SKIP.
81  */
82 const char *vfio_selftests_get_bdf(int *argc, char *argv[]);
83 
84 struct vfio_pci_device *vfio_pci_device_init(const char *bdf, int iommu_type);
85 void vfio_pci_device_cleanup(struct vfio_pci_device *device);
86 
87 void vfio_pci_dma_map(struct vfio_pci_device *device, u64 iova, u64 size,
88 		      void *vaddr);
89 void vfio_pci_dma_unmap(struct vfio_pci_device *device, u64 iova, u64 size);
90 
91 void vfio_pci_config_access(struct vfio_pci_device *device, bool write,
92 			    size_t config, size_t size, void *data);
93 
94 #define vfio_pci_config_read(_device, _offset, _type) ({			    \
95 	_type __data;								    \
96 	vfio_pci_config_access((_device), false, _offset, sizeof(__data), &__data); \
97 	__data;									    \
98 })
99 
100 #define vfio_pci_config_readb(_d, _o) vfio_pci_config_read(_d, _o, u8)
101 #define vfio_pci_config_readw(_d, _o) vfio_pci_config_read(_d, _o, u16)
102 #define vfio_pci_config_readl(_d, _o) vfio_pci_config_read(_d, _o, u32)
103 
104 #define vfio_pci_config_write(_device, _offset, _value, _type) do {		  \
105 	_type __data = (_value);						  \
106 	vfio_pci_config_access((_device), true, _offset, sizeof(_type), &__data); \
107 } while (0)
108 
109 #define vfio_pci_config_writeb(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u8)
110 #define vfio_pci_config_writew(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u16)
111 #define vfio_pci_config_writel(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u32)
112 
113 void vfio_pci_irq_enable(struct vfio_pci_device *device, u32 index,
114 			 u32 vector, int count);
115 void vfio_pci_irq_disable(struct vfio_pci_device *device, u32 index);
116 void vfio_pci_irq_trigger(struct vfio_pci_device *device, u32 index, u32 vector);
117 
118 static inline void vfio_pci_msi_enable(struct vfio_pci_device *device,
119 				       u32 vector, int count)
120 {
121 	vfio_pci_irq_enable(device, VFIO_PCI_MSI_IRQ_INDEX, vector, count);
122 }
123 
124 static inline void vfio_pci_msi_disable(struct vfio_pci_device *device)
125 {
126 	vfio_pci_irq_disable(device, VFIO_PCI_MSI_IRQ_INDEX);
127 }
128 
129 static inline void vfio_pci_msix_enable(struct vfio_pci_device *device,
130 					u32 vector, int count)
131 {
132 	vfio_pci_irq_enable(device, VFIO_PCI_MSIX_IRQ_INDEX, vector, count);
133 }
134 
135 static inline void vfio_pci_msix_disable(struct vfio_pci_device *device)
136 {
137 	vfio_pci_irq_disable(device, VFIO_PCI_MSIX_IRQ_INDEX);
138 }
139 
140 #endif /* SELFTESTS_VFIO_LIB_INCLUDE_VFIO_UTIL_H */
141