Index: /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 52652)
+++ /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 52653)
@@ -218,4 +218,7 @@
     /** Whether the #VMEXIT was caused by a page-fault during delivery of a
      *  contributary exception or a page-fault. */
+    bool            fVectoringDoublePF;
+    /** Whether the VM-exit was caused by a page-fault during delivery of an
+     *  external interrupt or NMI. */
     bool            fVectoringPF;
 } SVMTRANSIENT, *PSVMTRANSIENT;
@@ -2209,4 +2212,9 @@
     }
 
+    /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
+       and if we're injecting an event we should have a TRPM trap pending. */
+    Assert(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu));
+    Assert(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu));
+
     /* Sync. the necessary state for going back to ring-3. */
     hmR0SvmLeaveSession(pVM, pVCpu, pCtx);
@@ -3220,4 +3228,5 @@
     pSvmTransient->u64ExitCode  = pVmcb->ctrl.u64ExitCode;      /* Save the #VMEXIT reason. */
     HMCPU_EXIT_HISTORY_ADD(pVCpu, pVmcb->ctrl.u64ExitCode);     /* Update the #VMEXIT history array. */
+    pSvmTransient->fVectoringDoublePF = false;                  /* Vectoring double page-fault needs to be determined later. */
     pSvmTransient->fVectoringPF = false;                        /* Vectoring page-fault needs to be determined later. */
 
@@ -4055,6 +4064,6 @@
                     && uIdtVector  == X86_XCPT_PF)
                 {
-                    pSvmTransient->fVectoringPF = true;
-                    Log4(("IDT: Vectoring #PF uCR2=%#RX64\n", pCtx->cr2));
+                    pSvmTransient->fVectoringDoublePF = true;
+                    Log4(("IDT: Vectoring double #PF uCR2=%#RX64\n", pCtx->cr2));
                 }
                 else if (   (pVmcb->ctrl.u32InterceptException & HMSVM_CONTRIBUTORY_XCPT_MASK)
@@ -4085,10 +4094,21 @@
             }
         }
-        else if (pVmcb->ctrl.ExitIntInfo.n.u3Type != SVM_EVENT_SOFTWARE_INT)
-        {
-            /* Ignore software interrupts (INT n) as they reoccur when restarting the instruction. */
+        else if (   pVmcb->ctrl.ExitIntInfo.n.u3Type == SVM_EVENT_EXTERNAL_IRQ
+                 || pVmcb->ctrl.ExitIntInfo.n.u3Type == SVM_EVENT_NMI)
+        {
             enmReflect = SVMREFLECTXCPT_XCPT;
             fReflectingNmi = RT_BOOL(pVmcb->ctrl.ExitIntInfo.n.u3Type == SVM_EVENT_NMI);
-        }
+
+            if (pSvmTransient->u64ExitCode - SVM_EXIT_EXCEPTION_0 <= SVM_EXIT_EXCEPTION_1F)
+            {
+                uint8_t uExitVector = (uint8_t)(pSvmTransient->u64ExitCode - SVM_EXIT_EXCEPTION_0);
+                if (uExitVector == X86_XCPT_PF)
+                {
+                    pSvmTransient->fVectoringPF = true;
+                    Log4(("IDT: Vectoring #PF due to Ext-Int/NMI. uCR2=%#RX64\n", pCtx->cr2));
+                }
+            }
+        }
+        /* else: Ignore software interrupts (INT n) as they reoccur when restarting the instruction. */
 
         switch (enmReflect)
@@ -5044,5 +5064,5 @@
     {
         pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
-        if (!pSvmTransient->fVectoringPF)
+        if (!pSvmTransient->fVectoringDoublePF)
         {
             /* A genuine guest #PF, reflect it to the guest. */
@@ -5094,4 +5114,12 @@
           pCtx->rip, u32ErrCode, pCtx->cr3));
 
+    /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
+       of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{}. */
+    if (pSvmTransient->fVectoringPF)
+    {
+        Assert(pVCpu->hm.s.Event.fPending);
+        return VINF_EM_RAW_INJECT_TRPM_EVENT;
+    }
+
     TRPMAssertXcptPF(pVCpu, uFaultAddress, u32ErrCode);
     int rc = PGMTrap0eHandler(pVCpu, u32ErrCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
@@ -5111,5 +5139,5 @@
         pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
 
-        if (!pSvmTransient->fVectoringPF)
+        if (!pSvmTransient->fVectoringDoublePF)
         {
             /* It's a guest page fault and needs to be reflected to the guest. */
Index: /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 52652)
+++ /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 52653)
@@ -279,4 +279,7 @@
     /** Whether the VM-exit was caused by a page-fault during delivery of a
      *  contributory exception or a page-fault. */
+    bool            fVectoringDoublePF;
+    /** Whether the VM-exit was caused by a page-fault during delivery of an
+     *  external interrupt or NMI. */
     bool            fVectoringPF;
 } VMXTRANSIENT;
@@ -5801,6 +5804,6 @@
                     && uIdtVector == X86_XCPT_PF)
                 {
-                    pVmxTransient->fVectoringPF = true;
-                    Log4(("IDT: vcpu[%RU32] Vectoring #PF uCR2=%#RX64\n", pVCpu->idCpu, pMixedCtx->cr2));
+                    pVmxTransient->fVectoringDoublePF = true;
+                    Log4(("IDT: vcpu[%RU32] Vectoring Double #PF uCR2=%#RX64\n", pVCpu->idCpu, pMixedCtx->cr2));
                 }
                 else if (   (pVCpu->hm.s.vmx.u32XcptBitmap & HMVMX_CONTRIBUTORY_XCPT_MASK)
@@ -5814,6 +5817,5 @@
                     enmReflect = VMXREFLECTXCPT_TF;
             }
-            else if (   uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
-                     || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT
+            else if (   uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT
                      || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI)
             {
@@ -5823,4 +5825,10 @@
                  */
                 enmReflect = VMXREFLECTXCPT_XCPT;
+
+                if (uExitVector == X86_XCPT_PF)
+                {
+                    pVmxTransient->fVectoringPF = true;
+                    Log4(("IDT: vcpu[%RU32] Vectoring #PF due to Ext-Int/NMI. uCR2=%#RX64\n", pVCpu->idCpu, pMixedCtx->cr2));
+                }
             }
         }
@@ -7187,8 +7195,14 @@
     }
 
+    /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
+       and if we're injecting an event we should have a TRPM trap pending. */
+    Assert(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu));
+    Assert(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu));
+
     /* Save guest state and restore host state bits. */
     int rc = hmR0VmxLeaveSession(pVM, pVCpu, pMixedCtx);
     AssertRCReturn(rc, rc);
     STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
+    /* Thread-context hooks are unregistered at this point!!! */
 
     /* Sync recompiler state. */
@@ -8678,4 +8692,5 @@
     pVmxTransient->fVmcsFieldsRead     = 0;                     /* Transient fields need to be read from the VMCS. */
     pVmxTransient->fVectoringPF        = false;                 /* Vectoring page-fault needs to be determined later. */
+    pVmxTransient->fVectoringDoublePF  = false;                 /* Vectoring double page-fault needs to be determined later. */
 
     if (!(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT))
@@ -11963,5 +11978,5 @@
     {
         pVCpu->hm.s.Event.fPending = false;                  /* In case it's a contributory or vectoring #PF. */
-        if (RT_LIKELY(!pVmxTransient->fVectoringPF))
+        if (RT_LIKELY(!pVmxTransient->fVectoringDoublePF))
         {
             pMixedCtx->cr2 = pVmxTransient->uExitQualification;  /* Update here in case we go back to ring-3 before injection. */
@@ -11982,4 +11997,12 @@
     NOREF(pVM);
 #endif
+
+    /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
+       of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{}. */
+    if (pVmxTransient->fVectoringPF)
+    {
+        Assert(pVCpu->hm.s.Event.fPending);
+        return VINF_EM_RAW_INJECT_TRPM_EVENT;
+    }
 
     rc = hmR0VmxSaveGuestState(pVCpu, pMixedCtx);
@@ -12009,5 +12032,5 @@
     else if (rc == VINF_EM_RAW_GUEST_TRAP)
     {
-        if (!pVmxTransient->fVectoringPF)
+        if (!pVmxTransient->fVectoringDoublePF)
         {
             /* It's a guest page fault and needs to be reflected to the guest. */
