aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaliy Gusev <gusev.vitaliy@gmail.com>2023-04-26 08:17:50 +0000
committerCorvin Köhne <corvink@FreeBSD.org>2023-04-26 08:38:46 +0000
commit0912408a281f203c43d0b3f73c38117336588342 (patch)
tree07f1c4841a727064eb593fffac4777d1fd337d01
parentb9600db494a04db6fbf1a16dbcf92f7c64d5e863 (diff)
downloadsrc-0912408a281f203c43d0b3f73c38117336588342.tar.gz
src-0912408a281f203c43d0b3f73c38117336588342.zip
vmm: fix HLT loop while vcpu has requested virtual interrupts
This fixes the detection of pending interrupts when pirval is 0 and the pending bit is set More information how this situation occurs, can be found here: https://github.com/freebsd/freebsd-src/blob/c5b5f2d8086f540fefe4826da013dd31d4e45fe8/sys/amd64/vmm/intel/vmx.c#L4016-L4031 Reviewed by: corvink, markj Fixes: 02cc877968bbcd57695035c67114a67427f54549 ("Recognize a pending virtual interrupt while emulating the halt instruction.") MFC after: 1 week Sponsored by: vStack Differential Revision: https://reviews.freebsd.org/D39620
-rw-r--r--sys/amd64/vmm/intel/vmx.c44
1 files changed, 19 insertions, 25 deletions
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 91406f0614ce..32e53de4e8ee 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -3763,7 +3763,8 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
struct pir_desc *pir_desc;
struct LAPIC *lapic;
uint64_t pending, pirval;
- uint32_t ppr, vpr;
+ uint8_t ppr, vpr, rvi;
+ struct vm_exit *vmexit;
int i;
/*
@@ -3774,31 +3775,26 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
vlapic_vtx = (struct vlapic_vtx *)vlapic;
pir_desc = vlapic_vtx->pir_desc;
+ lapic = vlapic->apic_page;
- pending = atomic_load_acq_long(&pir_desc->pending);
- 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.
- */
- struct vm_exit *vmexit;
- uint8_t rvi, ppr;
-
- vmexit = vm_exitinfo(vlapic->vcpu);
- KASSERT(vmexit->exitcode == VM_EXITCODE_HLT,
- ("vmx_pending_intr: exitcode not 'HLT'"));
- rvi = vmexit->u.hlt.intr_status & APIC_TPR_INT;
- lapic = vlapic->apic_page;
- ppr = lapic->ppr & APIC_TPR_INT;
- if (rvi > ppr) {
- return (1);
- }
+ /*
+ * 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 30.2.1 in the Intel SDM Volume 3.
+ */
+ vmexit = vm_exitinfo(vlapic->vcpu);
+ KASSERT(vmexit->exitcode == VM_EXITCODE_HLT,
+ ("vmx_pending_intr: exitcode not 'HLT'"));
+ rvi = vmexit->u.hlt.intr_status & APIC_TPR_INT;
+ ppr = lapic->ppr & APIC_TPR_INT;
+ if (rvi > ppr)
+ return (1);
+ pending = atomic_load_acq_long(&pir_desc->pending);
+ if (!pending)
return (0);
- }
/*
* If there is an interrupt pending then it will be recognized only
@@ -3807,8 +3803,6 @@ vmx_pending_intr(struct vlapic *vlapic, int *vecptr)
* Special case: if the processor priority is zero then any pending
* interrupt will be recognized.
*/
- lapic = vlapic->apic_page;
- ppr = lapic->ppr & APIC_TPR_INT;
if (ppr == 0)
return (1);