chiark / gitweb /
basic: detect_vm_cpuid: use gcc's __get_cpuid() function (#7758)
authorMike Gilbert <floppymaster@gmail.com>
Fri, 29 Dec 2017 18:30:38 +0000 (13:30 -0500)
committerSven Eden <yamakuzure@gmx.net>
Wed, 30 May 2018 05:49:46 +0000 (07:49 +0200)
The __get_cpuid() function includes a safety check to ensure that
executing the cpuid instruction is valid/safe.

This method also works with clang.

https://lists.freedesktop.org/archives/systemd-devel/2017-December/040054.html

src/basic/virt.c

index eac5c062624627cf3f56f35fa3c5fd60195d9353..15dc860ad830a1ac97d8614ef5a760939ec2959b 100644 (file)
@@ -18,6 +18,9 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#if defined(__i386__) || defined(__x86_64__)
+//#include <cpuid.h>
+#endif
 #include <errno.h>
 #include <stdint.h>
 #include <stdlib.h>
@@ -57,30 +60,14 @@ static int detect_vm_cpuid(void) {
                 { "bhyve bhyve ", VIRTUALIZATION_BHYVE     },
         };
 
-        uint32_t eax, ecx;
+        uint32_t eax, ebx, ecx, edx;
         bool hypervisor;
 
         /* http://lwn.net/Articles/301888/ */
 
-#if defined (__i386__)
-#define REG_a "eax"
-#define REG_b "ebx"
-#elif defined (__amd64__)
-#define REG_a "rax"
-#define REG_b "rbx"
-#endif
-
         /* First detect whether there is a hypervisor */
-        eax = 1;
-        __asm__ __volatile__ (
-                /* ebx/rbx is being used for PIC! */
-                "  push %%"REG_b"         \n\t"
-                "  cpuid                  \n\t"
-                "  pop %%"REG_b"          \n\t"
-
-                : "=a" (eax), "=c" (ecx)
-                : "0" (eax)
-        );
+        if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) == 0)
+                return VIRTUALIZATION_NONE;
 
         hypervisor = !!(ecx & 0x80000000U);
 
@@ -92,17 +79,12 @@ static int detect_vm_cpuid(void) {
                 unsigned j;
 
                 /* There is a hypervisor, see what it is */
-                eax = 0x40000000U;
-                __asm__ __volatile__ (
-                        /* ebx/rbx is being used for PIC! */
-                        "  push %%"REG_b"         \n\t"
-                        "  cpuid                  \n\t"
-                        "  mov %%ebx, %1          \n\t"
-                        "  pop %%"REG_b"          \n\t"
-
-                        : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
-                        : "0" (eax)
-                );
+                if (__get_cpuid(0x40000000U, &eax, &ebx, &ecx, &edx) == 0)
+                        return VIRTUALIZATION_NONE;
+
+                sig.sig32[0] = ebx;
+                sig.sig32[1] = ecx;
+                sig.sig32[2] = edx;
 
                 log_debug("Virtualization found, CPUID=%s", sig.text);