git: 743938876959 - stable/13 - vmm: fix HLT loop while vcpu has requested virtual interrupts

From: Corvin Köhne <corvink_at_FreeBSD.org>
Date: Mon, 08 May 2023 08:25:33 UTC
The branch stable/13 has been updated by corvink:

URL: https://cgit.FreeBSD.org/src/commit/?id=74393887695971d59e108b950e27d21b3070e1fc

commit 74393887695971d59e108b950e27d21b3070e1fc
Author:     Vitaliy Gusev <gusev.vitaliy@gmail.com>
AuthorDate: 2023-04-26 08:17:50 +0000
Commit:     Corvin Köhne <corvink@FreeBSD.org>
CommitDate: 2023-05-08 08:21:32 +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
    
    (cherry picked from commit 0912408a281f203c43d0b3f73c38117336588342)
---
 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);