Get iommu class of PCI device on the bus and returns preferred iova mapping mode for that bus.
IOVA mapping scheme for linuxapp case: - uio/uio_generic/vfio_noiommu --> default i.e.. (RTE_IOVA_PA) - vfio --> RTE_IOVA_VA. - In case of no device attached to any driver, return RTE_IOVA_DC. Signed-off-by: Santosh Shukla <santosh.shu...@caviumnetworks.com> Signed-off-by: Jerin Jacob <jerin.ja...@caviumnetworks.com> --- lib/librte_eal/linuxapp/eal/eal_pci.c | 38 +++++++++++++++++++++++++ lib/librte_eal/linuxapp/eal/eal_vfio.c | 23 +++++++++++++++ lib/librte_eal/linuxapp/eal/eal_vfio.h | 4 +++ lib/librte_eal/linuxapp/eal/rte_eal_version.map | 7 +++++ 4 files changed, 72 insertions(+) diff --git a/lib/librte_eal/linuxapp/eal/eal_pci.c b/lib/librte_eal/linuxapp/eal/eal_pci.c index 595622b21..2772e883e 100644 --- a/lib/librte_eal/linuxapp/eal/eal_pci.c +++ b/lib/librte_eal/linuxapp/eal/eal_pci.c @@ -45,6 +45,7 @@ #include "eal_filesystem.h" #include "eal_private.h" #include "eal_pci_init.h" +#include "eal_vfio.h" /** * @file @@ -488,6 +489,43 @@ rte_pci_scan(void) return -1; } +/* + * Get iommu class of PCI devices on the bus. + * Check that those devices are attached to iommu driver. + * If attached then return iova_va or iova_pa mode, else + * return with dont_care(_DC). + */ +enum rte_iova_mode +rte_pci_get_iommu_class(void) +{ + struct rte_pci_device *dev = NULL; + int ret = RTE_IOVA_DC; + + TAILQ_FOREACH(dev, &rte_pci_bus.device_list, next) { + + if (dev->kdrv == RTE_KDRV_UNKNOWN || + dev->kdrv == RTE_KDRV_NONE) + continue; + + if (dev->kdrv != RTE_KDRV_VFIO) { + ret = RTE_IOVA_PA; + return ret; + } + + ret = RTE_IOVA_VA; + } + + /* In case of iova_va, check for vfio_noiommu mode */ + if (ret == RTE_IOVA_VA) { +#ifdef VFIO_PRESENT + if (vfio_noiommu_is_enabled() == 1) +#endif + ret = RTE_IOVA_PA; + } + + return ret; +} + /* Read PCI config space. */ int rte_pci_read_config(const struct rte_pci_device *device, void *buf, size_t len, off_t offset) diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio.c b/lib/librte_eal/linuxapp/eal/eal_vfio.c index 946df7e31..04914406f 100644 --- a/lib/librte_eal/linuxapp/eal/eal_vfio.c +++ b/lib/librte_eal/linuxapp/eal/eal_vfio.c @@ -816,4 +816,27 @@ vfio_noiommu_dma_map(int __rte_unused vfio_container_fd) return 0; } +int +vfio_noiommu_is_enabled(void) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0) + return -1; +#else + int fd, ret, cnt __rte_unused; + char c; + + ret = -1; + fd = open(VFIO_NOIOMMU_MODE, O_RDONLY); + if (fd < 0) + return -1; + + cnt = read(fd, &c, 1); + if (c == 'Y') + ret = 1; + + close(fd); + return ret; +#endif +} + #endif diff --git a/lib/librte_eal/linuxapp/eal/eal_vfio.h b/lib/librte_eal/linuxapp/eal/eal_vfio.h index 5ff63e5d7..26ea8e119 100644 --- a/lib/librte_eal/linuxapp/eal/eal_vfio.h +++ b/lib/librte_eal/linuxapp/eal/eal_vfio.h @@ -150,6 +150,8 @@ struct vfio_config { #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" /* DMA mapping function prototype. * Takes VFIO container fd as a parameter. @@ -210,6 +212,8 @@ int pci_vfio_is_enabled(void); int vfio_mp_sync_setup(void); +int vfio_noiommu_is_enabled(void); + #define SOCKET_REQ_CONTAINER 0x100 #define SOCKET_REQ_GROUP 0x200 #define SOCKET_CLR_GROUP 0x300 diff --git a/lib/librte_eal/linuxapp/eal/rte_eal_version.map b/lib/librte_eal/linuxapp/eal/rte_eal_version.map index 670bab3a5..2cea7c272 100644 --- a/lib/librte_eal/linuxapp/eal/rte_eal_version.map +++ b/lib/librte_eal/linuxapp/eal/rte_eal_version.map @@ -198,3 +198,10 @@ DPDK_17.05 { vfio_get_group_no; } DPDK_17.02; + +DPDK_17.08 { + global: + + rte_pci_get_iommu_class; + +} DPDK_17.05; -- 2.11.0