extern "C" {
#endif
+#include <stdint.h>
+
/*
* determine if VFIO is present on the system
*/
#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
#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 */
#endif /* VFIO_PRESENT */
+#define RTE_VFIO_DEFAULT_CONTAINER_FD (-1)
+
/**
* 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.
* an error on BSD.
*
* @param vfio_group_fd
- * VFIO Grouup FD.
+ * VFIO Group FD.
*
* @return
* 0 on success.
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_experimental
-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_experimental
-rte_vfio_dma_unmap(uint64_t vaddr, uint64_t iova, uint64_t len);
/**
* Parse IOMMU group number for a device
*
* 0 for non-existent group or VFIO
* <0 for errors
*/
-int __rte_experimental
+int
rte_vfio_get_group_num(const char *sysfs_base,
const char *dev_addr, int *iommu_group_num);
/**
- * Open VFIO container fd or get an existing one
+ * Open a new VFIO container fd
*
* This function is only relevant to linux and will return
* an error on BSD.
* > 0 container fd
* < 0 for errors
*/
-int __rte_experimental
+int
rte_vfio_get_container_fd(void);
/**
* > 0 group fd
* < 0 for errors
*/
-int __rte_experimental
+int
rte_vfio_get_group_fd(int iommu_group_num);
/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
* 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.
*
+ * @note When creating containers using this API, the container will only be
+ * available in the process that has created it. Sharing containers and
+ * devices between multiple processes is not supported.
+ *
* @return
* the container fd if successful
* <0 if failed
*/
-int __rte_experimental
+int
rte_vfio_container_create(void);
/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
* Destroy the container, unbind all vfio groups within it.
*
* @param container_fd
* 0 if successful
* <0 if failed
*/
-int __rte_experimental
+int
rte_vfio_container_destroy(int container_fd);
/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
* Bind a IOMMU group to a container.
*
* @param container_fd
* group fd if successful
* <0 if failed
*/
-int __rte_experimental
+int
rte_vfio_container_group_bind(int container_fd, int iommu_group_num);
/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
* Unbind a IOMMU group from a container.
*
* @param container_fd
* 0 if successful
* <0 if failed
*/
-int __rte_experimental
+int
rte_vfio_container_group_unbind(int container_fd, int iommu_group_num);
/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
* Perform DMA mapping for devices in a container.
*
* @param container_fd
- * the specified container fd
+ * the specified container fd. Use RTE_VFIO_DEFAULT_CONTAINER_FD to
+ * use the default container.
*
* @param vaddr
* Starting virtual address of memory to be mapped.
* 0 if successful
* <0 if failed
*/
-int __rte_experimental
+int
rte_vfio_container_dma_map(int container_fd, uint64_t vaddr,
uint64_t iova, uint64_t len);
/**
- * @warning
- * @b EXPERIMENTAL: this API may change, or be removed, without prior notice
- *
* Perform DMA unmapping for devices in a container.
*
* @param container_fd
- * the specified container fd
+ * the specified container fd. Use RTE_VFIO_DEFAULT_CONTAINER_FD to
+ * use the default container.
*
* @param vaddr
* Starting virtual address of memory to be unmapped.
* 0 if successful
* <0 if failed
*/
-int __rte_experimental
+int
rte_vfio_container_dma_unmap(int container_fd, uint64_t vaddr,
uint64_t iova, uint64_t len);