From 9139b46a6be9d04e0b6cf882f6ab4d3a9efb4825 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 7 Oct 2015 17:46:18 +0100 Subject: [PATCH] virt-host-validate: check for IOMMU support 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 --- tools/virt-host-validate-common.c | 65 +++++++++++++++++++++++++++++++ tools/virt-host-validate-common.h | 3 ++ tools/virt-host-validate-qemu.c | 6 +++ 3 files changed, 74 insertions(+) diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c index dd41fd44ca..dd1c414f96 100644 --- a/tools/virt-host-validate-common.c +++ b/tools/virt-host-validate-common.c @@ -29,6 +29,7 @@ #ifdef HAVE_MNTENT_H # include #endif /* HAVE_MNTENT_H */ +#include #include "virutil.h" #include "viralloc.h" @@ -354,3 +355,67 @@ 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; + } + virHostMsgPass(); + return 0; +} diff --git a/tools/virt-host-validate-common.h b/tools/virt-host-validate-common.h index 1547e22897..d4c4759b0f 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 b0ae293be5..044df65b02 100644 --- a/tools/virt-host-validate-qemu.c +++ b/tools/virt-host-validate-qemu.c @@ -20,6 +20,8 @@ */ #include +#include + #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; } -- GitLab