Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Sep 2014 01:10:53 +0000 (UTC)
From:      Neel Natu <neel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r271342 - projects/bhyve_svm/sys/amd64/vmm/amd
Message-ID:  <201409100110.s8A1Are1006483@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: neel
Date: Wed Sep 10 01:10:53 2014
New Revision: 271342
URL: http://svnweb.freebsd.org/changeset/base/271342

Log:
  Allow guest read access to MSR_EFER without hypervisor intervention.
  
  Dirty the VMCB_CACHE_CR state cache when MSR_EFER is modified.

Modified:
  projects/bhyve_svm/sys/amd64/vmm/amd/svm.c

Modified: projects/bhyve_svm/sys/amd64/vmm/amd/svm.c
==============================================================================
--- projects/bhyve_svm/sys/amd64/vmm/amd/svm.c	Wed Sep 10 00:19:33 2014	(r271341)
+++ projects/bhyve_svm/sys/amd64/vmm/amd/svm.c	Wed Sep 10 01:10:53 2014	(r271342)
@@ -385,8 +385,12 @@ svm_msr_rd_ok(uint8_t *perm_bitmap, uint
 }
 
 static __inline void
-vcpu_set_dirty(struct svm_vcpu *vcpustate, uint32_t dirtybits)
+vcpu_set_dirty(struct svm_softc *sc, int vcpu, uint32_t dirtybits)
 {
+	struct svm_vcpu *vcpustate;
+
+	vcpustate = svm_get_vcpu(sc, vcpu);
+
 	vcpustate->dirty |= dirtybits;
 }
 
@@ -434,6 +438,7 @@ svm_vminit(struct vm *vm, pmap_t pmap)
 	svm_msr_rw_ok(svm_sc->msr_bitmap, MSR_PAT);
 
 	svm_msr_rd_ok(svm_sc->msr_bitmap, MSR_TSC);
+	svm_msr_rd_ok(svm_sc->msr_bitmap, MSR_EFER);
 
 	 /* Intercept access to all I/O ports. */
 	memset(svm_sc->iopm_bitmap, 0xFF, sizeof(svm_sc->iopm_bitmap));
@@ -682,25 +687,23 @@ svm_handle_inst_emul(struct vmcb *vmcb, 
 }
 
 /*
- * Special handling of EFER MSR.
- * SVM guest must have SVM EFER bit set, prohibit guest from cleareing SVM
- * enable bit in EFER.
+ * Intercept access to MSR_EFER to prevent the guest from clearing the
+ * SVM enable bit.
  */
 static void
-svm_efer(struct svm_softc *svm_sc, int vcpu, boolean_t write)
+svm_write_efer(struct svm_softc *sc, int vcpu, uint32_t edx, uint32_t eax)
 {
-	struct svm_regctx *swctx;
 	struct vmcb_state *state;
-	
-	state = svm_get_vmcb_state(svm_sc, vcpu);
-	swctx = svm_get_guest_regctx(svm_sc, vcpu);
+	uint64_t oldval;
 
-	if (write) {
-		state->efer = ((swctx->e.g.sctx_rdx & (uint32_t)~0) << 32) |
-				((uint32_t)state->rax) | EFER_SVM;
-	} else {
-		state->rax = (uint32_t)state->efer;
-		swctx->e.g.sctx_rdx = (uint32_t)(state->efer >> 32);
+	state = svm_get_vmcb_state(sc, vcpu);
+
+	oldval = state->efer;
+	state->efer = (uint64_t)edx << 32 | eax | 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);
 	}
 }
 
@@ -775,8 +778,10 @@ svm_vmexit(struct svm_softc *svm_sc, int
 			edx = ctx->e.g.sctx_rdx;
 			
 			if (ecx == MSR_EFER) {
-				VCPU_CTR0(svm_sc->vm, vcpu,"VMEXIT EFER\n");
-				svm_efer(svm_sc, vcpu, info1);
+				KASSERT(info1 != 0, ("rdmsr(MSR_EFER) is not "
+				    "emulated: info1(%#lx) info2(%#lx)",
+				    info1, info2));
+				svm_write_efer(svm_sc, vcpu, edx, eax);
 				break;
 			}
 		
@@ -1186,7 +1191,7 @@ check_asid(struct svm_softc *sc, int vcp
 		vcpustate->asid.num = asid[thiscpu].num;
 
 		ctrl->asid = vcpustate->asid.num;
-		vcpu_set_dirty(vcpustate, VMCB_CACHE_ASID);
+		vcpu_set_dirty(sc, vcpuid, VMCB_CACHE_ASID);
 		/*
 		 * If this cpu supports "flush-by-asid" then the TLB
 		 * was not flushed after the generation bump. The TLB
@@ -1253,7 +1258,7 @@ svm_vmrun(void *arg, int vcpu, register_
 		/*
 		 * Invalidate the VMCB state cache by marking all fields dirty.
 		 */
-		vcpu_set_dirty(vcpustate, 0xffffffff);
+		vcpu_set_dirty(svm_sc, vcpu, 0xffffffff);
 
 		/*
 		 * XXX



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