From b3db2a65eacd8e0b5d93cfcb79a4faa4ac003a08 Mon Sep 17 00:00:00 2001 From: Darek Stojaczyk Date: Fri, 9 Nov 2018 05:26:22 +0100 Subject: [PATCH] vfio: don't use VFIO when IOMMU is disabled Previously we used VFIO if only the vfio-pci kernel module was loaded, which is different from what our setup.sh script did. On a fairly usual system configuration, setup.sh could have bound devices to UIO, but SPDK would still try to map memory to an (empty) DPDK VFIO container just because its fd was available. That would fail obviously. setup.sh checks for IOMMU presence in order to use vfio-pci and SPDK should probably do the same. We could check the kernel driver of each attached PCI device, but there's no chance right now of supporting both UIO and VFIO devices at the same time with IOMMU passthrough. That's not a reasonable configuration anyway. To keep things simple, we just add a single check on vtophys initialization. Fixes #462 Change-Id: Ica653f117743be322291a1b7e37ed00e34ef5035 Signed-off-by: Darek Stojaczyk Reviewed-on: https://review.gerrithub.io/432518 Tested-by: SPDK CI Jenkins Reviewed-by: Ben Walker Reviewed-by: Jim Harris Reviewed-by: --- lib/env_dpdk/vtophys.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/lib/env_dpdk/vtophys.c b/lib/env_dpdk/vtophys.c index 00e8bb6d8b..908ad31661 100644 --- a/lib/env_dpdk/vtophys.c +++ b/lib/env_dpdk/vtophys.c @@ -445,6 +445,27 @@ spdk_vfio_enabled(void) #endif } +/* Check if IOMMU is enabled on the system */ +static bool +has_iommu_groups(void) +{ + struct dirent *d; + int count = 0; + DIR *dir = opendir("/sys/kernel/iommu_groups"); + + if (dir == NULL) { + return false; + } + + while (count < 3 && (d = readdir(dir)) != NULL) { + count++; + } + + closedir(dir); + /* there will always be ./ and ../ entries */ + return count > 2; +} + static void spdk_vtophys_iommu_init(void) { @@ -454,7 +475,7 @@ spdk_vtophys_iommu_init(void) DIR *dir; struct dirent *d; - if (!spdk_vfio_enabled()) { + if (!spdk_vfio_enabled() || !has_iommu_groups()) { return; }