From a68effe70977348e94a3c4a0f57293c873c6ff69 Mon Sep 17 00:00:00 2001 From: Ben Walker Date: Tue, 26 Nov 2019 12:39:07 -0700 Subject: [PATCH] env_dpdk: Detect DPDK's iova mode when programming the IOMMU If DPDK is using virtual addresses, we should use virtual addresses. If DPDK is using physical addresses, we should use physical addresses. This way there can never be a conflict and everything is consistent. Change-Id: Ie4b0e885e9a52dd6cbc81000a87908102a9771cb Signed-off-by: Ben Walker Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/475928 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Shuhei Matsumoto --- lib/env_dpdk/memory.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/env_dpdk/memory.c b/lib/env_dpdk/memory.c index 33e56fcc1..ebdae6991 100644 --- a/lib/env_dpdk/memory.c +++ b/lib/env_dpdk/memory.c @@ -1013,13 +1013,8 @@ spdk_vtophys_notify(void *cb_ctx, struct spdk_mem_map *map, if (paddr == SPDK_VTOPHYS_ERROR) { /* This is not an address that DPDK is managing. */ #if SPDK_VFIO_ENABLED - if (spdk_iommu_is_enabled()) { - /* We'll use the virtual address as the iova. DPDK - * currently uses physical addresses as the iovas (or counts - * up from 0 if it can't get physical addresses), so - * the range of user space virtual addresses and physical - * addresses will never overlap. - */ + if (spdk_iommu_is_enabled() && rte_eal_get_configuration()->iova_mode == RTE_IOVA_VA) { + /* We'll use the virtual address as the iova to match DPDK. */ paddr = (uint64_t)vaddr; rc = vtophys_iommu_map_dma((uint64_t)vaddr, paddr, len); if (rc) { @@ -1071,6 +1066,16 @@ spdk_vtophys_notify(void *cb_ctx, struct spdk_mem_map *map, DEBUG_PRINT("invalid paddr 0x%" PRIx64 " - must be 2MB aligned\n", paddr); return -EINVAL; } +#if SPDK_VFIO_ENABLED + /* If the IOMMU is on, but DPDK is using iova-mode=pa, we want to register this memory + * with the IOMMU using the physical address to match. */ + if (spdk_iommu_is_enabled()) { + rc = vtophys_iommu_map_dma((uint64_t)vaddr, paddr, VALUE_2MB); + if (rc) { + return -EFAULT; + } + } +#endif rc = spdk_mem_map_set_translation(map, (uint64_t)vaddr, VALUE_2MB, paddr); if (rc != 0) {