Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 21 Dec 2017 18:30:11 +0000 (UTC)
From:      Tycho Nightingale <tychon@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r327065 - head/sys/amd64/vmm/intel
Message-ID:  <201712211830.vBLIUBYE075062@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tychon
Date: Thu Dec 21 18:30:11 2017
New Revision: 327065
URL: https://svnweb.freebsd.org/changeset/base/327065

Log:
  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

Modified:
  head/sys/amd64/vmm/intel/vmx.c

Modified: head/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- head/sys/amd64/vmm/intel/vmx.c	Thu Dec 21 16:25:33 2017	(r327064)
+++ head/sys/amd64/vmm/intel/vmx.c	Thu Dec 21 18:30:11 2017	(r327065)
@@ -3174,9 +3174,29 @@ 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
 	 * if its priority is greater than the processor priority.
@@ -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);
 		}
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201712211830.vBLIUBYE075062>