aboutsummaryrefslogtreecommitdiff
path: root/sys/amd64/vmm
diff options
context:
space:
mode:
authorTycho Nightingale <tychon@FreeBSD.org>2017-12-21 18:30:11 +0000
committerTycho Nightingale <tychon@FreeBSD.org>2017-12-21 18:30:11 +0000
commit9e33a616939fcff87f7539e3c41323deca5c74ce (patch)
treea19bb1ae5f0668a9bcb4225395ce38859f6c93de /sys/amd64/vmm
parent76df519fe099c90ba2188cd1ca6846181b24b4b2 (diff)
downloadsrc-9e33a616939fcff87f7539e3c41323deca5c74ce.tar.gz
src-9e33a616939fcff87f7539e3c41323deca5c74ce.zip
Recognize a pending virtual interrupt while emulating the halt instruction.
Reviewed by: grehan, rgrimes Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D13573
Notes
Notes: svn path=/head/; revision=327065
Diffstat (limited to 'sys/amd64/vmm')
-rw-r--r--sys/amd64/vmm/intel/vmx.c28
1 files changed, 24 insertions, 4 deletions
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index e563bed62127..f803862079c4 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -3174,8 +3174,28 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
pir_desc = vlapic_vtx->pir_desc;
pending = atomic_load_acq_long(&pir_desc->pending);
- if (!pending)
- return (0); /* common case */
+ if (!pending) {
+ /*
+ * While a virtual interrupt may have already been
+ * processed the actual delivery maybe pending the
+ * interruptibility of the guest. Recognize a pending
+ * interrupt by reevaluating virtual interrupts
+ * following Section 29.2.1 in the Intel SDM Volume 3.
+ */
+ uint64_t val;
+ uint8_t rvi, ppr;
+
+ vmx_getreg(vlapic_vtx->vmx, vlapic->vcpuid,
+ VMCS_IDENT(VMCS_GUEST_INTR_STATUS), &val);
+ rvi = val & APIC_TPR_INT;
+ lapic = vlapic->apic_page;
+ ppr = lapic->ppr & APIC_TPR_INT;
+ if (rvi > ppr) {
+ return (1);
+ }
+
+ return (0);
+ }
/*
* If there is an interrupt pending then it will be recognized only
@@ -3185,7 +3205,7 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
* interrupt will be recognized.
*/
lapic = vlapic->apic_page;
- ppr = lapic->ppr & 0xf0;
+ ppr = lapic->ppr & APIC_TPR_INT;
if (ppr == 0)
return (1);
@@ -3195,7 +3215,7 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
for (i = 3; i >= 0; i--) {
pirval = pir_desc->pir[i];
if (pirval != 0) {
- vpr = (i * 64 + flsl(pirval) - 1) & 0xf0;
+ vpr = (i * 64 + flsl(pirval) - 1) & APIC_TPR_INT;
return (vpr > ppr);
}
}