chiark / gitweb /
virtualization: check cpuid first, since it is cheaper than DMI
[elogind.git] / src / util.c
index 7e8246bb61195a0019b6945eb87e7a621b892c41..e2859fafc1b115215eb7638125a126e031aa1bf5 100644 (file)
@@ -3713,13 +3713,13 @@ int detect_vm(const char **id) {
 
         /* Both CPUID and DMI are x86 specific interfaces... */
 
-        const char *const dmi_vendors[] = {
+        static const char *const dmi_vendors[] = {
                 "/sys/class/dmi/id/sys_vendor",
                 "/sys/class/dmi/id/board_vendor",
                 "/sys/class/dmi/id/bios_vendor"
         };
 
-        const char dmi_vendor_table[] =
+        static const char dmi_vendor_table[] =
                 "QEMU\0"                  "qemu\0"
                 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
                 "VMware\0"                "vmware\0"
@@ -3727,9 +3727,10 @@ int detect_vm(const char **id) {
                 "Microsoft Corporation\0" "microsoft\0"
                 "innotek GmbH\0"          "oracle\0"
                 "Xen\0"                   "xen\0"
+                "Bochs\0"                 "bochs\0"
                 "\0";
 
-        const char cpuid_vendor_table[] =
+        static const char cpuid_vendor_table[] =
                 "XenVMMXenVMM\0"          "xen\0"
                 "KVMKVMKVM\0"             "kvm\0"
                 /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
@@ -3743,34 +3744,9 @@ int detect_vm(const char **id) {
                 uint32_t sig32[3];
                 char text[13];
         } sig;
-
         unsigned i;
         const char *j, *k;
-
-        for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
-                char *s;
-                int r;
-                const char *found = NULL;
-
-                if ((r = read_one_line_file(dmi_vendors[i], &s)) < 0) {
-                        if (r != -ENOENT)
-                                return r;
-
-                        continue;
-                }
-
-                NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
-                        if (startswith(s, j))
-                                found = k;
-                free(s);
-
-                if (found) {
-                        if (id)
-                                *id = found;
-
-                        return 1;
-                }
-        }
+        bool hypervisor;
 
         /* http://lwn.net/Articles/301888/ */
         zero(sig);
@@ -3795,7 +3771,9 @@ int detect_vm(const char **id) {
                 : "0" (eax)
         );
 
-        if (ecx & 0x80000000U) {
+        hypervisor = !!(ecx & ecx & 0x80000000U);
+
+        if (hypervisor) {
 
                 /* There is a hypervisor, see what it is */
                 eax = 0x40000000U;
@@ -3818,14 +3796,41 @@ int detect_vm(const char **id) {
 
                                 return 1;
                         }
+        }
 
+        for (i = 0; i < ELEMENTSOF(dmi_vendors); i++) {
+                char *s;
+                int r;
+                const char *found = NULL;
+
+                if ((r = read_one_line_file(dmi_vendors[i], &s)) < 0) {
+                        if (r != -ENOENT)
+                                return r;
+
+                        continue;
+                }
+
+                NULSTR_FOREACH_PAIR(j, k, dmi_vendor_table)
+                        if (startswith(s, j))
+                                found = k;
+                free(s);
+
+                if (found) {
+                        if (id)
+                                *id = found;
+
+                        return 1;
+                }
+        }
+
+        if (hypervisor) {
                 if (id)
                         *id = "other";
 
                 return 1;
         }
-#endif
 
+#endif
         return 0;
 }