diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c index dd41fd44ca33e4255a0fba28ee905237de40a1a1..dd1c414f96531ded3692896cf125710b6250e925 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 1547e22897eb51eb2f8f1f695bd694da30071784..d4c4759b0f539cf6fd23affe128bd6b40aa2dd24 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 b0ae293be598cc906c6054875876f4d15c615795..044df65b02cfd74a0c90c8ad508af6d7725afc9a 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; }