Index: /trunk/include/VBox/vmm/hm.h
===================================================================
--- /trunk/include/VBox/vmm/hm.h	(revision 67203)
+++ /trunk/include/VBox/vmm/hm.h	(revision 67204)
@@ -158,5 +158,6 @@
 VMM_INT_DECL(VBOXSTRICTRC)      HMSvmVmrun(PVMCPU pVCpu, PCPUMCTX pCtx, uint8_t cbInstr, RTGCPHYS GCPhysVmcb);
 VMM_INT_DECL(uint8_t)           HMSvmNstGstGetInterrupt(PCCPUMCTX pCtx);
-VMM_INT_DECL(bool)              HMSvmNstGstCanTakeInterrupt(PVMCPU pVCpu, PCCPUMCTX pCtx);
+VMM_INT_DECL(bool)              HMSvmNstGstCanTakePhysInterrupt(PVMCPU pVCpu, PCCPUMCTX pCtx);
+VMM_INT_DECL(bool)              HMSvmNstGstCanTakeVirtInterrupt(PVMCPU pVCpu, PCCPUMCTX pCtx);
 VMM_INT_DECL(VBOXSTRICTRC)      HMSvmNstGstHandleCtrlIntercept(PVMCPU pVCpu, PCPUMCTX pCtx, uint64_t uExitCode,
                                                                uint64_t uExitInfo1, uint64_t uExitInfo2);
Index: /trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp	(revision 67203)
+++ /trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp	(revision 67204)
@@ -811,35 +811,57 @@
 
 /**
- * Checks whether an interrupt is pending for the nested-guest.
+ * Checks whether the nested-guest is in a state to receive physical (APIC)
+ * interrupts.
  *
  * @returns VBox status code.
- * @retval  true if there's a pending interrupt, false otherwise.
+ * @retval  true if it's ready, false otherwise.
  *
  * @param   pVCpu       The cross context virtual CPU structure.
  * @param   pCtx        The guest-CPU context.
  */
-VMM_INT_DECL(bool) HMSvmNstGstCanTakeInterrupt(PVMCPU pVCpu, PCCPUMCTX pCtx)
+VMM_INT_DECL(bool) HMSvmNstGstCanTakePhysInterrupt(PVMCPU pVCpu, PCCPUMCTX pCtx)
 {
+    Assert(CPUMIsGuestInSvmNestedHwVirtMode(pCtx));
+    RT_NOREF(pVCpu);
+
     PCSVMVMCBCTRL pVmcbCtrl = &pCtx->hwvirt.svm.VmcbCtrl;
+    X86EFLAGS fEFlags;
+    if (!pVmcbCtrl->IntCtrl.n.u1VIntrMasking)
+        fEFlags.u = pCtx->hwvirt.svm.HostState.rflags.u;
+    else
+        fEFlags.u = pCtx->eflags.u;
+
+    return pCtx->hwvirt.svm.fGif && fEFlags.Bits.u1IF;
+}
+
+
+/**
+ * Checks whether the nested-guest is in a state to receive virtual (injected by
+ * VMRUN) interrupts.
+ *
+ * @returns VBox status code.
+ * @retval  true if it's ready, false otherwise.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   pCtx        The guest-CPU context.
+ */
+VMM_INT_DECL(bool) HMSvmNstGstCanTakeVirtInterrupt(PVMCPU pVCpu, PCCPUMCTX pCtx)
+{
     Assert(CPUMIsGuestInSvmNestedHwVirtMode(pCtx));
-
-    X86RFLAGS RFlags;
-    if (pVmcbCtrl->IntCtrl.n.u1VIntrMasking)
-        RFlags.u = pCtx->rflags.u;
-    else
-        RFlags.u = pCtx->hwvirt.svm.HostState.rflags.u;
-
-    if (!RFlags.Bits.u1IF)
-        return false;
-
+    Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS));
+    Assert(VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST));
+    RT_NOREF(pVCpu);
+
+    PCSVMVMCBCTRL pVmcbCtrl = &pCtx->hwvirt.svm.VmcbCtrl;
     if (   !pVmcbCtrl->IntCtrl.n.u1IgnoreTPR
         &&  pVmcbCtrl->IntCtrl.n.u4VIntrPrio <= pVmcbCtrl->IntCtrl.n.u8VTPR)
         return false;
 
-    /* Paranoia. */
-    Assert(RT_BOOL(pCtx->hwvirt.svm.fGif));
-    Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS));
-    Assert(VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST));
-    RT_NOREF(pVCpu);
+    if (!pCtx->rflags.Bits.u1IF)
+        return false;
+
+    if (!pCtx->hwvirt.svm.fGif)
+        return false;
+
     return true;
 }
Index: /trunk/src/VBox/VMM/VMMR3/EM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 67203)
+++ /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 67204)
@@ -1951,4 +1951,5 @@
          * Interrupts.
          */
+        /** @todo this can be optimized a bit. later.   */
         bool fWakeupPending = false;
         if (    !VM_FF_IS_PENDING(pVM, VM_FF_PGM_NO_MEMORY)
@@ -1956,67 +1957,33 @@
         {
             if (    !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
-                &&  !TRPMHasTrap(pVCpu) /* an interrupt could already be scheduled for dispatching in the recompiler. */
+                &&  !TRPMHasTrap(pVCpu)) /* an interrupt could already be scheduled for dispatching in the recompiler. */
+            {
+                bool     fIntrEnabled;
+                PCPUMCTX pCtx = pVCpu->em.s.pCtx;
 #ifdef VBOX_WITH_RAW_MODE
-                &&  PATMAreInterruptsEnabled(pVM)
+                fIntrEnabled = PATMAreInterruptsEnabled(pVM); RT_NOREF(pCtx);
+#elif defined(VBOX_WITH_NESTED_HWVIRT)
+                if (CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
+                    fIntrEnabled = HMSvmNstGstCanTakePhysInterrupt(pVCpu, pCtx);
+                else
+                    fIntrEnabled = pCtx->eflags.Bits.u1IF;
 #else
-                &&  (pVCpu->em.s.pCtx->eflags.u32 & X86_EFL_IF)
-#endif
+                fIntrEnabled = pCtx->eflags.Bits.u1IF;
+#endif
+                if (fIntrEnabled)
+                {
+                    Assert(!HMR3IsEventPending(pVCpu));
+                    Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
+                    if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
+                    {
 #ifdef VBOX_WITH_NESTED_HWVIRT
-                &&  pVCpu->em.s.pCtx->hwvirt.svm.fGif
-#endif
-                )
-            {
-                Assert(!HMR3IsEventPending(pVCpu));
-                Assert(pVCpu->em.s.enmState != EMSTATE_WAIT_SIPI);
-                if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))
-                {
-#ifdef VBOX_WITH_NESTED_HWVIRT
-                    PCPUMCTX pCtx = pVCpu->em.s.pCtx;
-                    if (CPUMIsGuestSvmCtrlInterceptSet(pCtx, SVM_CTRL_INTERCEPT_INTR))
-                    {
-                        VBOXSTRICTRC rcStrict = HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_INTR, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
-                        if (rcStrict == VINF_SVM_VMEXIT)
-                            rc2 = VINF_EM_RESCHEDULE;
-                        else
+                        if (CPUMIsGuestSvmCtrlInterceptSet(pCtx, SVM_CTRL_INTERCEPT_INTR))
                         {
-                            Log(("EM: SVM Nested-guest INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
-                            /** @todo should we call iemInitiateCpuShutdown? Should this
-                             *        result in trapping triple-fault intercepts? */
-                            rc2 = VINF_EM_TRIPLE_FAULT;
-                        }
-                    }
-                    else
-#endif
-                    {
-                        /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */
-                        /** @todo this really isn't nice, should properly handle this */
-                        rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);
-                        if (pVM->em.s.fIemExecutesAll && (rc2 == VINF_EM_RESCHEDULE_REM || rc2 == VINF_EM_RESCHEDULE_HM || rc2 == VINF_EM_RESCHEDULE_RAW))
-                            rc2 = VINF_EM_RESCHEDULE;
-#ifdef VBOX_STRICT
-                        rcIrq = rc2;
-#endif
-                    }
-                    UPDATE_RC();
-                    /* Reschedule required: We must not miss the wakeup below! */
-                    fWakeupPending = true;
-                }
-#ifdef VBOX_WITH_NESTED_HWVIRT
-                else if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST))
-                {
-                    PCPUMCTX pCtx = pVCpu->em.s.pCtx;
-                    if (HMSvmNstGstCanTakeInterrupt(pVCpu, pCtx))
-                    {
-                        /*
-                         * Check nested-guest virtual interrupts.
-                         */
-                        if (CPUMIsGuestSvmCtrlInterceptSet(pCtx, SVM_CTRL_INTERCEPT_VINTR))
-                        {
-                            VBOXSTRICTRC rcStrict = HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_VINTR, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+                            VBOXSTRICTRC rcStrict = HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_INTR, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
                             if (rcStrict == VINF_SVM_VMEXIT)
                                 rc2 = VINF_EM_RESCHEDULE;
                             else
                             {
-                                Log(("EM: SVM Nested-guest VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
+                                Log(("EM: SVM Nested-guest INTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
                                 /** @todo should we call iemInitiateCpuShutdown? Should this
                                  *        result in trapping triple-fault intercepts? */
@@ -2025,14 +1992,14 @@
                         }
                         else
+#endif
                         {
-                            /*
-                             * Prepare the nested-guest interrupt for injection.
-                             */
-                            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);
-                            uint8_t uNstGstVector = HMSvmNstGstGetInterrupt(pCtx);
-                            TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT);
-                            /** @todo reschedule to HM/REM later, when the HMR0 nested-guest execution is
-                             *  done. For now just reschedule to IEM. */
-                            rc2 = VINF_EM_RESCHEDULE;
+                            /* Note: it's important to make sure the return code from TRPMR3InjectEvent isn't ignored! */
+                            /** @todo this really isn't nice, should properly handle this */
+                            rc2 = TRPMR3InjectEvent(pVM, pVCpu, TRPM_HARDWARE_INT);
+                            if (pVM->em.s.fIemExecutesAll && (rc2 == VINF_EM_RESCHEDULE_REM || rc2 == VINF_EM_RESCHEDULE_HM || rc2 == VINF_EM_RESCHEDULE_RAW))
+                                rc2 = VINF_EM_RESCHEDULE;
+#ifdef VBOX_STRICT
+                            rcIrq = rc2;
+#endif
                         }
                         UPDATE_RC();
@@ -2040,6 +2007,44 @@
                         fWakeupPending = true;
                     }
+#ifdef VBOX_WITH_NESTED_HWVIRT
+                    else if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST))
+                    {
+                        /*
+                         * Check nested-guest virtual interrupts.
+                         */
+                        if (HMSvmNstGstCanTakeVirtInterrupt(pVCpu, pCtx))
+                        {
+                            if (CPUMIsGuestSvmCtrlInterceptSet(pCtx, SVM_CTRL_INTERCEPT_VINTR))
+                            {
+                                VBOXSTRICTRC rcStrict = HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_VINTR, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+                                if (rcStrict == VINF_SVM_VMEXIT)
+                                    rc2 = VINF_EM_RESCHEDULE;
+                                else
+                                {
+                                    Log(("EM: SVM Nested-guest VINTR #VMEXIT failed! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
+                                    /** @todo should we call iemInitiateCpuShutdown? Should this
+                                     *        result in trapping triple-fault intercepts? */
+                                    rc2 = VINF_EM_TRIPLE_FAULT;
+                                }
+                            }
+                            else
+                            {
+                                /*
+                                 * Prepare the nested-guest interrupt for injection.
+                                 */
+                                VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NESTED_GUEST);
+                                uint8_t uNstGstVector = HMSvmNstGstGetInterrupt(pCtx);
+                                TRPMAssertTrap(pVCpu, uNstGstVector, TRPM_HARDWARE_INT);
+                                /** @todo reschedule to HM/REM later, when the HMR0 nested-guest execution is
+                                 *  done. For now just reschedule to IEM. */
+                                rc2 = VINF_EM_RESCHEDULE;
+                            }
+                            UPDATE_RC();
+                            /* Reschedule required: We must not miss the wakeup below! */
+                            fWakeupPending = true;
+                        }
+                    }
+#endif  /* VBOX_WITH_NESTED_HWVIRT */
                 }
-#endif  /* VBOX_WITH_NESTED_HWVIRT */
             }
         }
