Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 2 Jun 2011 14:04:08 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r222610 - in projects/bhyve/sys/amd64/vmm: . intel
Message-ID:  <201106021404.p52E48b2020411@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Thu Jun  2 14:04:07 2011
New Revision: 222610
URL: http://svn.freebsd.org/changeset/base/222610

Log:
  Some tweaks to the CPUID support:
  - Don't always pass the cpuid request to the current CPU as some nodes
    we will emulate purely in software.
  - Pass in the APIC ID of the virtual CPU so we can return the proper APIC
    ID.
  - Always report a completely flat topology with no SMT or multicore.
  - Report the CPUID2_HV feature and implement support for the 0x40000000
    CPUID level.
  - Use existing constants from <machine/specialreg.h> when possible and
    use cpu_feature2 when checking for VMX support.

Modified:
  projects/bhyve/sys/amd64/vmm/intel/vmx.c
  projects/bhyve/sys/amd64/vmm/x86.c
  projects/bhyve/sys/amd64/vmm/x86.h

Modified: projects/bhyve/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/intel/vmx.c	Thu Jun  2 14:03:12 2011	(r222609)
+++ projects/bhyve/sys/amd64/vmm/intel/vmx.c	Thu Jun  2 14:04:07 2011	(r222610)
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
 
 #include <machine/psl.h>
 #include <machine/cpufunc.h>
+#include <machine/md_var.h>
 #include <machine/pmap.h>
 #include <machine/segments.h>
 #include <machine/vmparam.h>
@@ -418,13 +419,11 @@ static int
 vmx_init(void)
 {
 	int error;
-	unsigned int regs[4];
 	uint64_t fixed0, fixed1;
 	uint32_t tmp;
 
 	/* CPUID.1:ECX[bit 5] must be 1 for processor to support VMX */
-	do_cpuid(1, regs);
-	if ((regs[2] & CPUID_0000_0001_FEAT0_VMX) == 0) {
+	if (!(cpu_feature2 & CPUID2_VMX)) {
 		printf("vmx_init: processor does not support VMX operation\n");
 		return (ENXIO);
 	}
@@ -705,7 +704,7 @@ vmx_vminit(struct vm *vm)
 }
 
 static int
-vmx_handle_cpuid(struct vmxctx *vmxctx)
+vmx_handle_cpuid(int vcpu, struct vmxctx *vmxctx)
 {
 	int handled, func;
 	
@@ -713,7 +712,7 @@ vmx_handle_cpuid(struct vmxctx *vmxctx)
 
 	handled = x86_emulate_cpuid((uint32_t*)(&vmxctx->guest_rax),
 	    (uint32_t*)(&vmxctx->guest_rbx), (uint32_t*)(&vmxctx->guest_rcx),
-	    (uint32_t*)(&vmxctx->guest_rdx));
+	    (uint32_t*)(&vmxctx->guest_rdx), vcpu);
 #if 0
 	printf("%s: func %x rax %lx rbx %lx rcx %lx rdx %lx handled %d\n",
 		__func__, func, vmxctx->guest_rax, vmxctx->guest_rbx,
@@ -1148,7 +1147,7 @@ vmx_exit_process(struct vmx *vmx, int vc
 		vmexit->u.inout.eax = (uint32_t)(vmxctx->guest_rax);
 		break;
 	case EXIT_REASON_CPUID:
-		handled = vmx_handle_cpuid(vmxctx);
+		handled = vmx_handle_cpuid(vcpu, vmxctx);
 		break;
 	default:
 		break;

Modified: projects/bhyve/sys/amd64/vmm/x86.c
==============================================================================
--- projects/bhyve/sys/amd64/vmm/x86.c	Thu Jun  2 14:03:12 2011	(r222609)
+++ projects/bhyve/sys/amd64/vmm/x86.c	Thu Jun  2 14:04:07 2011	(r222610)
@@ -30,27 +30,51 @@
 __FBSDID("$FreeBSD$");
 
 #include <sys/types.h>
+#include <sys/systm.h>
 
 #include <machine/cpufunc.h>
+#include <machine/md_var.h>
 #include <machine/specialreg.h>
 
 #include "x86.h"
 
+#define	CPUID_VM_HIGH		0x40000000
+
+static const char bhyve_id[12] = "BHyVE BHyVE ";
+
 int
-x86_emulate_cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
+x86_emulate_cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx,
+	uint32_t vcpu_id)
 {
 	unsigned int 	func, regs[4];
 
 	func = *eax;
 
-	cpuid_count(*eax, *ecx, regs);
+	/*
+	 * Requests for invalid CPUID levels should map to the highest
+	 * available level instead.
+	 */
+	if (cpu_exthigh != 0 && *eax >= 0x80000000) {
+		if (*eax > cpu_exthigh)
+			*eax = cpu_exthigh;
+	} else if (*eax >= 0x40000000) {
+		if (*eax > CPUID_VM_HIGH)
+			*eax = CPUID_VM_HIGH;
+	} else if (*eax > cpu_high) {
+		*eax = cpu_high;
+	}
 
-	switch(func) {
+	/*
+	 * In general the approach used for CPU topology is to
+	 * advertise a flat topology where all CPUs are packages with
+	 * no multi-core or SMT.
+	 */
+	switch (func) {
 		case CPUID_0000_0000:
 		case CPUID_0000_0002:
 		case CPUID_0000_0003:
-		case CPUID_0000_0004:
 		case CPUID_0000_000A:
+			cpuid_count(*eax, *ecx, regs);
 			break;
 
 		case CPUID_8000_0000:
@@ -61,26 +85,24 @@ x86_emulate_cpuid(uint32_t *eax, uint32_
 		case CPUID_8000_0006:
 		case CPUID_8000_0007:
 		case CPUID_8000_0008:
-
+			cpuid_count(*eax, *ecx, regs);
 			break;
 
 		case CPUID_0000_0001:
+			do_cpuid(1, regs);
+
 			/*
 			 * Override the APIC ID only in ebx
 			 */
-			regs[1] &= ~(CPUID_0000_0001_APICID_MASK);
-			/*
-			 * XXX fixme for MP case, set apicid properly for cpu. 
-			 */
-			regs[1] |= (0 << CPUID_0000_0001_APICID_SHIFT);
+			regs[1] &= ~(CPUID_LOCAL_APIC_ID);
+			regs[1] |= (vcpu_id << CPUID_0000_0001_APICID_SHIFT);
 
 			/*
 			 * Don't expose VMX, SpeedStep or TME capability.
-			 * Advertise x2APIC capability.
+			 * Advertise x2APIC capability and Hypervisor guest.
 			 */
-			regs[2] &= ~(CPUID_0000_0001_FEAT0_VMX | CPUID2_EST |
-				     CPUID2_TM2);
-			regs[2] |= CPUID2_X2APIC;
+			regs[2] &= ~(CPUID2_VMX | CPUID2_EST | CPUID2_TM2);
+			regs[2] |= CPUID2_X2APIC | CPUID2_HV;
 
 			/*
 			 * Hide thermal monitoring
@@ -93,6 +115,21 @@ x86_emulate_cpuid(uint32_t *eax, uint32_
 			 */
 			regs[3] &= ~(CPUID_MCA | CPUID_MCE | CPUID_MTRR);
 
+			/*
+			 * Disable multi-core.
+			 */
+			regs[1] &= ~CPUID_HTT_CORES;
+			regs[3] &= ~CPUID_HTT;
+			break;
+
+		case CPUID_0000_0004:
+			do_cpuid(4, regs);
+
+			/*
+			 * Do not expose topology.
+			 */
+			regs[0] &= 0xffff8000;
+			regs[0] |= 0x04008000;
 			break;
 
 		case CPUID_0000_0006:
@@ -108,16 +145,22 @@ x86_emulate_cpuid(uint32_t *eax, uint32_
 
 		case CPUID_0000_000B:
 			/*
-			 * XXXSMP fixme
 			 * Processor topology enumeration
 			 */
 			regs[0] = 0;
 			regs[1] = 0;
 			regs[2] = *ecx & 0xff;
-			regs[3] = 0;
+			regs[3] = vcpu_id;
 			break;
 
+		case 0x40000000:
+			regs[0] = CPUID_VM_HIGH;
+			bcopy(bhyve_id, &regs[1], 4);
+			bcopy(bhyve_id, &regs[2], 4);
+			bcopy(bhyve_id, &regs[3], 4);
+			break;
 		default:
+			/* XXX: Leaf 5? */
 			return (0);
 	}
 
@@ -127,4 +170,3 @@ x86_emulate_cpuid(uint32_t *eax, uint32_
 	*edx = regs[3];
 	return (1);
 }
-

Modified: projects/bhyve/sys/amd64/vmm/x86.h
==============================================================================
--- projects/bhyve/sys/amd64/vmm/x86.h	Thu Jun  2 14:03:12 2011	(r222609)
+++ projects/bhyve/sys/amd64/vmm/x86.h	Thu Jun  2 14:04:07 2011	(r222610)
@@ -58,6 +58,6 @@
 #define CPUID_0000_0001_FEAT0_VMX	(1<<5)
 
 int x86_emulate_cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx,
-		      uint32_t *edx);
+		      uint32_t *edx, uint32_t vcpu_id);
 
 #endif



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106021404.p52E48b2020411>