diff --git a/src/basic/virt.c b/src/basic/virt.c index c9c4416ef7..745a855779 100644 --- a/src/basic/virt.c +++ b/src/basic/virt.c @@ -276,19 +276,6 @@ static int detect_vm_dmi(void) { #endif } -static int detect_vm_xen(void) { - - /* Check for Dom0 will be executed later in detect_vm_xen_dom0 - The presence of /proc/xen indicates some form of a Xen domain */ - if (access("/proc/xen", F_OK) < 0) { - log_debug("Virtualization XEN not found, /proc/xen does not exist"); - return VIRTUALIZATION_NONE; - } - - log_debug("Virtualization XEN found (/proc/xen exists)"); - return VIRTUALIZATION_XEN; -} - #define XENFEAT_dom0 11 /* xen/include/public/features.h */ #define PATH_FEATURES "/sys/hypervisor/properties/features" /* Returns -errno, or 0 for domU, or 1 for dom0 */ @@ -342,6 +329,26 @@ static int detect_vm_xen_dom0(void) { } } +static int detect_vm_xen(void) { + int r; + + /* The presence of /proc/xen indicates some form of a Xen domain */ + if (access("/proc/xen", F_OK) < 0) { + log_debug("Virtualization XEN not found, /proc/xen does not exist"); + return VIRTUALIZATION_NONE; + } + log_debug("Virtualization XEN found (/proc/xen exists)"); + + /* Ignore the Xen hypervisor if we are in Dom0 */ + r = detect_vm_xen_dom0(); + if (r < 0) + return r; + if (r > 0) + return VIRTUALIZATION_NONE; + + return VIRTUALIZATION_XEN; +} + static int detect_vm_hypervisor(void) { _cleanup_free_ char *hvtype = NULL; int r; @@ -435,7 +442,8 @@ int detect_vm(void) { * * → First, try to detect Oracle Virtualbox and Amazon EC2 Nitro, even if they use KVM, as well as Xen even if * it cloaks as Microsoft Hyper-V. Attempt to detect uml at this stage also since it runs as a user-process - * nested inside other VMs. + * nested inside other VMs. Also check for Xen now, because Xen PV mode does not override CPUID when nested + * inside another hypervisor. * * → Second, try to detect from CPUID, this will report KVM for whatever software is used even if info in DMI is * overwritten. @@ -457,6 +465,15 @@ int detect_vm(void) { else if (r != VIRTUALIZATION_NONE) goto finish; + /* Detect Xen */ + r = detect_vm_xen(); + if (r < 0) + return r; + if (r == VIRTUALIZATION_VM_OTHER) + other = true; + else if (r != VIRTUALIZATION_NONE) + goto finish; + /* Detect from CPUID */ r = detect_vm_cpuid(); if (r < 0) @@ -476,20 +493,7 @@ int detect_vm(void) { goto finish; } - /* x86 xen will most likely be detected by cpuid. If not (most likely - * because we're not an x86 guest), then we should try the /proc/xen - * directory next. If that's not found, then we check for the high-level - * hypervisor sysfs file. - */ - - r = detect_vm_xen(); - if (r < 0) - return r; - if (r == VIRTUALIZATION_VM_OTHER) - other = true; - else if (r != VIRTUALIZATION_NONE) - goto finish; - + /* Check high-level hypervisor sysfs file */ r = detect_vm_hypervisor(); if (r < 0) return r; @@ -511,18 +515,7 @@ int detect_vm(void) { return r; finish: - /* x86 xen Dom0 is detected as XEN in hypervisor and maybe others. - * In order to detect the Dom0 as not virtualization we need to - * double-check it */ - if (r == VIRTUALIZATION_XEN) { - int dom0; - - dom0 = detect_vm_xen_dom0(); - if (dom0 < 0) - return dom0; - if (dom0 > 0) - r = VIRTUALIZATION_NONE; - } else if (r == VIRTUALIZATION_NONE && other) + if (r == VIRTUALIZATION_NONE && other) r = VIRTUALIZATION_VM_OTHER; cached_found = r;