svn commit: r270511 - projects/bhyve_svm/sys/amd64/vmm/amd
Neel Natu
neel at FreeBSD.org
Mon Aug 25 00:58:21 UTC 2014
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 at 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_ */
More information about the svn-src-projects
mailing list