Date: Sat, 20 Sep 2014 02:35:21 +0000 (UTC) From: Neel Natu <neel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271888 - in head: sys/amd64/include sys/amd64/vmm sys/amd64/vmm/intel sys/modules/vmm sys/x86/include usr.sbin/bhyve Message-ID: <201409200235.s8K2ZLnt095414@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: neel Date: Sat Sep 20 02:35:21 2014 New Revision: 271888 URL: http://svnweb.freebsd.org/changeset/base/271888 Log: Restructure the MSR handling so it is entirely handled by processor-specific code. There are only a handful of MSRs common between the two so there isn't too much duplicate functionality. The VT-x code has the following types of MSRs: - MSRs that are unconditionally saved/restored on every guest/host context switch (e.g., MSR_GSBASE). - MSRs that are restored to guest values on entry to vmx_run() and saved before returning. This is an optimization for MSRs that are not used in host kernel context (e.g., MSR_KGSBASE). - MSRs that are emulated and every access by the guest causes a trap into the hypervisor (e.g., MSR_IA32_MISC_ENABLE). Reviewed by: grehan Deleted: head/sys/amd64/vmm/vmm_msr.c head/sys/amd64/vmm/vmm_msr.h Modified: head/sys/amd64/include/vmm.h head/sys/amd64/vmm/intel/ept.c head/sys/amd64/vmm/intel/vmcs.h head/sys/amd64/vmm/intel/vmx.c head/sys/amd64/vmm/intel/vmx.h head/sys/amd64/vmm/intel/vmx_msr.c head/sys/amd64/vmm/intel/vmx_msr.h head/sys/amd64/vmm/vmm.c head/sys/modules/vmm/Makefile head/sys/x86/include/specialreg.h head/usr.sbin/bhyve/bhyverun.c head/usr.sbin/bhyve/xmsr.c head/usr.sbin/bhyve/xmsr.h Modified: head/sys/amd64/include/vmm.h ============================================================================== --- head/sys/amd64/include/vmm.h Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/amd64/include/vmm.h Sat Sep 20 02:35:21 2014 (r271888) @@ -195,7 +195,6 @@ void vm_nmi_clear(struct vm *vm, int vcp int vm_inject_extint(struct vm *vm, int vcpu); int vm_extint_pending(struct vm *vm, int vcpuid); void vm_extint_clear(struct vm *vm, int vcpuid); -uint64_t *vm_guest_msrs(struct vm *vm, int cpu); struct vlapic *vm_lapic(struct vm *vm, int cpu); struct vioapic *vm_ioapic(struct vm *vm); struct vhpet *vm_hpet(struct vm *vm); Modified: head/sys/amd64/vmm/intel/ept.c ============================================================================== --- head/sys/amd64/vmm/intel/ept.c Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/amd64/vmm/intel/ept.c Sat Sep 20 02:35:21 2014 (r271888) @@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$"); #include "vmx_cpufunc.h" #include "vmm_ipi.h" -#include "vmx_msr.h" #include "ept.h" #define EPT_SUPPORTS_EXEC_ONLY(cap) ((cap) & (1UL << 0)) Modified: head/sys/amd64/vmm/intel/vmcs.h ============================================================================== --- head/sys/amd64/vmm/intel/vmcs.h Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/amd64/vmm/intel/vmcs.h Sat Sep 20 02:35:21 2014 (r271888) @@ -54,6 +54,10 @@ int vmcs_getdesc(struct vmcs *vmcs, int int vmcs_setdesc(struct vmcs *vmcs, int running, int ident, struct seg_desc *desc); +/* + * Avoid header pollution caused by inline use of 'vtophys()' in vmx_cpufunc.h + */ +#ifdef _VMX_CPUFUNC_H_ static __inline uint64_t vmcs_read(uint32_t encoding) { @@ -73,6 +77,7 @@ vmcs_write(uint32_t encoding, uint64_t v error = vmwrite(encoding, val); KASSERT(error == 0, ("vmcs_write(%u) error %d", encoding, error)); } +#endif /* _VMX_CPUFUNC_H_ */ #define vmexit_instruction_length() vmcs_read(VMCS_EXIT_INSTRUCTION_LENGTH) #define vmcs_guest_rip() vmcs_read(VMCS_GUEST_RIP) Modified: head/sys/amd64/vmm/intel/vmx.c ============================================================================== --- head/sys/amd64/vmm/intel/vmx.c Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/amd64/vmm/intel/vmx.c Sat Sep 20 02:35:21 2014 (r271888) @@ -52,20 +52,20 @@ __FBSDID("$FreeBSD$"); #include <machine/vmm.h> #include <machine/vmm_dev.h> #include <machine/vmm_instruction_emul.h> +#include "vmm_lapic.h" #include "vmm_host.h" #include "vmm_ioport.h" #include "vmm_ipi.h" -#include "vmm_msr.h" #include "vmm_ktr.h" #include "vmm_stat.h" #include "vatpic.h" #include "vlapic.h" #include "vlapic_priv.h" -#include "vmx_msr.h" #include "ept.h" #include "vmx_cpufunc.h" #include "vmx.h" +#include "vmx_msr.h" #include "x86.h" #include "vmx_controls.h" @@ -116,12 +116,6 @@ __FBSDID("$FreeBSD$"); VM_ENTRY_INTO_SMM | \ VM_ENTRY_DEACTIVATE_DUAL_MONITOR) -#define guest_msr_rw(vmx, msr) \ - msr_bitmap_change_access((vmx)->msr_bitmap, (msr), MSR_BITMAP_ACCESS_RW) - -#define guest_msr_ro(vmx, msr) \ - msr_bitmap_change_access((vmx)->msr_bitmap, (msr), MSR_BITMAP_ACCESS_READ) - #define HANDLED 1 #define UNHANDLED 0 @@ -208,6 +202,7 @@ SYSCTL_UINT(_hw_vmm_vmx, OID_AUTO, vpid_ static int vmx_getdesc(void *arg, int vcpu, int reg, struct seg_desc *desc); static int vmx_getreg(void *arg, int vcpu, int reg, uint64_t *retval); +static int vmxctx_setreg(struct vmxctx *vmxctx, int reg, uint64_t val); static void vmx_inject_pir(struct vlapic *vlapic); #ifdef KTR @@ -475,22 +470,6 @@ vpid_init(void) } static void -msr_save_area_init(struct msr_entry *g_area, int *g_count) -{ - int cnt; - - static struct msr_entry guest_msrs[] = { - { MSR_KGSBASE, 0, 0 }, - }; - - cnt = sizeof(guest_msrs) / sizeof(guest_msrs[0]); - if (cnt > GUEST_MSR_MAX_ENTRIES) - panic("guest msr save area overrun"); - bcopy(guest_msrs, g_area, sizeof(guest_msrs)); - *g_count = cnt; -} - -static void vmx_disable(void *arg __unused) { struct invvpid_desc invvpid_desc = { 0 }; @@ -655,7 +634,6 @@ vmx_init(int ipinum) } else { if (bootverbose) printf("vmm: PAT MSR access not supported\n"); - guest_msr_valid(MSR_PAT); vmx_patmsr = 0; } } @@ -800,6 +778,8 @@ vmx_init(int ipinum) vpid_init(); + vmx_msr_init(); + /* enable VMX operation */ smp_rendezvous(NULL, vmx_enable, NULL, NULL); @@ -869,7 +849,7 @@ static void * vmx_vminit(struct vm *vm, pmap_t pmap) { uint16_t vpid[VM_MAXCPU]; - int i, error, guest_msr_count; + int i, error; struct vmx *vmx; struct vmcs *vmcs; @@ -958,6 +938,8 @@ vmx_vminit(struct vm *vm, pmap_t pmap) error, i); } + vmx_msr_guest_init(vmx, i); + error = vmcs_init(vmcs); KASSERT(error == 0, ("vmcs_init error %d", error)); @@ -996,13 +978,6 @@ vmx_vminit(struct vm *vm, pmap_t pmap) vmx->state[i].lastcpu = NOCPU; vmx->state[i].vpid = vpid[i]; - msr_save_area_init(vmx->guest_msrs[i], &guest_msr_count); - - error = vmcs_set_msr_save(vmcs, vtophys(vmx->guest_msrs[i]), - guest_msr_count); - if (error != 0) - panic("vmcs_set_msr_save error %d", error); - /* * Set up the CR0/4 shadows, and init the read shadow * to the power-on register value from the Intel Sys Arch. @@ -2078,6 +2053,46 @@ vmx_task_switch_reason(uint64_t qual) } static int +emulate_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu) +{ + int error; + + if (lapic_msr(num)) + error = lapic_wrmsr(vmx->vm, vcpuid, num, val, retu); + else + error = vmx_wrmsr(vmx, vcpuid, num, val, retu); + + return (error); +} + +static int +emulate_rdmsr(struct vmx *vmx, int vcpuid, u_int num, bool *retu) +{ + struct vmxctx *vmxctx; + uint64_t result; + uint32_t eax, edx; + int error; + + if (lapic_msr(num)) + error = lapic_rdmsr(vmx->vm, vcpuid, num, &result, retu); + else + error = vmx_rdmsr(vmx, vcpuid, num, &result, retu); + + if (error == 0) { + eax = result; + vmxctx = &vmx->ctx[vcpuid]; + error = vmxctx_setreg(vmxctx, VM_REG_GUEST_RAX, eax); + KASSERT(error == 0, ("vmxctx_setreg(rax) error %d", error)); + + edx = result >> 32; + error = vmxctx_setreg(vmxctx, VM_REG_GUEST_RDX, edx); + KASSERT(error == 0, ("vmxctx_setreg(rdx) error %d", error)); + } + + return (error); +} + +static int vmx_exit_process(struct vmx *vmx, int vcpu, struct vm_exit *vmexit) { int error, handled, in; @@ -2215,7 +2230,7 @@ vmx_exit_process(struct vmx *vmx, int vc retu = false; ecx = vmxctx->guest_rcx; VCPU_CTR1(vmx->vm, vcpu, "rdmsr 0x%08x", ecx); - error = emulate_rdmsr(vmx->vm, vcpu, ecx, &retu); + error = emulate_rdmsr(vmx, vcpu, ecx, &retu); if (error) { vmexit->exitcode = VM_EXITCODE_RDMSR; vmexit->u.msr.code = ecx; @@ -2224,7 +2239,7 @@ vmx_exit_process(struct vmx *vmx, int vc } else { /* Return to userspace with a valid exitcode */ KASSERT(vmexit->exitcode != VM_EXITCODE_BOGUS, - ("emulate_wrmsr retu with bogus exitcode")); + ("emulate_rdmsr retu with bogus exitcode")); } break; case EXIT_REASON_WRMSR: @@ -2235,7 +2250,7 @@ vmx_exit_process(struct vmx *vmx, int vc edx = vmxctx->guest_rdx; VCPU_CTR2(vmx->vm, vcpu, "wrmsr 0x%08x value 0x%016lx", ecx, (uint64_t)edx << 32 | eax); - error = emulate_wrmsr(vmx->vm, vcpu, ecx, + error = emulate_wrmsr(vmx, vcpu, ecx, (uint64_t)edx << 32 | eax, &retu); if (error) { vmexit->exitcode = VM_EXITCODE_WRMSR; @@ -2523,6 +2538,8 @@ vmx_run(void *arg, int vcpu, register_t KASSERT(vmxctx->pmap == pmap, ("pmap %p different than ctx pmap %p", pmap, vmxctx->pmap)); + vmx_msr_guest_enter(vmx, vcpu); + VMPTRLD(vmcs); /* @@ -2624,6 +2641,8 @@ vmx_run(void *arg, int vcpu, register_t vmexit->exitcode); VMCLEAR(vmcs); + vmx_msr_guest_exit(vmx, vcpu); + return (0); } Modified: head/sys/amd64/vmm/intel/vmx.h ============================================================================== --- head/sys/amd64/vmm/intel/vmx.h Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/amd64/vmm/intel/vmx.h Sat Sep 20 02:35:21 2014 (r271888) @@ -33,8 +33,6 @@ struct pmap; -#define GUEST_MSR_MAX_ENTRIES 64 /* arbitrary */ - struct vmxctx { register_t guest_rdi; /* Guest state */ register_t guest_rsi; @@ -97,13 +95,23 @@ struct pir_desc { } __aligned(64); CTASSERT(sizeof(struct pir_desc) == 64); +/* Index into the 'guest_msrs[]' array */ +enum { + IDX_MSR_LSTAR, + IDX_MSR_CSTAR, + IDX_MSR_STAR, + IDX_MSR_SF_MASK, + IDX_MSR_KGSBASE, + GUEST_MSR_NUM /* must be the last enumeration */ +}; + /* virtual machine softc */ struct vmx { struct vmcs vmcs[VM_MAXCPU]; /* one vmcs per virtual cpu */ struct apic_page apic_page[VM_MAXCPU]; /* one apic page per vcpu */ char msr_bitmap[PAGE_SIZE]; struct pir_desc pir_desc[VM_MAXCPU]; - struct msr_entry guest_msrs[VM_MAXCPU][GUEST_MSR_MAX_ENTRIES]; + uint64_t guest_msrs[VM_MAXCPU][GUEST_MSR_NUM]; struct vmxctx ctx[VM_MAXCPU]; struct vmxcap cap[VM_MAXCPU]; struct vmxstate state[VM_MAXCPU]; @@ -113,7 +121,6 @@ struct vmx { }; CTASSERT((offsetof(struct vmx, vmcs) & PAGE_MASK) == 0); CTASSERT((offsetof(struct vmx, msr_bitmap) & PAGE_MASK) == 0); -CTASSERT((offsetof(struct vmx, guest_msrs) & 15) == 0); CTASSERT((offsetof(struct vmx, pir_desc[0]) & 63) == 0); #define VMX_GUEST_VMEXIT 0 Modified: head/sys/amd64/vmm/intel/vmx_msr.c ============================================================================== --- head/sys/amd64/vmm/intel/vmx_msr.c Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/amd64/vmm/intel/vmx_msr.c Sat Sep 20 02:35:21 2014 (r271888) @@ -31,10 +31,13 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/systm.h> +#include <sys/cpuset.h> #include <machine/cpufunc.h> #include <machine/specialreg.h> +#include <machine/vmm.h> +#include "vmx.h" #include "vmx_msr.h" static boolean_t @@ -171,3 +174,115 @@ msr_bitmap_change_access(char *bitmap, u return (0); } + +static uint64_t misc_enable; +static uint64_t host_msrs[GUEST_MSR_NUM]; + +void +vmx_msr_init(void) +{ + /* + * It is safe to cache the values of the following MSRs because + * they don't change based on curcpu, curproc or curthread. + */ + host_msrs[IDX_MSR_LSTAR] = rdmsr(MSR_LSTAR); + host_msrs[IDX_MSR_CSTAR] = rdmsr(MSR_CSTAR); + host_msrs[IDX_MSR_STAR] = rdmsr(MSR_STAR); + host_msrs[IDX_MSR_SF_MASK] = rdmsr(MSR_SF_MASK); + + /* + * Initialize emulated MSRs + */ + misc_enable = rdmsr(MSR_IA32_MISC_ENABLE); + /* + * Set mandatory bits + * 11: branch trace disabled + * 12: PEBS unavailable + * Clear unsupported features + * 16: SpeedStep enable + * 18: enable MONITOR FSM + */ + misc_enable |= (1 << 12) | (1 << 11); + misc_enable &= ~((1 << 18) | (1 << 16)); +} + +void +vmx_msr_guest_init(struct vmx *vmx, int vcpuid) +{ + /* + * The permissions bitmap is shared between all vcpus so initialize it + * once when initializing the vBSP. + */ + if (vcpuid == 0) { + guest_msr_rw(vmx, MSR_LSTAR); + guest_msr_rw(vmx, MSR_CSTAR); + guest_msr_rw(vmx, MSR_STAR); + guest_msr_rw(vmx, MSR_SF_MASK); + guest_msr_rw(vmx, MSR_KGSBASE); + } + return; +} + +void +vmx_msr_guest_enter(struct vmx *vmx, int vcpuid) +{ + uint64_t *guest_msrs = vmx->guest_msrs[vcpuid]; + + /* Save host MSRs (if any) and restore guest MSRs */ + wrmsr(MSR_LSTAR, guest_msrs[IDX_MSR_LSTAR]); + wrmsr(MSR_CSTAR, guest_msrs[IDX_MSR_CSTAR]); + wrmsr(MSR_STAR, guest_msrs[IDX_MSR_STAR]); + wrmsr(MSR_SF_MASK, guest_msrs[IDX_MSR_SF_MASK]); + wrmsr(MSR_KGSBASE, guest_msrs[IDX_MSR_KGSBASE]); +} + +void +vmx_msr_guest_exit(struct vmx *vmx, int vcpuid) +{ + uint64_t *guest_msrs = vmx->guest_msrs[vcpuid]; + + /* Save guest MSRs */ + guest_msrs[IDX_MSR_LSTAR] = rdmsr(MSR_LSTAR); + guest_msrs[IDX_MSR_CSTAR] = rdmsr(MSR_CSTAR); + guest_msrs[IDX_MSR_STAR] = rdmsr(MSR_STAR); + guest_msrs[IDX_MSR_SF_MASK] = rdmsr(MSR_SF_MASK); + guest_msrs[IDX_MSR_KGSBASE] = rdmsr(MSR_KGSBASE); + + /* Restore host MSRs */ + wrmsr(MSR_LSTAR, host_msrs[IDX_MSR_LSTAR]); + wrmsr(MSR_CSTAR, host_msrs[IDX_MSR_CSTAR]); + wrmsr(MSR_STAR, host_msrs[IDX_MSR_STAR]); + wrmsr(MSR_SF_MASK, host_msrs[IDX_MSR_SF_MASK]); + + /* MSR_KGSBASE will be restored on the way back to userspace */ +} + +int +vmx_rdmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t *val, bool *retu) +{ + int error = 0; + + switch (num) { + case MSR_IA32_MISC_ENABLE: + *val = misc_enable; + break; + default: + error = EINVAL; + break; + } + return (error); +} + +int +vmx_wrmsr(struct vmx *vmx, int vcpuid, u_int num, uint64_t val, bool *retu) +{ + int error = 0; + + switch (num) { + default: + error = EINVAL; + break; + } + + return (error); +} Modified: head/sys/amd64/vmm/intel/vmx_msr.h ============================================================================== --- head/sys/amd64/vmm/intel/vmx_msr.h Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/amd64/vmm/intel/vmx_msr.h Sat Sep 20 02:35:21 2014 (r271888) @@ -29,6 +29,15 @@ #ifndef _VMX_MSR_H_ #define _VMX_MSR_H_ +struct vmx; + +void vmx_msr_init(void); +void vmx_msr_guest_init(struct vmx *vmx, int vcpuid); +void vmx_msr_guest_enter(struct vmx *vmx, int vcpuid); +void vmx_msr_guest_exit(struct vmx *vmx, int vcpuid); +int vmx_rdmsr(struct vmx *, int vcpuid, u_int num, uint64_t *val, bool *retu); +int vmx_wrmsr(struct vmx *, int vcpuid, u_int num, uint64_t val, bool *retu); + uint32_t vmx_revision(void); int vmx_set_ctlreg(int ctl_reg, int true_ctl_reg, uint32_t ones_mask, @@ -52,4 +61,10 @@ int vmx_set_ctlreg(int ctl_reg, int true void msr_bitmap_initialize(char *bitmap); int msr_bitmap_change_access(char *bitmap, u_int msr, int access); +#define guest_msr_rw(vmx, msr) \ + msr_bitmap_change_access((vmx)->msr_bitmap, (msr), MSR_BITMAP_ACCESS_RW) + +#define guest_msr_ro(vmx, msr) \ + msr_bitmap_change_access((vmx)->msr_bitmap, (msr), MSR_BITMAP_ACCESS_READ) + #endif Modified: head/sys/amd64/vmm/vmm.c ============================================================================== --- head/sys/amd64/vmm/vmm.c Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/amd64/vmm/vmm.c Sat Sep 20 02:35:21 2014 (r271888) @@ -74,7 +74,6 @@ __FBSDID("$FreeBSD$"); #include "vhpet.h" #include "vioapic.h" #include "vlapic.h" -#include "vmm_msr.h" #include "vmm_ipi.h" #include "vmm_stat.h" #include "vmm_lapic.h" @@ -105,7 +104,6 @@ struct vcpu { struct savefpu *guestfpu; /* (a,i) guest fpu state */ uint64_t guest_xcr0; /* (i) guest %xcr0 register */ void *stats; /* (a,i) statistics */ - uint64_t guest_msrs[VMM_MSR_NUM]; /* (i) emulated MSRs */ struct vm_exit exitinfo; /* (x) exit reason and collateral */ }; @@ -188,7 +186,6 @@ static struct vmm_ops *ops; #define fpu_stop_emulating() clts() static MALLOC_DEFINE(M_VM, "vm", "vm"); -CTASSERT(VMM_MSR_NUM <= 64); /* msr_mask can keep track of up to 64 msrs */ /* statistics */ static VMM_STAT(VCPU_TOTAL_RUNTIME, "vcpu total runtime"); @@ -249,7 +246,6 @@ vcpu_init(struct vm *vm, int vcpu_id, bo vcpu->guest_xcr0 = XFEATURE_ENABLED_X87; fpu_save_area_reset(vcpu->guestfpu); vmm_stat_init(vcpu->stats); - guest_msrs_init(vm, vcpu_id); } struct vm_exit * @@ -293,7 +289,6 @@ vmm_init(void) else return (ENXIO); - vmm_msr_init(); vmm_resume_p = vmm_resume; return (VMM_INIT(vmm_ipinum)); @@ -1440,7 +1435,6 @@ restart: pcb = PCPU_GET(curpcb); set_pcb_flags(pcb, PCB_FULL_IRET); - restore_guest_msrs(vm, vcpuid); restore_guest_fpustate(vcpu); vcpu_require_state(vm, vcpuid, VCPU_RUNNING); @@ -1448,7 +1442,6 @@ restart: vcpu_require_state(vm, vcpuid, VCPU_FROZEN); save_guest_fpustate(vcpu); - restore_host_msrs(vm, vcpuid); vmm_stat_incr(vm, vcpuid, VCPU_TOTAL_RUNTIME, rdtsc() - tscval); @@ -1890,12 +1883,6 @@ vm_set_capability(struct vm *vm, int vcp return (VMSETCAP(vm->cookie, vcpu, type, val)); } -uint64_t * -vm_guest_msrs(struct vm *vm, int cpu) -{ - return (vm->vcpu[cpu].guest_msrs); -} - struct vlapic * vm_lapic(struct vm *vm, int cpu) { Modified: head/sys/modules/vmm/Makefile ============================================================================== --- head/sys/modules/vmm/Makefile Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/modules/vmm/Makefile Sat Sep 20 02:35:21 2014 (r271888) @@ -19,7 +19,6 @@ SRCS+= vmm.c \ vmm_ipi.c \ vmm_lapic.c \ vmm_mem.c \ - vmm_msr.c \ vmm_stat.c \ vmm_util.c \ x86.c \ Modified: head/sys/x86/include/specialreg.h ============================================================================== --- head/sys/x86/include/specialreg.h Sat Sep 20 01:22:17 2014 (r271887) +++ head/sys/x86/include/specialreg.h Sat Sep 20 02:35:21 2014 (r271888) @@ -437,6 +437,10 @@ #define MSR_MC4_STATUS 0x411 #define MSR_MC4_ADDR 0x412 #define MSR_MC4_MISC 0x413 +#define MSR_PKG_ENERGY_STATUS 0x611 +#define MSR_DRAM_ENERGY_STATUS 0x619 +#define MSR_PP0_ENERGY_STATUS 0x639 +#define MSR_PP1_ENERGY_STATUS 0x641 /* * VMX MSRs Modified: head/usr.sbin/bhyve/bhyverun.c ============================================================================== --- head/usr.sbin/bhyve/bhyverun.c Sat Sep 20 01:22:17 2014 (r271887) +++ head/usr.sbin/bhyve/bhyverun.c Sat Sep 20 02:35:21 2014 (r271888) @@ -803,6 +803,12 @@ main(int argc, char *argv[]) exit(1); } + error = init_msr(); + if (error) { + fprintf(stderr, "init_msr error %d", error); + exit(1); + } + init_mem(); init_inout(); pci_irq_init(ctx); Modified: head/usr.sbin/bhyve/xmsr.c ============================================================================== --- head/usr.sbin/bhyve/xmsr.c Sat Sep 20 01:22:17 2014 (r271887) +++ head/usr.sbin/bhyve/xmsr.c Sat Sep 20 02:35:21 2014 (r271888) @@ -31,33 +31,84 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> +#include <machine/cpufunc.h> #include <machine/vmm.h> +#include <machine/specialreg.h> + #include <vmmapi.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include "xmsr.h" +static int cpu_vendor_intel, cpu_vendor_amd; + int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val) { - switch (code) { - case 0xd04: /* Sandy Bridge uncore PMC MSRs */ - case 0xc24: - return (0); - case 0x79: - return (0); /* IA32_BIOS_UPDT_TRIG MSR */ - default: - break; + if (cpu_vendor_intel) { + switch (code) { + case 0xd04: /* Sandy Bridge uncore PMCs */ + case 0xc24: + return (0); + case MSR_BIOS_UPDT_TRIG: + return (0); + case MSR_BIOS_SIGN: + return (0); + default: + break; + } } return (-1); } int -emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val) +emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t num, uint64_t *val) { + int error = 0; - return (-1); + if (cpu_vendor_intel) { + switch (num) { + case MSR_BIOS_SIGN: + case MSR_IA32_PLATFORM_ID: + case MSR_PKG_ENERGY_STATUS: + case MSR_PP0_ENERGY_STATUS: + case MSR_PP1_ENERGY_STATUS: + case MSR_DRAM_ENERGY_STATUS: + *val = 0; + break; + default: + error = -1; + break; + } + } + return (error); +} + +int +init_msr(void) +{ + int error; + u_int regs[4]; + char cpu_vendor[13]; + + do_cpuid(0, regs); + ((u_int *)&cpu_vendor)[0] = regs[1]; + ((u_int *)&cpu_vendor)[1] = regs[3]; + ((u_int *)&cpu_vendor)[2] = regs[2]; + cpu_vendor[12] = '\0'; + + error = 0; + if (strcmp(cpu_vendor, "AuthenticAMD") == 0) { + cpu_vendor_amd = 1; + } else if (strcmp(cpu_vendor, "GenuineIntel") == 0) { + cpu_vendor_intel = 1; + } else { + fprintf(stderr, "Unknown cpu vendor \"%s\"\n", cpu_vendor); + error = -1; + } + return (error); } Modified: head/usr.sbin/bhyve/xmsr.h ============================================================================== --- head/usr.sbin/bhyve/xmsr.h Sat Sep 20 01:22:17 2014 (r271887) +++ head/usr.sbin/bhyve/xmsr.h Sat Sep 20 02:35:21 2014 (r271888) @@ -29,6 +29,7 @@ #ifndef _XMSR_H_ #define _XMSR_H_ +int init_msr(void); int emulate_wrmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t val); int emulate_rdmsr(struct vmctx *ctx, int vcpu, uint32_t code, uint64_t *val);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201409200235.s8K2ZLnt095414>