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>