Index: /trunk/include/VBox/err.h
===================================================================
--- /trunk/include/VBox/err.h	(revision 60715)
+++ /trunk/include/VBox/err.h	(revision 60716)
@@ -2736,4 +2736,13 @@
 
 
+/** @name APIC Status Codes
+ * @{
+ */
+/** No pending interrupt. */
+#define VERR_APIC_INTR_NOT_PENDING                  (-6700)
+/** Pending interrupt is masked by TPR. */
+#define VERR_APIC_INTR_MASKED_BY_TPR                (-6701)
+/** @} */
+
 /* SED-END */
 
Index: /trunk/include/VBox/vmm/pdmapi.h
===================================================================
--- /trunk/include/VBox/vmm/pdmapi.h	(revision 60715)
+++ /trunk/include/VBox/vmm/pdmapi.h	(revision 60716)
@@ -51,9 +51,8 @@
 VMM_INT_DECL(int)       PDMIoApicSendMsi(PVM pVM, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc);
 VMM_INT_DECL(bool)      PDMHasApic(PVM pVM);
-VMM_INT_DECL(int)       PDMApicHasPendingIrq(PVM pVM, bool *pfPending);
 VMMDECL(VBOXSTRICTRC)   PDMApicSetBaseMsr(PVMCPU pVCpu, uint64_t u64Base);
 VMMDECL(VBOXSTRICTRC)   PDMApicGetBaseMsr(PVMCPU pVCpu, uint64_t *pu64Base, bool fIgnoreErrors);
 VMMDECL(int)            PDMApicSetTPR(PVMCPU pVCpu, uint8_t u8TPR);
-VMMDECL(int)            PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending, uint8_t *pu8PendingIrq);
+VMMDECL(int)            PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending, uint8_t *pu8PendingIntr);
 VMM_INT_DECL(VBOXSTRICTRC) PDMApicWriteMsr(PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Value);
 VMM_INT_DECL(VBOXSTRICTRC) PDMApicReadMsr(PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Value);
Index: /trunk/include/VBox/vmm/pdmdev.h
===================================================================
--- /trunk/include/VBox/vmm/pdmdev.h	(revision 60715)
+++ /trunk/include/VBox/vmm/pdmdev.h	(revision 60716)
@@ -1154,25 +1154,13 @@
      * Get a pending interrupt.
      *
-     * @returns Pending interrupt number, -1 if no interrupt is
-     *          pending.
+     * @returns VBox status code.
      * @param   pDevIns         Device instance of the APIC.
      * @param   pVCpu           The cross context virtual CPU structure.
-     * @param   puTagSrc        Where to return the tag source (tracing purposes).
-     * @remarks Caller enters the PDM critical section
-     */
-    DECLR3CALLBACKMEMBER(int, pfnGetInterruptR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t *puTagSrc));
-
-    /**
-     * Check if the APIC has a pending interrupt/if a TPR change would activate one.
-     *
-     * @returns true if an interrupt is pending, false otherwise.
-     * @param   pDevIns         Device instance of the APIC.
-     * @param   pVCpu           The cross context virtual CPU structure.
-     * @param   pu8PendingIrq   Where to store the highest priority pending IRQ
-     *                          (optional, can be NULL).
-     * @remarks Unlike the other callbacks, the PDM lock may not always be entered
-     *          prior to calling this method.
-     */
-    DECLR3CALLBACKMEMBER(bool, pfnHasPendingIrqR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8PendingIrq));
+     * @param   pu8Vector       Where to store the vector.
+     * @param   pu32TagSrc      Where to return the tag source (tracing
+     *                          purposes).
+     * @remarks Caller enters the PDM critical section.
+     */
+    DECLR3CALLBACKMEMBER(int, pfnGetInterruptR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8Vector, uint32_t *pu32TagSrc));
 
     /**
@@ -1213,7 +1201,11 @@
      * @param   pDevIns         Device instance of the APIC.
      * @param   pVCpu           The cross context virtual CPU structure.
+     * @param   pfPending       Where to store if there is an interrupt pending
+     *                          (optional, can be NULL).
+     * @param   pu8PendingIntr  Where to store the pending interrupt vector
+     *                          (optional, can be NULL).
      * @remarks Caller enters the PDM critical section.
      */
-    DECLR3CALLBACKMEMBER(uint8_t, pfnGetTprR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
+    DECLR3CALLBACKMEMBER(uint8_t, pfnGetTprR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr));
 
     /**
@@ -1296,6 +1288,4 @@
     /** The name of the RC GetInterrupt entry point. */
     const char         *pszGetInterruptRC;
-    /** The name of the RC HasPendingIrq entry point. */
-    const char         *pszHasPendingIrqRC;
     /** The name of the RC SetBaseMsr entry point. */
     const char         *pszSetBaseMsrRC;
@@ -1319,6 +1309,4 @@
     /** The name of the R0 GetInterrupt entry point. */
     const char         *pszGetInterruptR0;
-    /** The name of the R0 HasPendingIrq entry point. */
-    const char         *pszHasPendingIrqR0;
     /** The name of the R0 SetBaseMsr entry point. */
     const char         *pszSetBaseMsrR0;
@@ -1344,5 +1332,5 @@
 
 /** Current PDMAPICREG version number. */
-#define PDM_APICREG_VERSION                     PDM_VERSION_MAKE(0xfff6, 3, 0)
+#define PDM_APICREG_VERSION                     PDM_VERSION_MAKE(0xfff6, 4, 0)
 
 
Index: /trunk/src/VBox/Devices/PC/DevAPIC.cpp
===================================================================
--- /trunk/src/VBox/Devices/PC/DevAPIC.cpp	(revision 60715)
+++ /trunk/src/VBox/Devices/PC/DevAPIC.cpp	(revision 60716)
@@ -520,4 +520,45 @@
     }
 }
+
+
+static int apic_get_ppr_zero_tpr(APICState *pApic)
+{
+    return Apic256BitReg_FindLastSetBit(&pApic->isr, 0);
+}
+
+
+/* Check if the APIC has a pending interrupt/if a TPR change would active one. */
+static bool apicHasPendingIntr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8PendingIrq)
+{
+    APICDeviceInfo *pDev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
+    if (!pDev)
+        return false;
+
+    /* We don't perform any locking here as that would cause a lot of contention for VT-x/AMD-V. */
+
+    APICState *pApic = apicGetStateById(pDev, pVCpu->idCpu);
+
+    /*
+     * All our callbacks now come from single IOAPIC, thus locking
+     * seems to be excessive now
+     */
+    /** @todo check excessive locking whatever... */
+    int irrv = Apic256BitReg_FindLastSetBit(&pApic->irr, -1);
+    if (irrv < 0)
+        return false;
+
+    int isrv = apic_get_ppr_zero_tpr(pApic);
+
+    if (isrv && (irrv & 0xf0) <= (isrv & 0xf0))
+        return false;
+
+    if (pu8PendingIrq)
+    {
+        Assert(irrv >= 0 && irrv <= (int)UINT8_MAX);
+        *pu8PendingIrq = (uint8_t)irrv;
+    }
+    return true;
+}
+
 
 static int apic_bus_deliver(APICDeviceInfo *pDev,
@@ -653,5 +694,5 @@
 }
 
-PDMBOTHCBDECL(uint8_t) apicGetTPR(PPDMDEVINS pDevIns, PVMCPU pVCpu)
+PDMBOTHCBDECL(uint8_t) apicGetTPR(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr)
 {
     /* We don't perform any locking here as that would cause a lot of contention for VT-x/AMD-V. */
@@ -659,4 +700,7 @@
     APICState *pApic = apicGetStateById(pDev, pVCpu->idCpu);
     Log2(("apicGetTPR: returns %#x\n", pApic->tpr));
+
+    if (pfPending)
+        *pfPending = apicHasPendingIntr(pDevIns, pVCpu, pu8PendingIntr);
     return pApic->tpr;
 }
@@ -1203,9 +1247,4 @@
 }
 
-static int apic_get_ppr_zero_tpr(APICState *pApic)
-{
-    return Apic256BitReg_FindLastSetBit(&pApic->isr, 0);
-}
-
 static int apic_get_arb_pri(APICState const *pApic)
 {
@@ -1231,37 +1270,4 @@
         return false;
     apicCpuSetInterrupt(pDev, pApic);
-    return true;
-}
-
-/* Check if the APIC has a pending interrupt/if a TPR change would active one. */
-PDMBOTHCBDECL(bool) apicHasPendingIrq(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8PendingIrq)
-{
-    APICDeviceInfo *pDev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
-    if (!pDev)
-        return false;
-
-    /* We don't perform any locking here as that would cause a lot of contention for VT-x/AMD-V. */
-
-    APICState *pApic = apicGetStateById(pDev, pVCpu->idCpu);
-
-    /*
-     * All our callbacks now come from single IOAPIC, thus locking
-     * seems to be excessive now
-     */
-    /** @todo check excessive locking whatever... */
-    int irrv = Apic256BitReg_FindLastSetBit(&pApic->irr, -1);
-    if (irrv < 0)
-        return false;
-
-    int ppr = apic_get_ppr_zero_tpr(pApic);
-
-    if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
-        return false;
-
-    if (pu8PendingIrq)
-    {
-        Assert(irrv >= 0 && irrv <= (int)UINT8_MAX);
-        *pu8PendingIrq = (uint8_t)irrv;
-    }
     return true;
 }
@@ -1450,5 +1456,5 @@
 
 
-PDMBOTHCBDECL(int) apicGetInterrupt(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t *puTagSrc)
+PDMBOTHCBDECL(int) apicGetInterrupt(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8Vector, uint32_t *pu32TagSrc)
 {
     APICDeviceInfo *pDev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
@@ -1457,5 +1463,5 @@
     {
         Log(("apic_get_interrupt: returns -1 (!pDev)\n"));
-        return -1;
+        return VERR_APIC_INTR_NOT_PENDING;
     }
 
@@ -1467,5 +1473,5 @@
     {
         Log(("CPU%d: apic_get_interrupt: returns -1 (APIC_SV_ENABLE)\n", pApic->phys_id));
-        return -1;
+        return VERR_APIC_INTR_NOT_PENDING;
     }
 
@@ -1475,12 +1481,13 @@
     {
         Log(("CPU%d: apic_get_interrupt: returns -1 (irr)\n", pApic->phys_id));
-        return -1;
+        return VERR_APIC_INTR_NOT_PENDING;
     }
 
     if (pApic->tpr && (uint32_t)intno <= pApic->tpr)
     {
-        *puTagSrc = 0;
-        Log(("apic_get_interrupt: returns %d (sp)\n", pApic->spurious_vec & 0xff));
-        return pApic->spurious_vec & 0xff;
+        *pu32TagSrc = 0;
+        *pu8Vector = pApic->spurious_vec & 0xff;
+        Log(("apic_get_interrupt: returns %d (sp)\n", *pu8Vector));
+        return VINF_SUCCESS;
     }
 
@@ -1488,11 +1495,12 @@
     Apic256BitReg_SetBit(&pApic->isr, intno);
 
-    *puTagSrc = pApic->auTags[intno];
+    *pu32TagSrc = pApic->auTags[intno];
     pApic->auTags[intno] = 0;
 
     apic_update_irq(pDev, pApic);
 
-    LogFlow(("CPU%d: apic_get_interrupt: returns %d / %#x\n", pApic->phys_id, intno, *puTagSrc));
-    return intno;
+    LogFlow(("CPU%d: apic_get_interrupt: returns %d / %#x\n", pApic->phys_id, intno, *pu32TagSrc));
+    *pu8Vector = (uint8_t)intno;
+    return VINF_SUCCESS;
 }
 
@@ -2409,5 +2417,4 @@
     ApicReg.u32Version              = PDM_APICREG_VERSION;
     ApicReg.pfnGetInterruptR3       = apicGetInterrupt;
-    ApicReg.pfnHasPendingIrqR3      = apicHasPendingIrq;
     ApicReg.pfnSetBaseMsrR3         = apicSetBase;
     ApicReg.pfnGetBaseMsrR3         = apicGetBase;
@@ -2422,5 +2429,4 @@
     {
         ApicReg.pszGetInterruptRC   = "apicGetInterrupt";
-        ApicReg.pszHasPendingIrqRC  = "apicHasPendingIrq";
         ApicReg.pszSetBaseMsrRC     = "apicSetBase";
         ApicReg.pszGetBaseMsrRC     = "apicGetBase";
@@ -2434,5 +2440,4 @@
 
         ApicReg.pszGetInterruptR0   = "apicGetInterrupt";
-        ApicReg.pszHasPendingIrqR0  = "apicHasPendingIrq";
         ApicReg.pszSetBaseMsrR0     = "apicSetBase";
         ApicReg.pszGetBaseMsrR0     = "apicGetBase";
@@ -2448,5 +2453,4 @@
     {
         ApicReg.pszGetInterruptRC   = NULL;
-        ApicReg.pszHasPendingIrqRC  = NULL;
         ApicReg.pszSetBaseMsrRC     = NULL;
         ApicReg.pszGetBaseMsrRC     = NULL;
@@ -2460,5 +2464,4 @@
 
         ApicReg.pszGetInterruptR0   = NULL;
-        ApicReg.pszHasPendingIrqR0  = NULL;
         ApicReg.pszSetBaseMsrR0     = NULL;
         ApicReg.pszGetBaseMsrR0     = NULL;
Index: /trunk/src/VBox/VMM/VMMAll/APICAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/APICAll.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMAll/APICAll.cpp	(revision 60716)
@@ -429,27 +429,4 @@
     }
     return rcNotFound;
-}
-
-
-/**
- * Gets the highest priority pending interrupt.
- *
- * @returns true if any interrupt is pending, false otherwise.
- * @param   pVCpu               The cross context virtual CPU structure.
- * @param   pu8PendingIntr      Where to store the interrupt vector if the
- *                              interrupt is pending, optional can be NULL.
- */
-static bool apicGetHighestPendingInterrupt(PVMCPU pVCpu, uint8_t *pu8PendingIntr)
-{
-    PCXAPICPAGE pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
-    int const irrv = apicGetLastSetBit(&pXApicPage->irr, -1);
-    if (irrv >= 0)
-    {
-        Assert(irrv <= (int)UINT8_MAX);
-        if (pu8PendingIntr)
-            *pu8PendingIntr = (uint8_t)irrv;
-        return true;
-    }
-    return false;
 }
 
@@ -2112,10 +2089,43 @@
 
 /**
+ * Gets the highest priority pending interrupt.
+ *
+ * @returns true if any interrupt is pending, false otherwise.
+ * @param   pVCpu               The cross context virtual CPU structure.
+ * @param   pu8PendingIntr      Where to store the interrupt vector if the
+ *                              interrupt is pending (optional, can be NULL).
+ */
+static bool apicGetHighestPendingInterrupt(PVMCPU pVCpu, uint8_t *pu8PendingIntr)
+{
+    PCXAPICPAGE pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
+    int const irrv = apicGetLastSetBit(&pXApicPage->irr, -1);
+    if (irrv >= 0)
+    {
+        Assert(irrv <= (int)UINT8_MAX);
+        if (pu8PendingIntr)
+            *pu8PendingIntr = (uint8_t)irrv;
+        return true;
+    }
+    return false;
+}
+
+
+/**
  * @interface_method_impl{PDMAPICREG,pfnGetTprR3}
  */
-VMMDECL(uint8_t) APICGetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu)
+VMMDECL(uint8_t) APICGetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr)
 {
     VMCPU_ASSERT_EMT(pVCpu);
     PCXAPICPAGE pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
+
+    if (pfPending)
+    {
+        /*
+         * Just return whatever the highest pending interrupt is in the IRR.
+         * The caller is responsible for figuring out if it's masked by the TPR etc.
+         */
+        *pfPending = apicGetHighestPendingInterrupt(pVCpu, pu8PendingIntr);
+    }
+
     return pXApicPage->tpr.u8Tpr;
 }
@@ -2282,18 +2292,11 @@
 
 /**
- * @interface_method_impl{PDMAPICREG,pfnHasPendingIrqR3}
- */
-VMMDECL(bool) APICHasPendingIrq(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8PendingIrq)
-{
-    return apicGetHighestPendingInterrupt(pVCpu, pu8PendingIrq);
-}
-
-
-/**
  * @interface_method_impl{PDMAPICREG,pfnGetInterruptR3}
  */
-VMMDECL(int) APICGetInterrupt(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t *puTagSrc)
-{
-    VMCPU_ASSERT_EMT(pVCpu);
+VMMDECL(int) APICGetInterrupt(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8Vector, uint32_t *pu32TagSrc)
+{
+    VMCPU_ASSERT_EMT(pVCpu);
+    Assert(pu8Vector);
+    NOREF(pu32TagSrc);
 
     LogFlow(("APIC%u: APICGetInterrupt\n", pVCpu->idCpu));
@@ -2306,5 +2309,5 @@
         APICUpdatePendingInterrupts(pVCpu);
         int const irrv = apicGetLastSetBit(&pXApicPage->irr, -1);
-        if (irrv >= 0)
+        if (RT_LIKELY(irrv >= 0))
         {
             Assert(irrv <= (int)UINT8_MAX);
@@ -2316,14 +2319,19 @@
              */
             uint8_t const uTpr = pXApicPage->tpr.u8Tpr;
-            if (uTpr > 0 && uVector <= uTpr)
-            {
-                Log2(("APIC%u: APICGetInterrupt: Spurious interrupt. uVector=%#x uTpr=%#x SpuriousVector=%#x\n", pVCpu->idCpu,
+            if (uTpr > 0 && XAPIC_TPR_GET_TP(uVector) <= XAPIC_TPR_GET_TP(uTpr))
+            {
+                Log2(("APIC%u: APICGetInterrupt: Interrupt masked. uVector=%#x uTpr=%#x SpuriousVector=%#x\n", pVCpu->idCpu,
                       uVector, uTpr, pXApicPage->svr.u.u8SpuriousVector));
-                return pXApicPage->svr.u.u8SpuriousVector;
-            }
-
+                *pu8Vector = uVector;
+                return VERR_APIC_INTR_MASKED_BY_TPR;
+            }
+
+            /*
+             * The PPR should be up-to-date at this point and we're on EMT (so no parallel updates).
+             * Subject the pending vector to PPR prioritization.
+             */
             uint8_t const uPpr = pXApicPage->ppr.u8Ppr;
             if (   !uPpr
-                ||  XAPIC_PPR_GET_PP(uVector) > XAPIC_PPR_GET_PP(uPpr))
+                || XAPIC_PPR_GET_PP(uVector) > XAPIC_PPR_GET_PP(uPpr))
             {
                 apicClearVectorInReg(&pXApicPage->irr, uVector);
@@ -2333,8 +2341,9 @@
 
                 Log2(("APIC%u: APICGetInterrupt: Valid Interrupt. uVector=%#x\n", pVCpu->idCpu, uVector));
-                return uVector;
+                *pu8Vector = uVector;
+                return VINF_SUCCESS;
             }
             else
-                Log2(("APIC%u: APICGetInterrupt: Interrupt's priority is not higher than the PPR uVector=%#x PPR=%#x\n",
+                Log2(("APIC%u: APICGetInterrupt: Interrupt's priority is not higher than the PPR. uVector=%#x PPR=%#x\n",
                       pVCpu->idCpu, uVector, uPpr));
         }
@@ -2345,5 +2354,5 @@
         Log2(("APIC%u: APICGetInterrupt: APIC %s disabled\n", pVCpu->idCpu, !fApicHwEnabled ? "hardware" : "software"));
 
-    return -1;
+    return VERR_APIC_INTR_NOT_PENDING;
 }
 
Index: /trunk/src/VBox/VMM/VMMAll/PDMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PDMAll.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMAll/PDMAll.cpp	(revision 60716)
@@ -40,4 +40,11 @@
  *
  * @returns VBox status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_APIC_INTR_MASKED_BY_TPR when an APIC interrupt is pending but
+ *          can't be delivered due to TPR priority.
+ * @retval  VERR_NO_DATA if there is no interrupt to be delivered (either APIC
+ *          has been software-disabled since it flagged something was pending,
+ *          or other reasons).
+ *
  * @param   pVCpu           The cross context virtual CPU structure.
  * @param   pu8Interrupt    Where to store the interrupt on success.
@@ -60,16 +67,16 @@
         Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt));
         uint32_t uTagSrc;
-        int i = pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu, &uTagSrc);
-#ifndef VBOX_WITH_NEW_APIC
-        AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i));
-#endif
-        if (i >= 0)
+        uint8_t  uVector;
+        int rc = pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu, &uVector, &uTagSrc);
+        if (   rc == VINF_SUCCESS
+            || rc == VERR_APIC_INTR_MASKED_BY_TPR)
         {
 #ifndef VBOX_WITH_NEW_APIC
             pdmUnlock(pVM);
 #endif
-            *pu8Interrupt = (uint8_t)i;
-            VBOXVMM_PDM_IRQ_GET(pVCpu, RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc), i);
-            return VINF_SUCCESS;
+            *pu8Interrupt = uVector;
+            if (rc == VINF_SUCCESS)
+                VBOXVMM_PDM_IRQ_GET(pVCpu, RT_LOWORD(uTagSrc), RT_HIWORD(uTagSrc), uVector);
+            return rc;
         }
     }
@@ -99,5 +106,11 @@
     }
 
-    /** @todo Figure out exactly why we can get here without anything being set. (REM) */
+    /*
+     * One scenario where we may possibly get here is if the APIC signalled a pending interrupt,
+     * got an APIC MMIO/MSR VM-exit which disabled the APIC. We could, in theory, clear the APIC
+     * force-flag from all the places which disables the APIC but letting PDMGetInterrupt() fail
+     * without returning a valid interrupt still needs to be handled for the TPR masked case,
+     * so we shall just handle it here regardless if we choose to update the APIC code in the future.
+     */
 
     pdmUnlock(pVM);
@@ -313,41 +326,23 @@
 
 /**
- * Check if the APIC has a pending interrupt/if a TPR change would active one.
- *
- * @returns VINF_SUCCESS or VERR_PDM_NO_APIC_INSTANCE.
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   pfPending   Pending state (out).
- */
-VMM_INT_DECL(int) PDMApicHasPendingIrq(PVMCPU pVCpu, bool *pfPending)
+ * Set the TPR (Task Priority Register).
+ *
+ * @returns VBox status code.
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   u8TPR           The new TPR.
+ */
+VMMDECL(int) PDMApicSetTPR(PVMCPU pVCpu, uint8_t u8TPR)
 {
     PVM pVM = pVCpu->CTX_SUFF(pVM);
     if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
     {
-        Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnHasPendingIrq));
-        pdmLock(pVM);
-        *pfPending = pVM->pdm.s.Apic.CTX_SUFF(pfnHasPendingIrq)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu, NULL /*pu8PendingIrq*/);
-        pdmUnlock(pVM);
-        return VINF_SUCCESS;
-    }
-    return VERR_PDM_NO_APIC_INSTANCE;
-}
-
-
-/**
- * Set the TPR (task priority register).
- *
- * @returns VBox status code.
- * @param   pVCpu           The cross context virtual CPU structure.
- * @param   u8TPR           The new TPR.
- */
-VMMDECL(int) PDMApicSetTPR(PVMCPU pVCpu, uint8_t u8TPR)
-{
-    PVM pVM = pVCpu->CTX_SUFF(pVM);
-    if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
-    {
         Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnSetTpr));
+#ifdef VBOX_WITH_NEW_APIC
+        pVM->pdm.s.Apic.CTX_SUFF(pfnSetTpr)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu, u8TPR);
+#else
         pdmLock(pVM);
         pVM->pdm.s.Apic.CTX_SUFF(pfnSetTpr)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu, u8TPR);
         pdmUnlock(pVM);
+#endif
         return VINF_SUCCESS;
     }
@@ -357,16 +352,17 @@
 
 /**
- * Get the TPR (task priority register).
+ * Get the TPR (Task Priority Register).
  *
  * @returns VINF_SUCCESS or VERR_PDM_NO_APIC_INSTANCE.
  * @param   pVCpu           The cross context virtual CPU structure.
  * @param   pu8TPR          Where to store the TRP.
- * @param   pfPending       Pending interrupt state (out, optional).
- * @param   pu8PendingIrq   Where to store the highest-priority pending IRQ
+ * @param   pfPending       Where to store whether there is a pending interrupt
  *                          (out, optional).
+ * @param   pu8PendingIntr  Where to store the highest-priority pending
+ *                          interrupt (out, optional).
  *
  * @remarks No-long-jump zone!!!
  */
-VMMDECL(int) PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending, uint8_t *pu8PendingIrq)
+VMMDECL(int) PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending, uint8_t *pu8PendingIntr)
 {
     PVM        pVM      = pVCpu->CTX_SUFF(pVM);
@@ -380,7 +376,5 @@
          */
         Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnGetTpr));
-        *pu8TPR = pVM->pdm.s.Apic.CTX_SUFF(pfnGetTpr)(pApicIns, pVCpu);
-        if (pfPending)
-            *pfPending = pVM->pdm.s.Apic.CTX_SUFF(pfnHasPendingIrq)(pApicIns, pVCpu, pu8PendingIrq);
+        *pu8TPR = pVM->pdm.s.Apic.CTX_SUFF(pfnGetTpr)(pApicIns, pVCpu, pfPending, pu8PendingIntr);
         return VINF_SUCCESS;
     }
Index: /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 60716)
@@ -2670,5 +2670,5 @@
             uint8_t u8Interrupt;
             int rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
-            if (RT_SUCCESS(rc))
+            if (rc == VINF_SUCCESS)
             {
                 Log4(("Injecting external interrupt u8Interrupt=%#x\n", u8Interrupt));
@@ -2680,10 +2680,16 @@
                 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);
             }
+            else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
+            {
+                /*
+                 * AMD-V has no TPR thresholding feature. We just avoid posting the interrupt.
+                 * We just avoid delivering the TPR-masked interrupt here. TPR will be updated
+                 * always via hmR0SvmLoadGuestState() -> hmR0SvmLoadGuestApicState().
+                 */
+                Assert(!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC)));
+            }
             else
             {
-                /* This can happen with the new APIC code. */
-#ifndef VBOX_WITH_NEW_APIC
                 Assert(!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)));
-#endif
                 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
             }
Index: /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 60716)
@@ -3343,4 +3343,19 @@
 
 /**
+ * Sets the TPR threshold in the VMCS.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu               The cross context virtual CPU structure.
+ * @param   u32TprThreshold     The TPR threshold (task-priority class only).
+ */
+DECLINLINE(int) hmR0VmxApicSetTprThreshold(PVMCPU pVCpu, uint32_t u32TprThreshold)
+{
+    Assert(!(u32TprThreshold & 0xfffffff0));         /* Bits 31:4 MBZ. */
+    Assert(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW);
+    return VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
+}
+
+
+/**
  * Loads the guest APIC and related state.
  *
@@ -3387,7 +3402,6 @@
                     u32TprThreshold = u8TprPriority;             /* Required for Vista 64-bit guest, see @bugref{6398}. */
             }
-            Assert(!(u32TprThreshold & 0xfffffff0));             /* Bits 31:4 MBZ. */
-
-            rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
+
+            rc = hmR0VmxApicSetTprThreshold(pVCpu, u32TprThreshold);
             AssertRCReturn(rc, rc);
         }
@@ -7434,5 +7448,5 @@
             uint8_t u8Interrupt;
             rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
-            if (RT_SUCCESS(rc))
+            if (rc == VINF_SUCCESS)
             {
                 Log4(("Pending interrupt vcpu[%RU32] u8Interrupt=%#x \n", pVCpu->idCpu, u8Interrupt));
@@ -7442,10 +7456,13 @@
                 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrfaultAddress */);
             }
+            else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
+            {
+                Assert(!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC)));
+                if (pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_USE_TPR_SHADOW)
+                    hmR0VmxApicSetTprThreshold(pVCpu, u8Interrupt >> 4);
+            }
             else
             {
-                /* This can happen with the new APIC code. */
-#ifndef VBOX_WITH_NEW_APIC
                 Assert(!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)));
-#endif
                 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
             }
Index: /trunk/src/VBox/VMM/VMMR3/APIC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/APIC.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMR3/APIC.cpp	(revision 60716)
@@ -815,15 +815,8 @@
     AssertRCReturn(rc, rc);
     pApicCpu->uApicBaseMsr = uApicBaseLo;
+    Log2(("APIC%u: apicR3LoadLegacyVCpuData: uApicBaseMsr=%#RX64\n", pVCpu->idCpu, pApicCpu->uApicBaseMsr));
 
     switch (uVersion)
     {
-        case APIC_SAVED_STATE_VERSION_ANCIENT:
-        {
-            uint8_t uPhysApicId;
-            SSMR3GetU8(pSSM, &pXApicPage->id.u8ApicId);
-            SSMR3GetU8(pSSM, &uPhysApicId);   NOREF(uPhysApicId); /* PhysId == pVCpu->idCpu */
-            break;
-        }
-
         case APIC_SAVED_STATE_VERSION_VBOX_50:
         case APIC_SAVED_STATE_VERSION_VBOX_30:
@@ -833,4 +826,12 @@
             SSMR3GetU32(pSSM, &uPhysApicId);  NOREF(uPhysApicId); /* PhysId == pVCpu->idCpu */
             SSMR3GetU32(pSSM, &uArbId);       NOREF(uArbId);      /* ArbID is & was unused. */
+            break;
+        }
+
+        case APIC_SAVED_STATE_VERSION_ANCIENT:
+        {
+            uint8_t uPhysApicId;
+            SSMR3GetU8(pSSM, &pXApicPage->id.u8ApicId);
+            SSMR3GetU8(pSSM, &uPhysApicId);   NOREF(uPhysApicId); /* PhysId == pVCpu->idCpu */
             break;
         }
@@ -1160,7 +1161,6 @@
     pApicDev->pCritSectRC = pApicDev->pApicHlpR3->pfnGetRCCritSect(pDevIns);
 
-    pApic->pApicDevRC = PDMINS_2_DATA_RCPTR(pDevIns);
-    if (pApic->pvApicPibRC != NIL_RTRCPTR)
-        pApic->pvApicPibRC = MMHyperR3ToRC(pVM, (RTR3PTR)pApic->pvApicPibR3);
+    pApic->pApicDevRC   = PDMINS_2_DATA_RCPTR(pDevIns);
+    pApic->pvApicPibRC += offDelta;
 
     for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
@@ -1170,8 +1170,7 @@
         pApicCpu->pTimerRC     = TMTimerRCPtr(pApicCpu->pTimerR3);
 
-        if (pApicCpu->pvApicPageRC != NIL_RTRCPTR)
-            pApicCpu->pvApicPageRC = MMHyperR3ToRC(pVM, (RTR3PTR)pApicCpu->pvApicPageR3);
-        if (pApicCpu->pvApicPibRC != NIL_RTRCPTR)
-            pApicCpu->pvApicPibRC  = MMHyperR3ToRC(pVM, (RTR3PTR)pApicCpu->pvApicPibR3);
+        pApicCpu->pvApicPageRC += offDelta;
+        pApicCpu->pvApicPibRC  += offDelta;
+        Log2(("APIC%u: apicR3Relocate: APIC PIB at %RGv\n", pVCpu->idCpu, pApicCpu->pvApicPibRC));
     }
 }
@@ -1339,5 +1338,5 @@
                 pApicCpu->pvApicPibR3      = (RTR3PTR)((RTR3UINTPTR)pApic->pvApicPibR3 + offApicPib);
                 if (fNeedsGCMapping)
-                    pApicCpu->pvApicPibRC += offApicPib;
+                    pApicCpu->pvApicPibRC  = (RTRCPTR)((RTRCUINTPTR)pApic->pvApicPibRC + offApicPib);
 
                 /* Initialize the virtual-APIC state. */
@@ -1352,4 +1351,5 @@
                 Assert(pApicCpu->pvApicPageR0 != NIL_RTR0PTR);
                 Assert(!fNeedsGCMapping || pApicCpu->pvApicPageRC != NIL_RTRCPTR);
+                Assert(!fNeedsGCMapping || pApic->pvApicPibRC == pVM->aCpus[0].apic.s.pvApicPibRC);
 #endif
             }
@@ -1490,5 +1490,4 @@
     ApicReg.u32Version              = PDM_APICREG_VERSION;
     ApicReg.pfnGetInterruptR3       = APICGetInterrupt;
-    ApicReg.pfnHasPendingIrqR3      = APICHasPendingIrq;
     ApicReg.pfnSetBaseMsrR3         = APICSetBaseMsr;
     ApicReg.pfnGetBaseMsrR3         = APICGetBaseMsr;
@@ -1508,5 +1507,4 @@
     {
         ApicReg.pszGetInterruptRC   = "APICGetInterrupt";
-        ApicReg.pszHasPendingIrqRC  = "APICHasPendingIrq";
         ApicReg.pszSetBaseMsrRC     = "APICSetBaseMsr";
         ApicReg.pszGetBaseMsrRC     = "APICGetBaseMsr";
@@ -1520,5 +1518,4 @@
 
         ApicReg.pszGetInterruptR0   = "APICGetInterrupt";
-        ApicReg.pszHasPendingIrqR0  = "APICHasPendingIrq";
         ApicReg.pszSetBaseMsrR0     = "APICSetBaseMsr";
         ApicReg.pszGetBaseMsrR0     = "APICGetBaseMsr";
Index: /trunk/src/VBox/VMM/VMMR3/PDM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDM.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMR3/PDM.cpp	(revision 60716)
@@ -509,5 +509,4 @@
         pVM->pdm.s.Apic.pDevInsRC           += offDelta;
         pVM->pdm.s.Apic.pfnGetInterruptRC   += offDelta;
-        pVM->pdm.s.Apic.pfnHasPendingIrqRC  += offDelta;
         pVM->pdm.s.Apic.pfnSetBaseMsrRC     += offDelta;
         pVM->pdm.s.Apic.pfnGetBaseMsrRC     += offDelta;
Index: /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp	(revision 60716)
@@ -2644,5 +2644,4 @@
     }
     if (    !pApicReg->pfnGetInterruptR3
-        ||  !pApicReg->pfnHasPendingIrqR3
         ||  !pApicReg->pfnSetBaseMsrR3
         ||  !pApicReg->pfnGetBaseMsrR3
@@ -2656,5 +2655,4 @@
     {
         Assert(pApicReg->pfnGetInterruptR3);
-        Assert(pApicReg->pfnHasPendingIrqR3);
         Assert(pApicReg->pfnSetBaseMsrR3);
         Assert(pApicReg->pfnGetBaseMsrR3);
@@ -2670,5 +2668,4 @@
     }
     if (   (    pApicReg->pszGetInterruptRC
-            ||  pApicReg->pszHasPendingIrqRC
             ||  pApicReg->pszSetBaseMsrRC
             ||  pApicReg->pszGetBaseMsrRC
@@ -2681,5 +2678,4 @@
             ||  pApicReg->pszGetTimerFreqRC)
         &&  (   !VALID_PTR(pApicReg->pszGetInterruptRC)
-            ||  !VALID_PTR(pApicReg->pszHasPendingIrqRC)
             ||  !VALID_PTR(pApicReg->pszSetBaseMsrRC)
             ||  !VALID_PTR(pApicReg->pszGetBaseMsrRC)
@@ -2694,5 +2690,4 @@
     {
         Assert(VALID_PTR(pApicReg->pszGetInterruptRC));
-        Assert(VALID_PTR(pApicReg->pszHasPendingIrqRC));
         Assert(VALID_PTR(pApicReg->pszSetBaseMsrRC));
         Assert(VALID_PTR(pApicReg->pszGetBaseMsrRC));
@@ -2708,5 +2703,4 @@
     }
     if (   (    pApicReg->pszGetInterruptR0
-            ||  pApicReg->pszHasPendingIrqR0
             ||  pApicReg->pszSetBaseMsrR0
             ||  pApicReg->pszGetBaseMsrR0
@@ -2719,5 +2713,4 @@
             ||  pApicReg->pszGetTimerFreqR0)
         &&  (   !VALID_PTR(pApicReg->pszGetInterruptR0)
-            ||  !VALID_PTR(pApicReg->pszHasPendingIrqR0)
             ||  !VALID_PTR(pApicReg->pszSetBaseMsrR0)
             ||  !VALID_PTR(pApicReg->pszGetBaseMsrR0)
@@ -2732,5 +2725,4 @@
     {
         Assert(VALID_PTR(pApicReg->pszGetInterruptR0));
-        Assert(VALID_PTR(pApicReg->pszHasPendingIrqR0));
         Assert(VALID_PTR(pApicReg->pszSetBaseMsrR0));
         Assert(VALID_PTR(pApicReg->pszGetBaseMsrR0));
@@ -2773,9 +2765,4 @@
         if (RT_SUCCESS(rc))
         {
-            rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszHasPendingIrqRC, &pVM->pdm.s.Apic.pfnHasPendingIrqRC);
-            AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszHasPendingIrqRC, rc));
-        }
-        if (RT_SUCCESS(rc))
-        {
             rc = pdmR3DevGetSymbolRCLazy(pDevIns, pApicReg->pszSetBaseMsrRC, &pVM->pdm.s.Apic.pfnSetBaseMsrRC);
             AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szRCMod, pApicReg->pszSetBaseMsrRC, rc));
@@ -2832,5 +2819,4 @@
         pVM->pdm.s.Apic.pDevInsRC           = 0;
         pVM->pdm.s.Apic.pfnGetInterruptRC   = 0;
-        pVM->pdm.s.Apic.pfnHasPendingIrqRC  = 0;
         pVM->pdm.s.Apic.pfnSetBaseMsrRC     = 0;
         pVM->pdm.s.Apic.pfnGetBaseMsrRC     = 0;
@@ -2853,9 +2839,4 @@
         if (RT_SUCCESS(rc))
         {
-            rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszHasPendingIrqR0, &pVM->pdm.s.Apic.pfnHasPendingIrqR0);
-            AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszHasPendingIrqR0, rc));
-        }
-        if (RT_SUCCESS(rc))
-        {
             rc = pdmR3DevGetSymbolR0Lazy(pDevIns, pApicReg->pszSetBaseMsrR0, &pVM->pdm.s.Apic.pfnSetBaseMsrR0);
             AssertMsgRC(rc, ("%s::%s rc=%Rrc\n", pDevIns->pReg->szR0Mod, pApicReg->pszSetBaseMsrR0, rc));
@@ -2912,5 +2893,4 @@
     {
         pVM->pdm.s.Apic.pfnGetInterruptR0   = 0;
-        pVM->pdm.s.Apic.pfnHasPendingIrqR0  = 0;
         pVM->pdm.s.Apic.pfnSetBaseMsrR0     = 0;
         pVM->pdm.s.Apic.pfnGetBaseMsrR0     = 0;
@@ -2930,5 +2910,4 @@
     pVM->pdm.s.Apic.pDevInsR3           = pDevIns;
     pVM->pdm.s.Apic.pfnGetInterruptR3   = pApicReg->pfnGetInterruptR3;
-    pVM->pdm.s.Apic.pfnHasPendingIrqR3  = pApicReg->pfnHasPendingIrqR3;
     pVM->pdm.s.Apic.pfnSetBaseMsrR3     = pApicReg->pfnSetBaseMsrR3;
     pVM->pdm.s.Apic.pfnGetBaseMsrR3     = pApicReg->pfnGetBaseMsrR3;
Index: /trunk/src/VBox/VMM/VMMR3/TRPM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/TRPM.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMR3/TRPM.cpp	(revision 60716)
@@ -1509,5 +1509,5 @@
 # endif
 
-        uint8_t u8Interrupt;
+        uint8_t u8Interrupt = 0;
         int rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
         Log(("TRPMR3InjectEvent: CPU%d u8Interrupt=%d (%#x) rc=%Rrc\n", pVCpu->idCpu, u8Interrupt, u8Interrupt, rc));
@@ -1555,11 +1555,10 @@
         else
         {
-#ifndef VBOX_WITH_NEW_APIC
-            AssertRC(rc);
-#endif
+            /* Can happen if the interrupt is masked by TPR or APIC is disabled. */
+            AssertMsg(rc == VERR_APIC_INTR_MASKED_BY_TPR || rc == VERR_NO_DATA, ("PDMGetInterrupt failed. rc=%Rrc\n", rc));
             return HMR3IsActive(pVCpu) ? VINF_EM_RESCHEDULE_HM : VINF_EM_RESCHEDULE_REM; /* (Heed the halted state if this is changed!) */
         }
 #else /* !TRPM_FORWARD_TRAPS_IN_GC */
-        uint8_t u8Interrupt;
+        uint8_t u8Interrupt = 0;
         int rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
         Log(("TRPMR3InjectEvent: u8Interrupt=%d (%#x) rc=%Rrc\n", u8Interrupt, u8Interrupt, rc));
@@ -1569,6 +1568,11 @@
             AssertRC(rc);
             STAM_COUNTER_INC(&pVM->trpm.s.paStatForwardedIRQR3[u8Interrupt]);
-            return HMR3IsActive(pVCpu) ? VINF_EM_RESCHEDULE_HM : VINF_EM_RESCHEDULE_REM;
-        }
+        }
+        else
+        {
+            /* Can happen if the interrupt is masked by TPR or APIC is disabled. */
+            AssertMsg(rc == VERR_APIC_INTR_MASKED_BY_TPR || rc == VERR_NO_DATA, ("PDMGetInterrupt failed. rc=%Rrc\n", rc));
+        }
+        return HMR3IsActive(pVCpu) ? VINF_EM_RESCHEDULE_HM : VINF_EM_RESCHEDULE_REM; /* (Heed the halted state if this is changed!) */
 #endif /* !TRPM_FORWARD_TRAPS_IN_GC */
     }
Index: /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 60715)
+++ /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 60716)
@@ -249,5 +249,5 @@
         else if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_TRPM_SYNC_IDT))
             rc = VINF_EM_RAW_TO_R3;
-        /* Pending interrupt: dispatch it. */
+        /* Possibly pending interrupt: dispatch it. */
         else if (    VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
                  && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
@@ -258,18 +258,28 @@
             rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
             Log(("trpmGCExitTrap: u8Interrupt=%d (%#x) rc=%Rrc\n", u8Interrupt, u8Interrupt, rc));
-            AssertFatalMsgRC(rc, ("PDMGetInterrupt failed with %Rrc\n", rc));
-            rc = TRPMForwardTrap(pVCpu, pRegFrame, (uint32_t)u8Interrupt, 0, TRPM_TRAP_NO_ERRORCODE, TRPM_HARDWARE_INT, uOldActiveVector);
-            /* can't return if successful */
-            Assert(rc != VINF_SUCCESS);
-
-            /* Stop the profile counter that was started in TRPMGCHandlersA.asm */
-            Assert(uOldActiveVector <= 16);
-            STAM_PROFILE_ADV_STOP(&pVM->trpm.s.aStatGCTraps[uOldActiveVector], a);
-
-            /* Assert the trap and go to the recompiler to dispatch it. */
-            TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT);
-
-            STAM_PROFILE_ADV_START(&pVM->trpm.s.aStatGCTraps[uOldActiveVector], a);
-            rc = VINF_EM_RAW_INTERRUPT_PENDING;
+            if (RT_SUCCESS(rc))
+            {
+                rc = TRPMForwardTrap(pVCpu, pRegFrame, (uint32_t)u8Interrupt, 0, TRPM_TRAP_NO_ERRORCODE, TRPM_HARDWARE_INT, uOldActiveVector);
+                /* can't return if successful */
+                Assert(rc != VINF_SUCCESS);
+
+                /* Stop the profile counter that was started in TRPMRCHandlersA.asm */
+                Assert(uOldActiveVector <= 16);
+                STAM_PROFILE_ADV_STOP(&pVM->trpm.s.aStatGCTraps[uOldActiveVector], a);
+
+                /* Assert the trap and go to the recompiler to dispatch it. */
+                TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT);
+
+                STAM_PROFILE_ADV_START(&pVM->trpm.s.aStatGCTraps[uOldActiveVector], a);
+                rc = VINF_EM_RAW_INTERRUPT_PENDING;
+            }
+            else if (   rc == VERR_APIC_INTR_MASKED_BY_TPR  /* Can happen if TPR is too high for the newly arrived interrupt. */
+                     || rc == VERR_NO_DATA)                 /* Can happen if the APIC is disabled. */
+            {
+                STAM_PROFILE_ADV_STOP(&pVM->trpm.s.aStatGCTraps[uOldActiveVector], a);
+                rc = VINF_SUCCESS;
+            }
+            else
+                AssertFatalMsgRC(rc, ("PDMGetInterrupt failed. rc=%Rrc\n", rc));
         }
         /*
Index: /trunk/src/VBox/VMM/include/APICInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/APICInternal.h	(revision 60715)
+++ /trunk/src/VBox/VMM/include/APICInternal.h	(revision 60716)
@@ -633,5 +633,5 @@
 VMMDECL(uint64_t)       APICGetBaseMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu);
 VMMDECL(VBOXSTRICTRC)   APICSetBaseMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint64_t uBase);
-VMMDECL(uint8_t)        APICGetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu);
+VMMDECL(uint8_t)        APICGetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr);
 VMMDECL(void)           APICSetTpr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr);
 VMMDECL(uint64_t)       APICGetTimerFreq(PPDMDEVINS pDevIns);
@@ -640,6 +640,5 @@
 VMMDECL(VBOXSTRICTRC)   APICReadMsr(PPDMDEVINS pDevIns,  PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Val);
 VMMDECL(VBOXSTRICTRC)   APICWriteMsr(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Val);
-VMMDECL(bool)           APICHasPendingIrq(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8PendingIrq);
-VMMDECL(int)            APICGetInterrupt(PPDMDEVINS pDevIns,  PVMCPU pVCpu, uint32_t *puTagSrc);
+VMMDECL(int)            APICGetInterrupt(PPDMDEVINS pDevIns,  PVMCPU pVCpu, uint8_t *puVector, uint32_t *puTagSrc);
 VMMDECL(void)           APICSetInterruptFF(PVMCPU pVCpu, PDMAPICIRQ enmType);
 VMMDECL(void)           APICClearInterruptFF(PVMCPU pVCpu, PDMAPICIRQ enmType);
Index: /trunk/src/VBox/VMM/include/PDMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/PDMInternal.h	(revision 60715)
+++ /trunk/src/VBox/VMM/include/PDMInternal.h	(revision 60716)
@@ -563,83 +563,85 @@
 {
     /** Pointer to the APIC device instance - R3 Ptr. */
-    PPDMDEVINSR3                    pDevInsR3;
+    PPDMDEVINSR3                       pDevInsR3;
     /** @copydoc PDMAPICREG::pfnGetInterruptR3 */
-    DECLR3CALLBACKMEMBER(int,       pfnGetInterruptR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t *puTagSrc));
-    /** @copydoc PDMAPICREG::pfnHasPendingIrqR3 */
-    DECLR3CALLBACKMEMBER(bool,      pfnHasPendingIrqR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8PendingIrq));
+    DECLR3CALLBACKMEMBER(int,          pfnGetInterruptR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8Vector,
+                                                          uint32_t *pu32TagSrc));
     /** @copydoc PDMAPICREG::pfnSetBaseMsrR3 */
     DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnSetBaseMsrR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint64_t u64Base));
     /** @copydoc PDMAPICREG::pfnGetBaseMsrR3 */
-    DECLR3CALLBACKMEMBER(uint64_t,  pfnGetBaseMsrR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
+    DECLR3CALLBACKMEMBER(uint64_t,     pfnGetBaseMsrR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
     /** @copydoc PDMAPICREG::pfnSetTprR3 */
-    DECLR3CALLBACKMEMBER(void,      pfnSetTprR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr));
+    DECLR3CALLBACKMEMBER(void,         pfnSetTprR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr));
     /** @copydoc PDMAPICREG::pfnGetTprR3 */
-    DECLR3CALLBACKMEMBER(uint8_t,   pfnGetTprR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
+    DECLR3CALLBACKMEMBER(uint8_t,      pfnGetTprR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr));
     /** @copydoc PDMAPICREG::pfnWriteMsrR3 */
-    DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsrR3, (PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Value));
+    DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsrR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Value));
     /** @copydoc PDMAPICREG::pfnReadMsrR3 */
-    DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsrR3, (PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
+    DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsrR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
     /** @copydoc PDMAPICREG::pfnBusDeliverR3 */
-    DECLR3CALLBACKMEMBER(int,       pfnBusDeliverR3,(PPDMDEVINS pDevIns, uint8_t uDest, uint8_t uDestMode, uint8_t uDeliveryMode,
-                                                     uint8_t uVector, uint8_t uPolarity, uint8_t uTriggerMode, uint32_t uTagSrc));
+    DECLR3CALLBACKMEMBER(int,          pfnBusDeliverR3,(PPDMDEVINS pDevIns, uint8_t uDest, uint8_t uDestMode,
+                                                        uint8_t uDeliveryMode, uint8_t uVector, uint8_t uPolarity,
+                                                        uint8_t uTriggerMode, uint32_t uTagSrc));
     /** @copydoc PDMAPICREG::pfnLocalInterruptR3 */
     DECLR3CALLBACKMEMBER(VBOXSTRICTRC, pfnLocalInterruptR3,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Pin, uint8_t u8Level,
                                                             int rcRZ));
     /** @copydoc PDMAPICREG::pfnGetTimerFreqR3 */
-    DECLR3CALLBACKMEMBER(uint64_t,  pfnGetTimerFreqR3,(PPDMDEVINS pDevIns));
+    DECLR3CALLBACKMEMBER(uint64_t,     pfnGetTimerFreqR3,(PPDMDEVINS pDevIns));
 
     /** Pointer to the APIC device instance - R0 Ptr. */
-    PPDMDEVINSR0                    pDevInsR0;
+    PPDMDEVINSR0                       pDevInsR0;
     /** @copydoc PDMAPICREG::pfnGetInterruptR3 */
-    DECLR0CALLBACKMEMBER(int,       pfnGetInterruptR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t *puTagSrc));
-    /** @copydoc PDMAPICREG::pfnHasPendingIrqR3 */
-    DECLR0CALLBACKMEMBER(bool,      pfnHasPendingIrqR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8PendingIrq));
+    DECLR0CALLBACKMEMBER(int,          pfnGetInterruptR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8Vector,
+                                                          uint32_t *pu32TagSrc));
     /** @copydoc PDMAPICREG::pfnSetBaseMsrR3 */
     DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnSetBaseMsrR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint64_t u64Base));
     /** @copydoc PDMAPICREG::pfnGetBaseMsrR3 */
-    DECLR0CALLBACKMEMBER(uint64_t,  pfnGetBaseMsrR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
+    DECLR0CALLBACKMEMBER(uint64_t,     pfnGetBaseMsrR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
     /** @copydoc PDMAPICREG::pfnSetTprR3 */
-    DECLR0CALLBACKMEMBER(void,      pfnSetTprR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr));
+    DECLR0CALLBACKMEMBER(void,         pfnSetTprR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr));
     /** @copydoc PDMAPICREG::pfnGetTprR3 */
-    DECLR0CALLBACKMEMBER(uint8_t,   pfnGetTprR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
+    DECLR0CALLBACKMEMBER(uint8_t,      pfnGetTprR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr));
      /** @copydoc PDMAPICREG::pfnWriteMsrR3 */
-    DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsrR0, (PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Value));
+    DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsrR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Value));
     /** @copydoc PDMAPICREG::pfnReadMsrR3 */
-    DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsrR0, (PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
+    DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsrR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
     /** @copydoc PDMAPICREG::pfnBusDeliverR3 */
-    DECLR0CALLBACKMEMBER(int,       pfnBusDeliverR0,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
-                                                     uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
+    DECLR0CALLBACKMEMBER(int,          pfnBusDeliverR0,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
+                                                        uint8_t u8DeliveryMode, uint8_t iVector, uint8_t u8Polarity,
+                                                        uint8_t u8TriggerMode, uint32_t uTagSrc));
     /** @copydoc PDMAPICREG::pfnLocalInterruptR3 */
     DECLR0CALLBACKMEMBER(VBOXSTRICTRC, pfnLocalInterruptR0,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Pin, uint8_t u8Level,
                                                             int rcRZ));
     /** @copydoc PDMAPICREG::pfnGetTimerFreqR3 */
-    DECLR0CALLBACKMEMBER(uint64_t,  pfnGetTimerFreqR0,(PPDMDEVINS pDevIns));
+    DECLR0CALLBACKMEMBER(uint64_t,     pfnGetTimerFreqR0,(PPDMDEVINS pDevIns));
 
     /** Pointer to the APIC device instance - RC Ptr. */
-    PPDMDEVINSRC                    pDevInsRC;
+    PPDMDEVINSRC                       pDevInsRC;
     /** @copydoc PDMAPICREG::pfnGetInterruptR3 */
-    DECLRCCALLBACKMEMBER(int,       pfnGetInterruptRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t *puTagSrc));
-    /** @copydoc PDMAPICREG::pfnHasPendingIrqR3 */
-    DECLRCCALLBACKMEMBER(bool,      pfnHasPendingIrqRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8PendingIrq));
+    DECLRCCALLBACKMEMBER(int,          pfnGetInterruptRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t *pu8Vector,
+                                                          uint32_t *pu32TagSrc));
     /** @copydoc PDMAPICREG::pfnSetBaseMsrR3 */
     DECLRCCALLBACKMEMBER(VBOXSTRICTRC, pfnSetBaseMsrRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint64_t u64Base));
     /** @copydoc PDMAPICREG::pfnGetBaseMsrR3 */
-    DECLRCCALLBACKMEMBER(uint64_t,  pfnGetBaseMsrRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
+    DECLRCCALLBACKMEMBER(uint64_t,     pfnGetBaseMsrRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
     /** @copydoc PDMAPICREG::pfnSetTprR3 */
-    DECLRCCALLBACKMEMBER(void,      pfnSetTprRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr));
+    DECLRCCALLBACKMEMBER(void,         pfnSetTprRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Tpr));
     /** @copydoc PDMAPICREG::pfnGetTprR3 */
-    DECLRCCALLBACKMEMBER(uint8_t,   pfnGetTprRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu));
+    DECLRCCALLBACKMEMBER(uint8_t,      pfnGetTprRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, bool *pfPending, uint8_t *pu8PendingIntr));
     /** @copydoc PDMAPICREG::pfnWriteMsrR3 */
-    DECLRCCALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsrRC, (PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Value));
+    DECLRCCALLBACKMEMBER(VBOXSTRICTRC, pfnWriteMsrRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t u64Value));
     /** @copydoc PDMAPICREG::pfnReadMsrR3 */
-    DECLRCCALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsrRC, (PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
+    DECLRCCALLBACKMEMBER(VBOXSTRICTRC, pfnReadMsrRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint32_t u32Reg, uint64_t *pu64Value));
     /** @copydoc PDMAPICREG::pfnBusDeliverR3 */
-    DECLRCCALLBACKMEMBER(int,       pfnBusDeliverRC,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
-                                                     uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
+    DECLRCCALLBACKMEMBER(int,          pfnBusDeliverRC,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode,
+                                                        uint8_t u8DeliveryMode, uint8_t iVector, uint8_t u8Polarity,
+                                                        uint8_t u8TriggerMode, uint32_t uTagSrc));
     /** @copydoc PDMAPICREG::pfnLocalInterruptR3 */
     DECLRCCALLBACKMEMBER(VBOXSTRICTRC, pfnLocalInterruptRC,(PPDMDEVINS pDevIns, PVMCPU pVCpu, uint8_t u8Pin, uint8_t u8Level,
                                                             int rcRZ));
     /** @copydoc PDMAPICREG::pfnGetTimerFreqR3 */
-    DECLRCCALLBACKMEMBER(uint64_t,  pfnGetTimerFreqRC,(PPDMDEVINS pDevIns));
+    DECLRCCALLBACKMEMBER(uint64_t,     pfnGetTimerFreqRC,(PPDMDEVINS pDevIns));
+
+    uint8_t                            Alignment[4];
 } PDMAPIC;
 
