xref: /linux/tools/testing/selftests/vfio/lib/include/vfio_util.h (revision 346cd58f1fb588f8ff193d76cf0bb455446ace03)
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 typedef u64 iova_t;
55 
56 #define INVALID_IOVA UINT64_MAX
57 
58 struct vfio_dma_region {
59 	struct list_head link;
60 	void *vaddr;
61 	iova_t iova;
62 	u64 size;
63 };
64 
65 struct vfio_pci_device {
66 	int fd;
67 	int group_fd;
68 	int container_fd;
69 
70 	struct vfio_device_info info;
71 	struct vfio_region_info config_space;
72 	struct vfio_pci_bar bars[PCI_STD_NUM_BARS];
73 
74 	struct vfio_irq_info msi_info;
75 	struct vfio_irq_info msix_info;
76 
77 	struct list_head dma_regions;
78 
79 	/* eventfds for MSI and MSI-x interrupts */
80 	int msi_eventfds[PCI_MSIX_FLAGS_QSIZE + 1];
81 };
82 
83 /*
84  * Return the BDF string of the device that the test should use.
85  *
86  * If a BDF string is provided by the user on the command line (as the last
87  * element of argv[]), then this function will return that and decrement argc
88  * by 1.
89  *
90  * Otherwise this function will attempt to use the environment variable
91  * $VFIO_SELFTESTS_BDF.
92  *
93  * If BDF cannot be determined then the test will exit with KSFT_SKIP.
94  */
95 const char *vfio_selftests_get_bdf(int *argc, char *argv[]);
96 
97 struct vfio_pci_device *vfio_pci_device_init(const char *bdf, int iommu_type);
98 void vfio_pci_device_cleanup(struct vfio_pci_device *device);
99 void vfio_pci_device_reset(struct vfio_pci_device *device);
100 
101 void vfio_pci_dma_map(struct vfio_pci_device *device,
102 		      struct vfio_dma_region *region);
103 void vfio_pci_dma_unmap(struct vfio_pci_device *device,
104 			struct vfio_dma_region *region);
105 
106 void vfio_pci_config_access(struct vfio_pci_device *device, bool write,
107 			    size_t config, size_t size, void *data);
108 
109 #define vfio_pci_config_read(_device, _offset, _type) ({			    \
110 	_type __data;								    \
111 	vfio_pci_config_access((_device), false, _offset, sizeof(__data), &__data); \
112 	__data;									    \
113 })
114 
115 #define vfio_pci_config_readb(_d, _o) vfio_pci_config_read(_d, _o, u8)
116 #define vfio_pci_config_readw(_d, _o) vfio_pci_config_read(_d, _o, u16)
117 #define vfio_pci_config_readl(_d, _o) vfio_pci_config_read(_d, _o, u32)
118 
119 #define vfio_pci_config_write(_device, _offset, _value, _type) do {		  \
120 	_type __data = (_value);						  \
121 	vfio_pci_config_access((_device), true, _offset, sizeof(_type), &__data); \
122 } while (0)
123 
124 #define vfio_pci_config_writeb(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u8)
125 #define vfio_pci_config_writew(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u16)
126 #define vfio_pci_config_writel(_d, _o, _v) vfio_pci_config_write(_d, _o, _v, u32)
127 
128 void vfio_pci_irq_enable(struct vfio_pci_device *device, u32 index,
129 			 u32 vector, int count);
130 void vfio_pci_irq_disable(struct vfio_pci_device *device, u32 index);
131 void vfio_pci_irq_trigger(struct vfio_pci_device *device, u32 index, u32 vector);
132 
133 static inline void vfio_pci_msi_enable(struct vfio_pci_device *device,
134 				       u32 vector, int count)
135 {
136 	vfio_pci_irq_enable(device, VFIO_PCI_MSI_IRQ_INDEX, vector, count);
137 }
138 
139 static inline void vfio_pci_msi_disable(struct vfio_pci_device *device)
140 {
141 	vfio_pci_irq_disable(device, VFIO_PCI_MSI_IRQ_INDEX);
142 }
143 
144 static inline void vfio_pci_msix_enable(struct vfio_pci_device *device,
145 					u32 vector, int count)
146 {
147 	vfio_pci_irq_enable(device, VFIO_PCI_MSIX_IRQ_INDEX, vector, count);
148 }
149 
150 static inline void vfio_pci_msix_disable(struct vfio_pci_device *device)
151 {
152 	vfio_pci_irq_disable(device, VFIO_PCI_MSIX_IRQ_INDEX);
153 }
154 
155 iova_t __to_iova(struct vfio_pci_device *device, void *vaddr);
156 iova_t to_iova(struct vfio_pci_device *device, void *vaddr);
157 
158 #endif /* SELFTESTS_VFIO_LIB_INCLUDE_VFIO_UTIL_H */
159