/* * This program is derived from systemd. * * Copyright 2011 Lennart Poettering * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; If not, see . */ #include #include #include #define streq(a, b) (!strcmp(a, b)) #define ELEMENTSOF(a) (sizeof(a) / sizeof((a)[0])) enum { VIRTUALIZATION_NONE, VIRTUALIZATION_VM_OTHER, VIRTUALIZATION_MICROSOFT, }; static int detect_vm_cpuid(void) { static const struct { const char *cpuid; int id; } cpuid_vendor_table[] = { /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */ { "Microsoft Hv", VIRTUALIZATION_MICROSOFT }, }; uint32_t eax, ecx; 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) ); hypervisor = !!(ecx & 0x80000000U); if (hypervisor) { union { uint32_t sig32[3]; char text[13]; } sig = {}; 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) ); for (j = 0; j < ELEMENTSOF(cpuid_vendor_table); j ++) if (streq(sig.text, cpuid_vendor_table[j].cpuid)) return cpuid_vendor_table[j].id; return VIRTUALIZATION_VM_OTHER; } return VIRTUALIZATION_NONE; } int main(void) { return detect_vm_cpuid() != VIRTUALIZATION_MICROSOFT; }