Date: Mon, 25 Aug 2014 00:58:21 +0000 (UTC) From: Neel Natu <neel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r270511 - projects/bhyve_svm/sys/amd64/vmm/amd Message-ID: <201408250058.s7P0wLHM036232@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: neel Date: Mon Aug 25 00:58:20 2014 New Revision: 270511 URL: http://svnweb.freebsd.org/changeset/base/270511 Log: An exception is allowed to be injected even if the vcpu is in an interrupt shadow, so move the check for pending exception before bailing out due to an interrupt shadow. Change return type of 'vmcb_eventinject()' to a void and convert all error returns into KASSERTs. Fix VMCB_EXITINTINFO_EC(x) and VMCB_EXITINTINFO_TYPE(x) to do the shift before masking the result. Reviewed by: Anish Gupta (akgupt3@gmail.com) Modified: projects/bhyve_svm/sys/amd64/vmm/amd/svm.c projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.c projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h Modified: projects/bhyve_svm/sys/amd64/vmm/amd/svm.c ============================================================================== --- projects/bhyve_svm/sys/amd64/vmm/amd/svm.c Sun Aug 24 21:21:54 2014 (r270510) +++ projects/bhyve_svm/sys/amd64/vmm/amd/svm.c Mon Aug 25 00:58:20 2014 (r270511) @@ -702,6 +702,9 @@ svm_vmexit(struct svm_softc *svm_sc, int vmexit->exitcode = VM_EXITCODE_VMX; vmexit->u.vmx.status = 0; + KASSERT((ctrl->eventinj & VMCB_EVENTINJ_VALID) == 0, ("%s: event " + "injection valid bit is set %#lx", __func__, ctrl->eventinj)); + switch (code) { case VMCB_EXIT_MC: /* Machine Check. */ vmm_stat_incr(svm_sc->vm, vcpu, VMEXIT_MTRAP, 1); @@ -930,11 +933,8 @@ svm_inject_nmi(struct svm_softc *svm_sc, if (!vm_nmi_pending(svm_sc->vm, vcpu)) return (0); - /* Inject NMI, vector number is not used.*/ - if (vmcb_eventinject(ctrl, VMCB_EVENTINJ_TYPE_NMI, IDT_NMI, 0, false)) { - VCPU_CTR0(svm_sc->vm, vcpu, "SVM:NMI injection failed.\n"); - return (EIO); - } + /* Inject NMI, vector number is not used.*/ + vmcb_eventinject(ctrl, VMCB_EVENTINJ_TYPE_NMI, IDT_NMI, 0, false); /* Acknowledge the request is accepted.*/ vm_nmi_clear(svm_sc->vm, vcpu); @@ -961,6 +961,13 @@ svm_inj_interrupts(struct svm_softc *svm state = svm_get_vmcb_state(svm_sc, vcpu); ctrl = svm_get_vmcb_ctrl(svm_sc, vcpu); + if (vm_exception_pending(svm_sc->vm, vcpu, &exc)) { + KASSERT(exc.vector >= 0 && exc.vector < 32, + ("Exception vector% invalid", exc.vector)); + vmcb_eventinject(ctrl, VMCB_EVENTINJ_TYPE_EXCEPTION, exc.vector, + exc.error_code, exc.error_code_valid); + } + /* Can't inject multiple events at once. */ if (ctrl->eventinj & VMCB_EVENTINJ_VALID) { VCPU_CTR1(svm_sc->vm, vcpu, @@ -973,18 +980,7 @@ svm_inj_interrupts(struct svm_softc *svm VCPU_CTR0(svm_sc->vm, vcpu, "SVM:Guest in interrupt shadow.\n"); return; } - - if (vm_exception_pending(svm_sc->vm, vcpu, &exc)) { - KASSERT(exc.vector >= 0 && exc.vector < 32, - ("Exception vector% invalid", exc.vector)); - if (vmcb_eventinject(ctrl, VMCB_EVENTINJ_TYPE_EXCEPTION, - exc.vector, exc.error_code, - exc.error_code_valid)) { - VCPU_CTR1(svm_sc->vm, vcpu, "SVM:Exception%d injection" - " failed.\n", exc.vector); - return; - } - } + /* NMI event has priority over interrupts.*/ if (svm_inject_nmi(svm_sc, vcpu)) { return; @@ -1013,11 +1009,7 @@ svm_inj_interrupts(struct svm_softc *svm return; } - if (vmcb_eventinject(ctrl, VMCB_EVENTINJ_TYPE_INTR, vector, 0, false)) { - VCPU_CTR1(svm_sc->vm, vcpu, "SVM:Event injection failed to" - " vector=%d.\n", vector); - return; - } + vmcb_eventinject(ctrl, VMCB_EVENTINJ_TYPE_INTR, vector, 0, false); if (!extint_pending) { /* Update the Local APIC ISR */ @@ -1067,17 +1059,14 @@ svm_handle_exitintinfo(struct svm_softc */ intinfo = ctrl->exitintinfo; - if (intinfo & VMCB_EXITINTINFO_VALID) { + if (VMCB_EXITINTINFO_VALID(intinfo)) { vmm_stat_incr(svm_sc->vm, vcpu, VCPU_EXITINTINFO, 1); VCPU_CTR1(svm_sc->vm, vcpu, "SVM:EXITINTINFO:0x%lx is valid\n", intinfo); - if (vmcb_eventinject(ctrl, VMCB_EXITINTINFO_TYPE(intinfo), - VMCB_EXITINTINFO_VECTOR(intinfo), - VMCB_EXITINTINFO_EC(intinfo), - VMCB_EXITINTINFO_EC_VALID & intinfo)) { - VCPU_CTR1(svm_sc->vm, vcpu, "SVM:couldn't inject pending" - " interrupt, exitintinfo:0x%lx\n", intinfo); - } + vmcb_eventinject(ctrl, VMCB_EXITINTINFO_TYPE(intinfo), + VMCB_EXITINTINFO_VECTOR(intinfo), + VMCB_EXITINTINFO_EC(intinfo), + VMCB_EXITINTINFO_EC_VALID(intinfo)); } } /* @@ -1198,7 +1187,7 @@ svm_vmrun(void *arg, int vcpu, register_ svm_handle_exitintinfo(svm_sc, vcpu); - (void)svm_inj_interrupts(svm_sc, vcpu, vlapic); + svm_inj_interrupts(svm_sc, vcpu, vlapic); /* Change TSS type to available.*/ setup_tss_type(); Modified: projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.c ============================================================================== --- projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.c Sun Aug 24 21:21:54 2014 (r270510) +++ projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.c Mon Aug 25 00:58:20 2014 (r270511) @@ -371,27 +371,32 @@ vmcb_seg(struct vmcb *vmcb, int type) /* * Inject an event to vcpu as described in section 15.20, "Event injection". */ -int +void vmcb_eventinject(struct vmcb_ctrl *ctrl, int intr_type, int vector, uint32_t error, bool ec_valid) { - if (intr_type < VMCB_EVENTINJ_TYPE_INTR || - intr_type > VMCB_EVENTINJ_TYPE_INTn) { - ERR("Event:%d is not supported by SVM.\n", intr_type); - return (EINVAL); - } - - if (intr_type == VMCB_EVENTINJ_TYPE_EXCEPTION && vector == IDT_NMI) { - ERR("NMI with Exception type is not possible.\n"); - return (EINVAL); - } + KASSERT((ctrl->eventinj & VMCB_EVENTINJ_VALID) == 0, + ("%s: event already pending %#lx", __func__, ctrl->eventinj)); - ctrl->eventinj = (vector & VMCB_EVENTINJ_VECTOR_MASK) | - (intr_type << VMCB_EVENTINJ_INTR_TYPE_SHIFT) | - (ec_valid ? VMCB_EVENTINJ_EC_VALID : 0) | - VMCB_EVENTINJ_VALID; + KASSERT(vector >=0 && vector <= 255, ("%s: invalid vector %d", + __func__, vector)); - ctrl->eventinj |= (uint64_t)error << VMCB_EVENTINJ_ERRCODE_SHIFT; - - return (0); + switch (intr_type) { + case VMCB_EVENTINJ_TYPE_INTR: + case VMCB_EVENTINJ_TYPE_NMI: + case VMCB_EVENTINJ_TYPE_INTn: + break; + case VMCB_EVENTINJ_TYPE_EXCEPTION: + if (vector >= 0 && vector <= 31 && vector != 2) + break; + /* FALLTHROUGH */ + default: + panic("%s: invalid intr_type/vector: %d/%d", __func__, + intr_type, vector); + } + ctrl->eventinj = vector | (intr_type << 8) | VMCB_EVENTINJ_VALID; + if (ec_valid) { + ctrl->eventinj |= VMCB_EVENTINJ_EC_VALID; + ctrl->eventinj |= (uint64_t)error << 32; + } } Modified: projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h ============================================================================== --- projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h Sun Aug 24 21:21:54 2014 (r270510) +++ projects/bhyve_svm/sys/amd64/vmm/amd/vmcb.h Mon Aug 25 00:58:20 2014 (r270511) @@ -109,10 +109,6 @@ #define VMCB_EVENTINJ_EC_VALID BIT(11) /* Error Code valid */ #define VMCB_EVENTINJ_VALID BIT(31) /* Event valid */ -#define VMCB_EVENTINJ_VECTOR_MASK 0xFF -#define VMCB_EVENTINJ_INTR_TYPE_SHIFT 8 -#define VMCB_EVENTINJ_ERRCODE_SHIFT 32 - /* Event types that can be injected */ #define VMCB_EVENTINJ_TYPE_INTR 0 #define VMCB_EVENTINJ_TYPE_NMI 2 @@ -152,11 +148,11 @@ * EXITINTINFO, Interrupt exit info for all intrecepts. * Section 15.7.2, Intercepts during IDT Interrupt Delivery. */ -#define VMCB_EXITINTINFO_VECTOR(x) (x & 0xFF) -#define VMCB_EXITINTINFO_TYPE(x) ((x & 0x7) >> 8) -#define VMCB_EXITINTINFO_EC_VALID BIT(11) -#define VMCB_EXITINTINFO_VALID BIT(31) -#define VMCB_EXITINTINFO_EC(x) ((x & 0xFFFFFFFF) >> 32) +#define VMCB_EXITINTINFO_VECTOR(x) ((x) & 0xFF) +#define VMCB_EXITINTINFO_TYPE(x) (((x) >> 8) & 0x7) +#define VMCB_EXITINTINFO_EC_VALID(x) (((x) & BIT(11)) ? 1 : 0) +#define VMCB_EXITINTINFO_VALID(x) (((x) & BIT(31)) ? 1 : 0) +#define VMCB_EXITINTINFO_EC(x) (((x) >> 32) & 0xFFFFFFFF) /* VMCB save state area segment format */ struct vmcb_segment { @@ -283,7 +279,7 @@ int svm_set_vmcb(struct vmcb *vmcb, uint int vmcb_read(struct vmcb *vmcb, int ident, uint64_t *retval); int vmcb_write(struct vmcb *vmcb, int ident, uint64_t val); struct vmcb_segment *vmcb_seg(struct vmcb *vmcb, int type); -int vmcb_eventinject(struct vmcb_ctrl *ctrl, int type, int vector, +void vmcb_eventinject(struct vmcb_ctrl *ctrl, int type, int vector, uint32_t error, bool ec_valid); #endif /* _VMCB_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201408250058.s7P0wLHM036232>