[libvirt] [PATCH v2] virt-host-validate: check for IOMMU support

Daniel P. Berrange berrange at redhat.com
Mon Oct 12 12:16:49 UTC 2015


This looks for existance of DMAR (Intel) and IVRS (AMD)
files under /sys/firmware/acpi/tables/, as a sign that
the platform has IOMMU present & enabled in the BIOS.

If these are present and /sys/kernel/iommu_groups does
not contain any entries this is taken as a sign that
the kernel has not enabled the IOMMU currently.

If no ACPI tables are found we can't distinguish between
disabled in BIOS and not present in the hardware, so we
have to give the user a generic hint.

Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
---

Changed in v2:

  - Completely refactor the check to remove false
    positives and cope with iommu being enabled
    by default
  - Add AMD support

 tools/virt-host-validate-common.c | 64 +++++++++++++++++++++++++++++++++++++++
 tools/virt-host-validate-common.h |  3 ++
 tools/virt-host-validate-qemu.c   |  6 ++++
 3 files changed, 73 insertions(+)

diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c
index a88fc56..38128b1 100644
--- a/tools/virt-host-validate-common.c
+++ b/tools/virt-host-validate-common.c
@@ -26,6 +26,7 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <sys/utsname.h>
+#include <sys/stat.h>
 #include <mntent.h>
 
 #include "virutil.h"
@@ -341,3 +342,66 @@ int virHostValidateCGroupController(const char *hvname,
         return -1;
     return 0;
 }
+
+int virHostValidateIOMMU(const char *hvname,
+                         virHostValidateLevel level)
+{
+    struct stat sb;
+    const char *bootarg = NULL;
+    bool isAMD = false, isIntel = false;
+
+    if (virHostValidateHasCPUFlag("vmx"))
+        isIntel = true;
+    else if (virHostValidateHasCPUFlag("svm"))
+        isAMD = true;
+    else
+        /* XXX PPC/ARM/etc support */
+        return 0;
+
+    virHostMsgCheck(hvname, "%s", _("for device assignment IOMMU support"));
+
+    if (isIntel) {
+        if (access("/sys/firmware/acpi/tables/DMAR", F_OK) == 0) {
+            virHostMsgPass();
+            bootarg = "intel_iommu=on";
+        } else {
+            virHostMsgFail(level,
+                           "No ACPI DMAR table found, IOMMU either "
+                           "disabled in BIOS or not supported by this "
+                           "hardware platform");
+            return -1;
+        }
+    } else if (isAMD) {
+        if (access("/sys/firmware/acpi/tables/IVRS", F_OK) == 0) {
+            virHostMsgPass();
+            bootarg = "iommu=pt iommu=1";
+        } else {
+            virHostMsgFail(level,
+                           "No ACPI IVRS table found, IOMMU either "
+                           "disabled in BIOS or not supported by this "
+                           "hardware platform");
+            return -1;
+        }
+    } else {
+        virHostMsgFail(level,
+                       "Unknown if this platform has IOMMU support");
+        return -1;
+    }
+
+
+    /* We can only check on newer kernels with iommu groups & vfio */
+    if (stat("/sys/kernel/iommu_groups", &sb) < 0)
+        return 0;
+
+    if (!S_ISDIR(sb.st_mode))
+        return 0;
+
+    virHostMsgCheck(hvname, "%s", _("if IOMMU is enabled by kernel"));
+    if (sb.st_nlink <= 2) {
+        virHostMsgFail(level,
+                       "IOMMU appears to be disabled in kernel. "
+                       "Add %s to kernel cmdline arguments", bootarg);
+        return -1;
+    }
+    return 0;
+}
diff --git a/tools/virt-host-validate-common.h b/tools/virt-host-validate-common.h
index 1547e22..d4c4759 100644
--- a/tools/virt-host-validate-common.h
+++ b/tools/virt-host-validate-common.h
@@ -70,4 +70,7 @@ extern int virHostValidateCGroupController(const char *hvname,
                                            virHostValidateLevel level,
                                            const char *config_name);
 
+extern int virHostValidateIOMMU(const char *hvname,
+                                virHostValidateLevel level);
+
 #endif /* __VIRT_HOST_VALIDATE_COMMON_H__ */
diff --git a/tools/virt-host-validate-qemu.c b/tools/virt-host-validate-qemu.c
index b0ae293..044df65 100644
--- a/tools/virt-host-validate-qemu.c
+++ b/tools/virt-host-validate-qemu.c
@@ -20,6 +20,8 @@
  */
 
 #include <config.h>
+#include <unistd.h>
+
 #include "virt-host-validate-qemu.h"
 #include "virt-host-validate-common.h"
 
@@ -87,5 +89,9 @@ int virHostValidateQEMU(void)
                                         "BLK_CGROUP") < 0)
         ret = -1;
 
+    if (virHostValidateIOMMU("QEMU",
+                             VIR_HOST_VALIDATE_WARN) < 0)
+        ret = -1;
+
     return ret;
 }
-- 
2.4.3




More information about the libvir-list mailing list