aboutsummaryrefslogtreecommitdiffstats
path: root/lib/librte_eal/common/include/rte_vfio.h
blob: cae96fab90f6af923ea6ac2d4d20c78c2bffb9fd (plain)
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
/* SPDX-License-Identifier: BSD-3-Clause
 * Copyright(c) 2017 6WIND S.A.
 */

#ifndef _RTE_VFIO_H_
#define _RTE_VFIO_H_

/**
 * @file
 * RTE VFIO. This library provides various VFIO related utility functions.
 */

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>

/*
 * determine if VFIO is present on the system
 */
#if !defined(VFIO_PRESENT) && defined(RTE_EAL_VFIO)
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
#define VFIO_PRESENT
#endif /* kernel version >= 3.6.0 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
#define HAVE_VFIO_DEV_REQ_INTERFACE
#endif /* kernel version >= 4.0.0 */
#endif /* RTE_EAL_VFIO */

#ifdef VFIO_PRESENT

#include <linux/vfio.h>

#define VFIO_DIR "/dev/vfio"
#define VFIO_CONTAINER_PATH "/dev/vfio/vfio"
#define VFIO_GROUP_FMT "/dev/vfio/%u"
#define VFIO_NOIOMMU_GROUP_FMT "/dev/vfio/noiommu-%u"
#define VFIO_GET_REGION_ADDR(x) ((uint64_t) x << 40ULL)
#define VFIO_GET_REGION_IDX(x) (x >> 40)
#define VFIO_NOIOMMU_MODE      \
	"/sys/module/vfio/parameters/enable_unsafe_noiommu_mode"

/* NOIOMMU is defined from kernel version 4.5 onwards */
#ifdef VFIO_NOIOMMU_IOMMU
#define RTE_VFIO_NOIOMMU VFIO_NOIOMMU_IOMMU
#else
#define RTE_VFIO_NOIOMMU 8
#endif

/*
 * capabilities are only supported on kernel 4.6+. there were also some API
 * changes as well, so add a macro to get cap offset.
 */
#ifdef VFIO_REGION_INFO_FLAG_CAPS
#define RTE_VFIO_INFO_FLAG_CAPS VFIO_REGION_INFO_FLAG_CAPS
#define VFIO_CAP_OFFSET(x) (x->cap_offset)
#else
#define RTE_VFIO_INFO_FLAG_CAPS (1 << 3)
#define VFIO_CAP_OFFSET(x) (x->resv)
struct vfio_info_cap_header {
	uint16_t id;
	uint16_t version;
	uint32_t next;
};
#endif

/* kernels 4.16+ can map BAR containing MSI-X table */
#ifdef VFIO_REGION_INFO_CAP_MSIX_MAPPABLE
#define RTE_VFIO_CAP_MSIX_MAPPABLE VFIO_REGION_INFO_CAP_MSIX_MAPPABLE
#else
#define RTE_VFIO_CAP_MSIX_MAPPABLE 3
#endif

#else /* not VFIO_PRESENT */

/* we don't need an actual definition, only pointer is used */
struct vfio_device_info;

#endif /* VFIO_PRESENT */

/**
 * Setup vfio_cfg for the device identified by its address.
 * It discovers the configured I/O MMU groups or sets a new one for the device.
 * If a new groups is assigned, the DMA mapping is performed.
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @param sysfs_base
 *   sysfs path prefix.
 *
 * @param dev_addr
 *   device location.
 *
 * @param vfio_dev_fd
 *   VFIO fd.
 *
 * @param device_info
 *   Device information.
 *
 * @return
 *   0 on success.
 *   <0 on failure.
 *   >1 if the device cannot be managed this way.
 */
int rte_vfio_setup_device(const char *sysfs_base, const char *dev_addr,
		int *vfio_dev_fd, struct vfio_device_info *device_info);

/**
 * Release a device mapped to a VFIO-managed I/O MMU group.
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @param sysfs_base
 *   sysfs path prefix.
 *
 * @param dev_addr
 *   device location.
 *
 * @param fd
 *   VFIO fd.
 *
 * @return
 *   0 on success.
 *   <0 on failure.
 */
int rte_vfio_release_device(const char *sysfs_base, const char *dev_addr, int fd);

/**
 * Enable a VFIO-related kmod.
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @param modname
 *   kernel module name.
 *
 * @return
 *   0 on success.
 *   <0 on failure.
 */
int rte_vfio_enable(const char *modname);

/**
 * Check whether a VFIO-related kmod is enabled.
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @param modname
 *   kernel module name.
 *
 * @return
 *   !0 if true.
 *   0 otherwise.
 */
int rte_vfio_is_enabled(const char *modname);

/**
 * Whether VFIO NOIOMMU mode is enabled.
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @return
 *   !0 if true.
 *   0 otherwise.
 */
int rte_vfio_noiommu_is_enabled(void);

/**
 * Remove group fd from internal VFIO group fd array/
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @param vfio_group_fd
 *   VFIO Grouup FD.
 *
 * @return
 *   0 on success.
 *   <0 on failure.
 */
int
rte_vfio_clear_group(int vfio_group_fd);

/**
 * Map memory region for use with VFIO.
 *
 * @note Require at least one device to be attached at the time of
 *       mapping. DMA maps done via this API will only apply to default
 *       container and will not apply to any of the containers created
 *       via rte_vfio_container_create().
 *
 * @param vaddr
 *   Starting virtual address of memory to be mapped.
 *
 * @param iova
 *   Starting IOVA address of memory to be mapped.
 *
 * @param len
 *   Length of memory segment being mapped.
 *
 * @return
 *   0 if success.
 *   -1 on error.
 */
int
rte_vfio_dma_map(uint64_t vaddr, uint64_t iova, uint64_t len);


/**
 * Unmap memory region from VFIO.
 *
 * @param vaddr
 *   Starting virtual address of memory to be unmapped.
 *
 * @param iova
 *   Starting IOVA address of memory to be unmapped.
 *
 * @param len
 *   Length of memory segment being unmapped.
 *
 * @return
 *   0 if success.
 *   -1 on error.
 */

int
rte_vfio_dma_unmap(uint64_t vaddr, uint64_t iova, uint64_t len);
/**
 * Parse IOMMU group number for a device
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @param sysfs_base
 *   sysfs path prefix.
 *
 * @param dev_addr
 *   device location.
 *
 * @param iommu_group_num
 *   iommu group number
 *
 * @return
 *  >0 on success
 *   0 for non-existent group or VFIO
 *  <0 for errors
 */
int
rte_vfio_get_group_num(const char *sysfs_base,
		      const char *dev_addr, int *iommu_group_num);

/**
 * Open a new VFIO container fd
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @return
 *  > 0 container fd
 *  < 0 for errors
 */
int
rte_vfio_get_container_fd(void);

/**
 * Open VFIO group fd or get an existing one
 *
 * This function is only relevant to linux and will return
 * an error on BSD.
 *
 * @param iommu_group_num
 *   iommu group number
 *
 * @return
 *  > 0 group fd
 *  < 0 for errors
 */
int
rte_vfio_get_group_fd(int iommu_group_num);

/**
 * Create a new container for device binding.
 *
 * @note Any newly allocated DPDK memory will not be mapped into these
 *       containers by default, user needs to manage DMA mappings for
 *       any container created by this API.
 *
 * @return
 *   the container fd if successful
 *   <0 if failed
 */
int
rte_vfio_container_create(void);

/**
 * Destroy the container, unbind all vfio groups within it.
 *
 * @param container_fd
 *   the container fd to destroy
 *
 * @return
 *    0 if successful
 *   <0 if failed
 */
int
rte_vfio_container_destroy(int container_fd);

/**
 * Bind a IOMMU group to a container.
 *
 * @param container_fd
 *   the container's fd
 *
 * @param iommu_group_num
 *   the iommu group number to bind to container
 *
 * @return
 *   group fd if successful
 *   <0 if failed
 */
int
rte_vfio_container_group_bind(int container_fd, int iommu_group_num);

/**
 * Unbind a IOMMU group from a container.
 *
 * @param container_fd
 *   the container fd of container
 *
 * @param iommu_group_num
 *   the iommu group number to delete from container
 *
 * @return
 *    0 if successful
 *   <0 if failed
 */
int
rte_vfio_container_group_unbind(int container_fd, int iommu_group_num);

/**
 * Perform DMA mapping for devices in a container.
 *
 * @param container_fd
 *   the specified container fd
 *
 * @param vaddr
 *   Starting virtual address of memory to be mapped.
 *
 * @param iova
 *   Starting IOVA address of memory to be mapped.
 *
 * @param len
 *   Length of memory segment being mapped.
 *
 * @return
 *    0 if successful
 *   <0 if failed
 */
int
rte_vfio_container_dma_map(int container_fd, uint64_t vaddr,
		uint64_t iova, uint64_t len);

/**
 * Perform DMA unmapping for devices in a container.
 *
 * @param container_fd
 *   the specified container fd
 *
 * @param vaddr
 *   Starting virtual address of memory to be unmapped.
 *
 * @param iova
 *   Starting IOVA address of memory to be unmapped.
 *
 * @param len
 *   Length of memory segment being unmapped.
 *
 * @return
 *    0 if successful
 *   <0 if failed
 */
int
rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr,
		uint64_t iova, uint64_t len);

#ifdef __cplusplus
}
#endif

#endif /* _RTE_VFIO_H_ */