Index: /trunk/include/VBox/vmm/apic.h
===================================================================
--- /trunk/include/VBox/vmm/apic.h	(revision 60592)
+++ /trunk/include/VBox/vmm/apic.h	(revision 60593)
@@ -911,5 +911,5 @@
 typedef struct APICPIB
 {
-    uint32_t volatile aVectorBitmap[8];
+    uint64_t volatile aVectorBitmap[4];
     uint32_t volatile fOutstandingNotification;
     uint8_t           au8Reserved[28];
Index: /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
===================================================================
--- /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 60592)
+++ /trunk/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp	(revision 60593)
@@ -793,5 +793,6 @@
     GEN_CHECK_OFF(APICCPU, StatMsrWriteRC);
     GEN_CHECK_OFF(APICCPU, StatUpdatePendingIntrs);
-    GEN_CHECK_OFF(APICCPU, StatPostInterrupt);
+    GEN_CHECK_OFF(APICCPU, StatPostIntr);
+    GEN_CHECK_OFF(APICCPU, StatPostIntrAlreadyPending);
 #else
     /* PC/DevAPIC.cpp */
Index: /trunk/src/VBox/VMM/VMMAll/APICAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/APICAll.cpp	(revision 60592)
+++ /trunk/src/VBox/VMM/VMMAll/APICAll.cpp	(revision 60593)
@@ -58,7 +58,7 @@
  * @param   uVector         The vector to check if set.
  */
-DECLINLINE(bool) apicTestVectorInReg(volatile XAPIC256BITREG *pApicReg, uint8_t uVector)
-{
-    volatile uint8_t *pbBitmap = (volatile uint8_t *)&pApicReg->u[0];
+DECLINLINE(bool) apicTestVectorInReg(const volatile XAPIC256BITREG *pApicReg, uint8_t uVector)
+{
+    const volatile uint8_t *pbBitmap = (const volatile uint8_t *)&pApicReg->u[0];
     return ASMBitTest(pbBitmap + XAPIC_REG256_VECTOR_OFF(uVector), XAPIC_REG256_VECTOR_BIT(uVector));
 }
@@ -2420,19 +2420,41 @@
     PAPICCPU pApicCpu = VMCPU_TO_APICCPU(pVCpu);
 
-    STAM_PROFILE_START(&pApicCpu->StatPostInterrupt, a);
-
-    /* Validate the vector. See Intel spec. 10.5.2 "Valid Interrupt Vectors". */
+    STAM_PROFILE_START(&pApicCpu->StatPostIntr, a);
+
+    /*
+     * Only post valid interrupt vectors.
+     * See Intel spec. 10.5.2 "Valid Interrupt Vectors".
+     */
     if (RT_LIKELY(uVector > XAPIC_ILLEGAL_VECTOR_END))
     {
-        Log4(("APIC%u: APICPostInterrupt: uVector=%#x\n", pVCpu->idCpu, uVector));
-        if (enmTriggerMode == XAPICTRIGGERMODE_EDGE)
-        {
-            if (pApic->fPostedIntrsEnabled)
-            { /** @todo posted-interrupt call to hardware */ }
+        /*
+         * If the interrupt is already pending in the vIRR we can skip the
+         * potential expensive operation of poking the guest EMT out of execution.
+         */
+        PCXAPICPAGE pXApicPage = VMCPU_TO_CXAPICPAGE(pVCpu);
+        if (!apicTestVectorInReg(&pXApicPage->irr, uVector))     /* PAV */
+        {
+            Log4(("APIC%u: APICPostInterrupt: uVector=%#x\n", pVCpu->idCpu, uVector));
+            if (enmTriggerMode == XAPICTRIGGERMODE_EDGE)
+            {
+                if (pApic->fPostedIntrsEnabled)
+                { /** @todo posted-interrupt call to hardware */ }
+                else
+                {
+                    Assert(CTX_SUFF(pApicCpu->pvApicPib));
+                    apicSetVectorInPib(CTX_SUFF(pApicCpu->pvApicPib), uVector);
+                    bool const fAlreadySet = apicSetNotificationBitInPib(CTX_SUFF(pApicCpu->pvApicPib));
+                    if (!fAlreadySet)
+                        APICSetInterruptFF(pVCpu, PDMAPICIRQ_HARDWARE);
+                }
+            }
             else
             {
-                Assert(CTX_SUFF(pApicCpu->pvApicPib));
-                apicSetVectorInPib(CTX_SUFF(pApicCpu->pvApicPib), uVector);
-                bool const fAlreadySet = apicSetNotificationBitInPib(CTX_SUFF(pApicCpu->pvApicPib));
+                /*
+                 * Level-triggered interrupts requires updating of the TMR and thus cannot be
+                 * delivered asynchronously.
+                 */
+                apicSetVectorInPib(&pApicCpu->ApicPibLevel.aVectorBitmap[0], uVector);
+                bool const fAlreadySet = apicSetNotificationBitInPib(&pApicCpu->ApicPibLevel.aVectorBitmap[0]);
                 if (!fAlreadySet)
                     APICSetInterruptFF(pVCpu, PDMAPICIRQ_HARDWARE);
@@ -2440,19 +2462,10 @@
         }
         else
-        {
-            /*
-             * Level-triggered interrupts requires updating of the TMR and thus cannot be
-             * delivered asynchronously.
-             */
-            apicSetVectorInPib(&pApicCpu->ApicPibLevel.aVectorBitmap[0], uVector);
-            bool const fAlreadySet = apicSetNotificationBitInPib(&pApicCpu->ApicPibLevel.aVectorBitmap[0]);
-            if (!fAlreadySet)
-                APICSetInterruptFF(pVCpu, PDMAPICIRQ_HARDWARE);
-        }
+            STAM_COUNTER_INC(&pApicCpu->StatPostIntrAlreadyPending);
     }
     else
         apicSetError(pVCpu, XAPIC_ESR_RECV_ILLEGAL_VECTOR);
 
-    STAM_PROFILE_STOP(&pApicCpu->StatPostInterrupt, a);
+    STAM_PROFILE_STOP(&pApicCpu->StatPostIntr, a);
 }
 
@@ -2628,11 +2641,19 @@
 
         PAPICPIB pPib = (PAPICPIB)CTX_SUFF(pApicCpu->pvApicPib);
-        for (size_t i = 0; i < RT_ELEMENTS(pPib->aVectorBitmap); i++)
-        {
-            uint32_t const uFragment = ASMAtomicXchgU32(&pPib->aVectorBitmap[i], 0);
-            if (uFragment)
-            {
-                pXApicPage->irr.u[i].u32Reg |=  uFragment;
-                pXApicPage->tmr.u[i].u32Reg &= ~uFragment;
+        AssertCompile(RT_ELEMENTS(pXApicPage->irr.u) == 2 * RT_ELEMENTS(pPib->aVectorBitmap));
+
+        for (size_t idxPib = 0, idxReg = 0; idxPib < RT_ELEMENTS(pPib->aVectorBitmap); idxPib++, idxReg += 2)
+        {
+            uint64_t const u64Fragment = ASMAtomicXchgU64(&pPib->aVectorBitmap[idxPib], 0);
+            if (u64Fragment)
+            {
+                uint32_t const u32FragmentLo = RT_LO_U32(u64Fragment);
+                uint32_t const u32FragmentHi = RT_HI_U32(u64Fragment);
+
+                pXApicPage->irr.u[idxReg].u32Reg     |=  u32FragmentLo;
+                pXApicPage->irr.u[idxReg + 1].u32Reg |=  u32FragmentHi;
+
+                pXApicPage->tmr.u[idxReg].u32Reg     &= ~u32FragmentLo;
+                pXApicPage->tmr.u[idxReg + 1].u32Reg &= ~u32FragmentHi;
             }
         }
@@ -2647,11 +2668,19 @@
 
         PAPICPIB pPib = (PAPICPIB)&pApicCpu->ApicPibLevel;
-        for (size_t i = 0; i < RT_ELEMENTS(pPib->aVectorBitmap); i++)
-        {
-            uint32_t const uFragment = ASMAtomicXchgU32(&pPib->aVectorBitmap[i], 0);
-            if (uFragment)
-            {
-                pXApicPage->irr.u[i].u32Reg |= uFragment;
-                pXApicPage->tmr.u[i].u32Reg |= uFragment;
+        AssertCompile(RT_ELEMENTS(pXApicPage->irr.u) == 2 * RT_ELEMENTS(pPib->aVectorBitmap));
+
+        for (size_t idxPib = 0, idxReg = 0; idxPib < RT_ELEMENTS(pPib->aVectorBitmap); idxPib++, idxReg += 2)
+        {
+            uint64_t const u64Fragment = ASMAtomicXchgU64(&pPib->aVectorBitmap[idxPib], 0);
+            if (u64Fragment)
+            {
+                uint32_t const u32FragmentLo = RT_LO_U32(u64Fragment);
+                uint32_t const u32FragmentHi = RT_HI_U32(u64Fragment);
+
+                pXApicPage->irr.u[idxReg].u32Reg     |= u32FragmentLo;
+                pXApicPage->irr.u[idxReg + 1].u32Reg |= u32FragmentHi;
+
+                pXApicPage->tmr.u[idxReg].u32Reg     |= u32FragmentLo;
+                pXApicPage->tmr.u[idxReg + 1].u32Reg |= u32FragmentHi;
             }
         }
Index: /trunk/src/VBox/VMM/VMMR3/APIC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/APIC.cpp	(revision 60592)
+++ /trunk/src/VBox/VMM/VMMR3/APIC.cpp	(revision 60593)
@@ -1184,5 +1184,10 @@
     ApicReg.pfnLocalInterruptR3     = APICLocalInterrupt;
     ApicReg.pfnGetTimerFreqR3       = APICGetTimerFreq;
-    if (pApic->fRZEnabled)
+
+    /*
+     * We always require R0 functionality (e.g. APICGetTpr() called by HMR0 VT-x/AMD-V code).
+     * Hence, 'fRZEnabled' strictly only applies to MMIO and MSR read/write handlers returning
+     * to ring-3. We still need other handlers like APICGetTpr() in ring-0 for now.
+     */
     {
         ApicReg.pszGetInterruptRC   = "APICGetInterrupt";
@@ -1264,9 +1269,4 @@
             pApicCpu->pTimerR0 = TMTimerR0Ptr(pApicCpu->pTimerR3);
             pApicCpu->pTimerRC = TMTimerRCPtr(pApicCpu->pTimerR3);
-#if 0
-            rc = PDMR3CritSectInit(pVM, &pApicCpu->TimerCritSect, RT_SRC_POS, pApicCpu->szTimerDesc);
-            AssertRCReturn(rc, rc);
-            TMR3TimerSetCritSect(pApicCpu->pTimerR3, &pApicCpu->TimerCritSect);
-#endif
         }
         else
@@ -1332,6 +1332,10 @@
         APIC_PROF_COUNTER(&pApicCpu->StatUpdatePendingIntrs, "Profiling of APICUpdatePendingInterrupts",
                           "/PROF/CPU%d/APIC/UpdatePendingInterrupts");
-        APIC_PROF_COUNTER(&pApicCpu->StatPostInterrupt, "Profiling of APICPostInterrupt", "/PROF/CPU%d/APIC/PostInterrupt");
-    }
+        APIC_PROF_COUNTER(&pApicCpu->StatPostIntr, "Profiling of APICPostInterrupt", "/PROF/CPU%d/APIC/PostInterrupt");
+
+        APIC_REG_COUNTER(&pApicCpu->StatPostIntrAlreadyPending,  "Number of times an interrupt is already pending.",
+                         "/Devices/APIC/%u/PostInterruptAlreadyPending");
+    }
+# undef APIC_PROF_COUNTER
 # undef APIC_REG_ACCESS_COUNTER
 #endif
Index: /trunk/src/VBox/VMM/include/APICInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/APICInternal.h	(revision 60592)
+++ /trunk/src/VBox/VMM/include/APICInternal.h	(revision 60593)
@@ -473,5 +473,5 @@
     /** Whether this VM has an IO-APIC. */
     bool                        fIoApicPresent;
-    /** Whether RZ is enabled or not (required for MSR handling as well). */
+    /** Whether RZ is enabled or not (applies to MSR handling as well). */
     bool                        fRZEnabled;
     /** Alignment padding. */
@@ -591,5 +591,8 @@
     STAMPROFILE                 StatUpdatePendingIntrs;
     /** Profiling of APICPostInterrupt().  */
-    STAMPROFILE                 StatPostInterrupt;
+    STAMPROFILE                 StatPostIntr;
+    /** Number of times an interrupt is already pending in
+     *  APICPostInterrupts().*/
+    STAMCOUNTER                 StatPostIntrAlreadyPending;
     /** @} */
 #endif
