From owner-svn-src-all@freebsd.org Fri May 17 17:21:33 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id C9118159A9CD; Fri, 17 May 2019 17:21:33 +0000 (UTC) (envelope-from stevek@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 6C8D18497D; Fri, 17 May 2019 17:21:33 +0000 (UTC) (envelope-from stevek@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 47092B574; Fri, 17 May 2019 17:21:33 +0000 (UTC) (envelope-from stevek@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id x4HHLXdm065979; Fri, 17 May 2019 17:21:33 GMT (envelope-from stevek@FreeBSD.org) Received: (from stevek@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x4HHLWwk065974; Fri, 17 May 2019 17:21:32 GMT (envelope-from stevek@FreeBSD.org) Message-Id: <201905171721.x4HHLWwk065974@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: stevek set sender to stevek@FreeBSD.org using -f From: "Stephen J. Kiernan" Date: Fri, 17 May 2019 17:21:32 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r347932 - in head/sys: kern sys x86/include x86/x86 X-SVN-Group: head X-SVN-Commit-Author: stevek X-SVN-Commit-Paths: in head/sys: kern sys x86/include x86/x86 X-SVN-Commit-Revision: 347932 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 6C8D18497D X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.98 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.98)[-0.978,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US]; NEURAL_HAM_LONG(-1.00)[-1.000,0] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 May 2019 17:21:34 -0000 Author: stevek Date: Fri May 17 17:21:32 2019 New Revision: 347932 URL: https://svnweb.freebsd.org/changeset/base/347932 Log: Instead of individual conditional statements to look for each hypervisor type, use a table to make it easier to add more in the future, if needed. Add VirtualBox detection to the table ("VBoxVBoxVBox" is the hypervisor vendor string to look for.) Also add VM_GUEST_VBOX to the VM_GUEST enumeration to indicate VirtualBox. Save the CPUID base for the hypervisor entry that we detected. Driver code may need to know about it in order to obtain additional CPUID features. Approved by: bryanv, jhb Differential Revision: https://reviews.freebsd.org/D16305 Modified: head/sys/kern/subr_param.c head/sys/sys/systm.h head/sys/x86/include/x86_var.h head/sys/x86/x86/identcpu.c Modified: head/sys/kern/subr_param.c ============================================================================== --- head/sys/kern/subr_param.c Fri May 17 17:11:01 2019 (r347931) +++ head/sys/kern/subr_param.c Fri May 17 17:21:32 2019 (r347932) @@ -153,6 +153,7 @@ static const char *const vm_guest_sysctl_names[] = { "vmware", "kvm", "bhyve", + "vbox", NULL }; CTASSERT(nitems(vm_guest_sysctl_names) - 1 == VM_LAST); Modified: head/sys/sys/systm.h ============================================================================== --- head/sys/sys/systm.h Fri May 17 17:11:01 2019 (r347931) +++ head/sys/sys/systm.h Fri May 17 17:21:32 2019 (r347932) @@ -78,7 +78,8 @@ extern int vm_guest; /* Running as virtual machine gu * 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 }; /* * These functions need to be declared before the KASSERT macro is invoked in Modified: head/sys/x86/include/x86_var.h ============================================================================== --- head/sys/x86/include/x86_var.h Fri May 17 17:11:01 2019 (r347931) +++ head/sys/x86/include/x86_var.h Fri May 17 17:21:32 2019 (r347932) @@ -68,6 +68,7 @@ extern u_int cpu_mon_min_size; 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[]; Modified: head/sys/x86/x86/identcpu.c ============================================================================== --- head/sys/x86/x86/identcpu.c Fri May 17 17:11:01 2019 (r347931) +++ head/sys/x86/x86/identcpu.c Fri May 17 17:21:32 2019 (r347932) @@ -164,6 +164,7 @@ static int hw_clockrate; 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, @@ -1323,11 +1324,22 @@ static const char *const vm_pnames[] = { NULL }; -void -identify_hypervisor(void) +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 regs[4]; - char *p; + u_int leaf, regs[4]; int i; /* @@ -1337,10 +1349,13 @@ identify_hypervisor(void) * KB1009458: Mechanisms to determine if software is running in * a VMware virtual machine * http://kb.vmware.com/kb/1009458 + * + * Search for a hypervisor that we recognize. If we cannot find + * a specific hypervisor, return the first information about the + * hypervisor that we found, as others may be able to use. */ - if (cpu_feature2 & CPUID2_HV) { - vm_guest = VM_GUEST_VM; - do_cpuid(0x40000000, regs); + for (leaf = 0x40000000; leaf < 0x40010000; leaf += 0x100) { + do_cpuid(leaf, regs); /* * KVM from Linux kernels prior to commit @@ -1351,23 +1366,52 @@ identify_hypervisor(void) */ if (regs[0] == 0 && regs[1] == 0x4b4d564b && regs[2] == 0x564b4d56 && regs[3] == 0x0000004d) - regs[0] = 0x40000001; + regs[0] = leaf + 1; - 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; + if (regs[0] >= leaf) { + 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 this is the first entry or we found a + * specific hypervisor, record the base, high value, + * and vendor identifier. + */ + if (vm_guest != VM_GUEST_VM || leaf == 0x40000000) { + hv_high = leaf; + ((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 we found a specific hypervisor, then + * we are finished. + */ + if (vm_guest != VM_GUEST_VM) + return; + } } + } +} + +void +identify_hypervisor(void) +{ + u_int regs[4]; + char *p; + int i; + + /* + * If CPUID2_HV is set, we are running in a hypervisor environment. + */ + if (cpu_feature2 & CPUID2_HV) { + vm_guest = VM_GUEST_VM; + identify_hypervisor_cpuid_base(); return; }