svn commit: r271912 - in projects/bhyve_svm: sys/amd64/include sys/amd64/vmm sys/amd64/vmm/amd sys/amd64/vmm/intel sys/modules/vmm sys/x86/include usr.sbin/bhyve

Neel Natu neel at FreeBSD.org
Sat Sep 20 21:46:35 UTC 2014


Author: neel
Date: Sat Sep 20 21:46:31 2014
New Revision: 271912
URL: http://svnweb.freebsd.org/changeset/base/271912

Log:
  IFC r271888.
  
  Restructure MSR emulation so it is all done in processor-specific code.

Added:
  projects/bhyve_svm/sys/amd64/vmm/amd/svm_msr.c   (contents, props changed)
  projects/bhyve_svm/sys/amd64/vmm/amd/svm_msr.h   (contents, props changed)
Deleted:
  projects/bhyve_svm/sys/amd64/vmm/vmm_msr.c
  projects/bhyve_svm/sys/amd64/vmm/vmm_msr.h
Modified:
  projects/bhyve_svm/sys/amd64/include/vmm.h   (contents, props changed)
  projects/bhyve_svm/sys/amd64/vmm/amd/svm.c
  projects/bhyve_svm/sys/amd64/vmm/intel/ept.c
  projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.h
  projects/bhyve_svm/sys/amd64/vmm/intel/vmx.c
  projects/bhyve_svm/sys/amd64/vmm/intel/vmx.h
  projects/bhyve_svm/sys/amd64/vmm/intel/vmx_msr.c
  projects/bhyve_svm/sys/amd64/vmm/intel/vmx_msr.h
  projects/bhyve_svm/sys/amd64/vmm/vmm.c
  projects/bhyve_svm/sys/modules/vmm/Makefile
  projects/bhyve_svm/sys/x86/include/specialreg.h
  projects/bhyve_svm/usr.sbin/bhyve/bhyverun.c
  projects/bhyve_svm/usr.sbin/bhyve/xmsr.c
  projects/bhyve_svm/usr.sbin/bhyve/xmsr.h
Directory Properties:
  projects/bhyve_svm/   (props changed)
  projects/bhyve_svm/sys/   (props changed)
  projects/bhyve_svm/sys/amd64/vmm/   (props changed)
  projects/bhyve_svm/sys/modules/vmm/   (props changed)
  projects/bhyve_svm/usr.sbin/bhyve/   (props changed)

Modified: projects/bhyve_svm/sys/amd64/include/vmm.h
==============================================================================
--- projects/bhyve_svm/sys/amd64/include/vmm.h	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/include/vmm.h	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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: projects/bhyve_svm/sys/amd64/vmm/amd/svm.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/amd/svm.c	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/vmm/amd/svm.c	Sat Sep 20 21:46:31 2014	(r271912)
@@ -54,7 +54,6 @@ __FBSDID("$FreeBSD$");
 #include <x86/apicreg.h>
 
 #include "vmm_lapic.h"
-#include "vmm_msr.h"
 #include "vmm_stat.h"
 #include "vmm_ktr.h"
 #include "vmm_ioport.h"
@@ -66,6 +65,7 @@ __FBSDID("$FreeBSD$");
 #include "vmcb.h"
 #include "svm.h"
 #include "svm_softc.h"
+#include "svm_msr.h"
 #include "npt.h"
 
 SYSCTL_DECL(_hw_vmm);
@@ -303,6 +303,7 @@ svm_init(int ipinum)
 		asid[cpu].num = nasid - 1;
 	}
 
+	svm_msr_init();
 	svm_npt_init(ipinum);
 
 	/* Start SVM on all CPUs */
@@ -606,6 +607,7 @@ svm_vminit(struct vm *vm, pmap_t pmap)
 		vcpu->lastcpu = NOCPU;
 		vcpu->vmcb_pa = vtophys(&vcpu->vmcb);
 		vmcb_init(svm_sc, i, iopm_pa, msrpm_pa, pml4_pa);
+		svm_msr_guest_init(svm_sc, i);
 	}
 	return (svm_sc);
 }
@@ -867,8 +869,8 @@ svm_handle_inst_emul(struct vmcb *vmcb, 
  * Intercept access to MSR_EFER to prevent the guest from clearing the
  * SVM enable bit.
  */
-static void
-svm_write_efer(struct svm_softc *sc, int vcpu, uint32_t edx, uint32_t eax)
+static int
+svm_write_efer(struct svm_softc *sc, int vcpu, uint64_t val)
 {
 	struct vmcb_state *state;
 	uint64_t oldval;
@@ -876,12 +878,13 @@ svm_write_efer(struct svm_softc *sc, int
 	state = svm_get_vmcb_state(sc, vcpu);
 
 	oldval = state->efer;
-	state->efer = (uint64_t)edx << 32 | eax | EFER_SVM;
+	state->efer = val | EFER_SVM;
 	if (state->efer != oldval) {
 		VCPU_CTR2(sc->vm, vcpu, "Guest EFER changed from %#lx to %#lx",
 		    oldval, state->efer);
 		vcpu_set_dirty(sc, vcpu, VMCB_CACHE_CR);
 	}
+	return (0);
 }
 
 #ifdef KTR
@@ -1132,6 +1135,45 @@ clear_nmi_blocking(struct svm_softc *sc,
 	KASSERT(!error, ("%s: error %d setting intr_shadow", __func__, error));
 }
 
+static int
+emulate_wrmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t val,
+    bool *retu)
+{
+	int error;
+
+	if (lapic_msr(num))
+		error = lapic_wrmsr(sc->vm, vcpu, num, val, retu);
+	else if (num == MSR_EFER)
+		error = svm_write_efer(sc, vcpu, val);
+	else
+		error = svm_wrmsr(sc, vcpu, num, val, retu);
+
+	return (error);
+}
+
+static int
+emulate_rdmsr(struct svm_softc *sc, int vcpu, u_int num, bool *retu)
+{
+	struct vmcb_state *state;
+	struct svm_regctx *ctx;
+	uint64_t result;
+	int error;
+
+	if (lapic_msr(num))
+		error = lapic_rdmsr(sc->vm, vcpu, num, &result, retu);
+	else
+		error = svm_rdmsr(sc, vcpu, num, &result, retu);
+
+	if (error == 0) {
+		state = svm_get_vmcb_state(sc, vcpu);
+		ctx = svm_get_guest_regctx(sc, vcpu);
+		state->rax = result & 0xffffffff;
+		ctx->e.g.sctx_rdx = result >> 32;
+	}
+
+	return (error);
+}
+
 #ifdef KTR
 static const char *
 exit_reason_to_str(uint64_t reason)
@@ -1288,31 +1330,12 @@ svm_vmexit(struct svm_softc *svm_sc, int
 		edx = ctx->e.g.sctx_rdx;
 		retu = false;	
 
-		if (ecx == MSR_EFER) {
-			KASSERT(info1 != 0, ("rdmsr(MSR_EFER) is not emulated: "
-			    "info1(%#lx) info2(%#lx)", info1, info2));
-			svm_write_efer(svm_sc, vcpu, edx, eax);
-			handled = 1;
-			break;
-		}
-
-#define MSR_AMDK8_IPM           0xc0010055
-		/*
-		 * Ignore access to the "Interrupt Pending Message" MSR.
-		 */
-		if (ecx == MSR_AMDK8_IPM) {
-			if (!info1)
-				state->rax = ctx->e.g.sctx_rdx = 0;
-			handled = 1;
-			break;
-		}
-
 		if (info1) {
 			vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_WRMSR, 1);
 			val = (uint64_t)edx << 32 | eax;
 			VCPU_CTR2(svm_sc->vm, vcpu, "wrmsr %#x val %#lx",
 			    ecx, val);
-			if (emulate_wrmsr(svm_sc->vm, vcpu, ecx, val, &retu)) {
+			if (emulate_wrmsr(svm_sc, vcpu, ecx, val, &retu)) {
 				vmexit->exitcode = VM_EXITCODE_WRMSR;
 				vmexit->u.msr.code = ecx;
 				vmexit->u.msr.wval = val;
@@ -1325,7 +1348,7 @@ svm_vmexit(struct svm_softc *svm_sc, int
 		} else {
 			VCPU_CTR1(svm_sc->vm, vcpu, "rdmsr %#x", ecx);
 			vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_RDMSR, 1);
-			if (emulate_rdmsr(svm_sc->vm, vcpu, ecx, &retu)) {
+			if (emulate_rdmsr(svm_sc, vcpu, ecx, &retu)) {
 				vmexit->exitcode = VM_EXITCODE_RDMSR;
 				vmexit->u.msr.code = ecx;
 			} else if (!retu) {
@@ -1823,6 +1846,8 @@ svm_vmrun(void *arg, int vcpu, register_
 		vmm_stat_incr(vm, vcpu, VCPU_MIGRATIONS, 1);
 	}
 
+	svm_msr_guest_enter(svm_sc, vcpu);
+
 	/* Update Guest RIP */
 	state->rip = rip;
 
@@ -1904,6 +1929,8 @@ svm_vmrun(void *arg, int vcpu, register_
 		handled = svm_vmexit(svm_sc, vcpu, vmexit);
 	} while (handled);
 
+	svm_msr_guest_exit(svm_sc, vcpu);
+
 	return (0);
 }
 

Added: projects/bhyve_svm/sys/amd64/vmm/amd/svm_msr.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve_svm/sys/amd64/vmm/amd/svm_msr.c	Sat Sep 20 21:46:31 2014	(r271912)
@@ -0,0 +1,136 @@
+/*-
+ * Copyright (c) 2014, Neel Natu (neel at freebsd.org)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/errno.h>
+
+#include <machine/cpufunc.h>
+#include <machine/specialreg.h>
+
+#include "svm_msr.h"
+
+#ifndef MSR_AMDK8_IPM
+#define	MSR_AMDK8_IPM	0xc0010055
+#endif
+
+enum {
+	IDX_MSR_LSTAR,
+	IDX_MSR_CSTAR,
+	IDX_MSR_STAR,
+	IDX_MSR_SF_MASK,
+	HOST_MSR_NUM		/* must be the last enumeration */
+};
+
+static uint64_t host_msrs[HOST_MSR_NUM];
+
+void
+svm_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);
+}
+
+void
+svm_msr_guest_init(struct svm_softc *sc, int vcpu)
+{
+	/*
+	 * All the MSRs accessible to the guest are either saved/restored by
+	 * hardware on every #VMEXIT/VMRUN (e.g., G_PAT) or are saved/restored
+	 * by VMSAVE/VMLOAD (e.g., MSR_GSBASE).
+	 *
+	 * There are no guest MSRs that are saved/restored "by hand" so nothing
+	 * more to do here.
+	 */
+	return;
+}
+
+void
+svm_msr_guest_enter(struct svm_softc *sc, int vcpu)
+{
+	/*
+	 * Save host MSRs (if any) and restore guest MSRs (if any).
+	 */
+}
+
+void
+svm_msr_guest_exit(struct svm_softc *sc, int vcpu)
+{
+	/*
+	 * Save guest MSRs (if any) and 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
+svm_rdmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t *result,
+    bool *retu)
+{
+	int error = 0;
+
+	switch (num) {
+	case MSR_AMDK8_IPM:
+		*result = 0;
+		break;
+	default:
+		error = EINVAL;
+		break;
+	}
+
+	return (error);
+}
+
+int
+svm_wrmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t val, bool *retu)
+{
+	int error = 0;
+
+	switch (num) {
+	case MSR_AMDK8_IPM:
+		/*
+		 * Ignore writes to the "Interrupt Pending Message" MSR.
+		 */
+		break;
+	default:
+		error = EINVAL;
+		break;
+	}
+
+	return (error);
+}

Added: projects/bhyve_svm/sys/amd64/vmm/amd/svm_msr.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/bhyve_svm/sys/amd64/vmm/amd/svm_msr.h	Sat Sep 20 21:46:31 2014	(r271912)
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2014 Neel Natu (neel at freebsd.org)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice unmodified, this list of conditions, and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SVM_MSR_H_
+#define	_SVM_MSR_H_
+
+struct svm_softc;
+
+void svm_msr_init(void);
+void svm_msr_guest_init(struct svm_softc *sc, int vcpu);
+void svm_msr_guest_enter(struct svm_softc *sc, int vcpu);
+void svm_msr_guest_exit(struct svm_softc *sc, int vcpu);
+
+int svm_wrmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t val,
+    bool *retu);
+int svm_rdmsr(struct svm_softc *sc, int vcpu, u_int num, uint64_t *result,
+    bool *retu);
+
+#endif	/* _SVM_MSR_H_ */

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/ept.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/ept.c	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/ept.c	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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: projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.h
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.h	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmcs.h	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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: projects/bhyve_svm/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmx.c	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmx.c	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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.
@@ -2077,6 +2052,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;
@@ -2214,7 +2229,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;
@@ -2223,7 +2238,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:
@@ -2234,7 +2249,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;
@@ -2522,6 +2537,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);
 
 	/*
@@ -2623,6 +2640,8 @@ vmx_run(void *arg, int vcpu, register_t 
 	    vmexit->exitcode);
 
 	VMCLEAR(vmcs);
+	vmx_msr_guest_exit(vmx, vcpu);
+
 	return (0);
 }
 

Modified: projects/bhyve_svm/sys/amd64/vmm/intel/vmx.h
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmx.h	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmx.h	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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: projects/bhyve_svm/sys/amd64/vmm/intel/vmx_msr.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmx_msr.c	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmx_msr.c	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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: projects/bhyve_svm/sys/amd64/vmm/intel/vmx_msr.h
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/intel/vmx_msr.h	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/vmm/intel/vmx_msr.h	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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: projects/bhyve_svm/sys/amd64/vmm/vmm.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/vmm.c	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/amd64/vmm/vmm.c	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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));
@@ -1456,7 +1451,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);
@@ -1464,7 +1458,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);
 
@@ -1906,12 +1899,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: projects/bhyve_svm/sys/modules/vmm/Makefile
==============================================================================
--- projects/bhyve_svm/sys/modules/vmm/Makefile	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/modules/vmm/Makefile	Sat Sep 20 21:46:31 2014	(r271912)
@@ -20,7 +20,6 @@ SRCS+=	vmm.c		\
 	vmm_ipi.c	\
 	vmm_lapic.c	\
 	vmm_mem.c	\
-	vmm_msr.c	\
 	vmm_stat.c	\
 	vmm_util.c	\
 	x86.c		\
@@ -48,7 +47,8 @@ SRCS+=	ept.c		\
 SRCS+=	vmcb.c		\
 	svm.c		\
 	npt.c		\
-	amdv.c		
+	amdv.c		\
+	svm_msr.c
 	
 OBJS=	vmx_support.o svm_support.o
 

Modified: projects/bhyve_svm/sys/x86/include/specialreg.h
==============================================================================
--- projects/bhyve_svm/sys/x86/include/specialreg.h	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/sys/x86/include/specialreg.h	Sat Sep 20 21:46:31 2014	(r271912)
@@ -438,6 +438,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: projects/bhyve_svm/usr.sbin/bhyve/bhyverun.c
==============================================================================
--- projects/bhyve_svm/usr.sbin/bhyve/bhyverun.c	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/usr.sbin/bhyve/bhyverun.c	Sat Sep 20 21:46:31 2014	(r271912)
@@ -818,6 +818,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: projects/bhyve_svm/usr.sbin/bhyve/xmsr.c
==============================================================================
--- projects/bhyve_svm/usr.sbin/bhyve/xmsr.c	Sat Sep 20 21:02:54 2014	(r271911)
+++ projects/bhyve_svm/usr.sbin/bhyve/xmsr.c	Sat Sep 20 21:46:31 2014	(r271912)
@@ -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);
+}
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-projects mailing list