svn commit: r222610 - in projects/bhyve/sys/amd64/vmm: . intel
John Baldwin
jhb at FreeBSD.org
Thu Jun 2 14:04:08 UTC 2011
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, ®s[1], 4);
+ bcopy(bhyve_id, ®s[2], 4);
+ bcopy(bhyve_id, ®s[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
More information about the svn-src-projects
mailing list