git: 0912408a281f - main - vmm: fix HLT loop while vcpu has requested virtual interrupts
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 26 Apr 2023 08:38:55 UTC
The branch main has been updated by corvink:
URL: https://cgit.FreeBSD.org/src/commit/?id=0912408a281f203c43d0b3f73c38117336588342
commit 0912408a281f203c43d0b3f73c38117336588342
Author: Vitaliy Gusev <gusev.vitaliy@gmail.com>
AuthorDate: 2023-04-26 08:17:50 +0000
Commit: Corvin Köhne <corvink@FreeBSD.org>
CommitDate: 2023-04-26 08:38:46 +0000
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
---
sys/amd64/vmm/intel/vmx.c | 44 +++++++++++++++++++-------------------------
1 file 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);