Index: sys/kern/subr_param.c =================================================================== --- sys/kern/subr_param.c +++ sys/kern/subr_param.c @@ -152,6 +152,7 @@ "vmware", "kvm", "bhyve", + "vbox", NULL }; CTASSERT(nitems(vm_guest_sysctl_names) - 1 == VM_LAST); Index: sys/sys/systm.h =================================================================== --- sys/sys/systm.h +++ sys/sys/systm.h @@ -78,7 +78,8 @@ * Keep in sync with vm_guest_sysctl_names[]. */ enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN, VM_GUEST_HV, - VM_GUEST_VMWARE, VM_GUEST_KVM, VM_GUEST_BHYVE, VM_LAST }; + VM_GUEST_VMWARE, VM_GUEST_KVM, VM_GUEST_BHYVE, VM_GUEST_VBOX, + VM_LAST }; #if defined(WITNESS) || defined(INVARIANT_SUPPORT) void kassert_panic(const char *fmt, ...) __printflike(1, 2); Index: sys/x86/include/x86_var.h =================================================================== --- sys/x86/include/x86_var.h +++ sys/x86/include/x86_var.h @@ -68,6 +68,7 @@ extern u_int cpu_mon_max_size; extern u_int cpu_maxphyaddr; extern char ctx_switch_xsave[]; +extern u_int hv_base; extern u_int hv_high; extern char hv_vendor[]; extern char kstack[]; Index: sys/x86/x86/identcpu.c =================================================================== --- sys/x86/x86/identcpu.c +++ sys/x86/x86/identcpu.c @@ -161,6 +161,7 @@ SYSCTL_INT(_hw, OID_AUTO, clockrate, CTLFLAG_RD, &hw_clockrate, 0, "CPU instruction clock rate"); +u_int hv_base; u_int hv_high; char hv_vendor[16]; SYSCTL_STRING(_hw, OID_AUTO, hv_vendor, CTLFLAG_RD | CTLFLAG_MPSAFE, hv_vendor, @@ -1255,6 +1256,71 @@ hw_clockrate = level->total_set.freq; } +static struct { + const char *vm_cpuid; + int vm_guest; +} vm_cpuids[] = { + { "XENXENXEN", VM_GUEST_XEN }, /* XEN */ + { "Microsoft Hv", VM_GUEST_HV }, /* Microsoft Hyper-V */ + { "VMwareVMware", VM_GUEST_VMWARE }, /* VMware VM */ + { "KVMKVMKVM", VM_GUEST_KVM }, /* KVM */ + { "bhyve bhyve", VM_GUEST_BHYVE }, /* bhyve */ + { "VBoxVBoxVBox", VM_GUEST_VBOX }, /* VirtualBox */ +}; + +static void +identify_hypervisor_cpuid_base(void) +{ + u_int leaf, regs[4]; + int i; + + /* + * [RFC] CPUID usage for interaction between Hypervisors and Linux. + * http://lkml.org/lkml/2008/10/1/246 + * + * KB1009458: Mechanisms to determine if software is running in + * a VMware virtual machine + * http://kb.vmware.com/kb/1009458 + */ + for (leaf = 0x40000000; leaf < 0x40010000; leaf += 0x100) { + do_cpuid(leaf, regs); + + /* + * KVM from Linux kernels prior to commit + * 57c22e5f35aa4b9b2fe11f73f3e62bbf9ef36190 set %eax + * to 0 rather than a valid hv_high value. Check for + * the KVM signature bytes and fixup %eax to the + * highest supported leaf in that case. + */ + if (regs[0] == 0 && regs[1] == 0x4b4d564b && + regs[2] == 0x564b4d56 && regs[3] == 0x0000004d) + regs[0] = leaf + 1; + + if (regs[0] >= 0x40000000) { + for (i = 0; i < nitems(vm_cpuids); i++) + if (strncmp((const char *)®s[1], + vm_cpuids[i].vm_cpuid, 12) == 0) { + vm_guest = vm_cpuids[i].vm_guest; + break; + } + + /* + * If we found a specific hypervisor, record the + * base, high value, and vendor identifier. + */ + if (vm_guest != VM_GUEST_VM) { + hv_base = leaf; + hv_high = regs[0]; + ((u_int *)&hv_vendor)[0] = regs[1]; + ((u_int *)&hv_vendor)[1] = regs[2]; + ((u_int *)&hv_vendor)[2] = regs[3]; + hv_vendor[12] = '\0'; + return; + } + } + } +} + static void hook_tsc_freq(void *arg __unused) { @@ -1295,43 +1361,11 @@ int i; /* - * [RFC] CPUID usage for interaction between Hypervisors and Linux. - * http://lkml.org/lkml/2008/10/1/246 - * - * KB1009458: Mechanisms to determine if software is running in - * a VMware virtual machine - * http://kb.vmware.com/kb/1009458 + * If CPUID2_HV is set, we are running in a hypervisor environment. */ if (cpu_feature2 & CPUID2_HV) { vm_guest = VM_GUEST_VM; - do_cpuid(0x40000000, regs); - - /* - * KVM from Linux kernels prior to commit - * 57c22e5f35aa4b9b2fe11f73f3e62bbf9ef36190 set %eax - * to 0 rather than a valid hv_high value. Check for - * the KVM signature bytes and fixup %eax to the - * highest supported leaf in that case. - */ - if (regs[0] == 0 && regs[1] == 0x4b4d564b && - regs[2] == 0x564b4d56 && regs[3] == 0x0000004d) - regs[0] = 0x40000001; - - if (regs[0] >= 0x40000000) { - hv_high = regs[0]; - ((u_int *)&hv_vendor)[0] = regs[1]; - ((u_int *)&hv_vendor)[1] = regs[2]; - ((u_int *)&hv_vendor)[2] = regs[3]; - hv_vendor[12] = '\0'; - if (strcmp(hv_vendor, "VMwareVMware") == 0) - vm_guest = VM_GUEST_VMWARE; - else if (strcmp(hv_vendor, "Microsoft Hv") == 0) - vm_guest = VM_GUEST_HV; - else if (strcmp(hv_vendor, "KVMKVMKVM") == 0) - vm_guest = VM_GUEST_KVM; - else if (strcmp(hv_vendor, "bhyve bhyve") == 0) - vm_guest = VM_GUEST_BHYVE; - } + identify_hypervisor_cpuid_base(); return; }