Index: trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 72428)
+++ trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 72440)
@@ -91,5 +91,5 @@
         else if (     rc == VINF_HM_DOUBLE_FAULT) { return VINF_SUCCESS;            } \
         else if (     rc == VINF_EM_RESET \
-                 &&   HMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_SHUTDOWN)) \
+                 &&   CPUMIsGuestSvmCtrlInterceptSet(pVCpu, pCtx, SVM_CTRL_INTERCEPT_SHUTDOWN)) \
             return VBOXSTRICTRC_TODO(IEMExecSvmVmexit(pVCpu, SVM_EXIT_SHUTDOWN, 0, 0)); \
         else \
@@ -374,5 +374,4 @@
 #endif
 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM
-static FNSVMEXITHANDLER hmR0SvmExitXcptPFNested;
 static FNSVMEXITHANDLER hmR0SvmExitClgi;
 static FNSVMEXITHANDLER hmR0SvmExitStgi;
@@ -5099,9 +5098,9 @@
                     return HM_SVM_VMEXIT_NESTED(pVCpu, uExitCode, u32ErrCode, uFaultAddress);
 
-                /* If the nested-guest is not intercepting #PFs, forward the #PF to the nested-guest. */
+                /* If the nested-guest is not intercepting #PFs, forward the #PF to the guest. */
                 hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
                 return VINF_SUCCESS;
             }
-            return hmR0SvmExitXcptPFNested(pVCpu, pCtx,pSvmTransient);
+            return hmR0SvmExitXcptPF(pVCpu, pCtx,pSvmTransient);
         }
 
@@ -5883,5 +5882,8 @@
                     /* Determine a vectoring #PF condition, see comment in hmR0SvmExitXcptPF(). */
                     if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
+                    {
                         pSvmTransient->fVectoringPF = true;
+                        Log4(("IDT: Pending vectoring #PF due to delivery of Ext-Int/NMI. uCR2=%#RX64\n", pCtx->cr2));
+                    }
                     else if (   pVmcb->ctrl.ExitIntInfo.n.u3Type == SVM_EVENT_EXCEPTION
                              && uIdtVector == X86_XCPT_PF)
@@ -5923,4 +5925,5 @@
                 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
                 {
+                    Log4(("IDT: Pending vectoring double #PF uCR2=%#RX64\n", pCtx->cr2));
                     pSvmTransient->fVectoringDoublePF = true;
                     Assert(rc == VINF_SUCCESS);
@@ -7252,13 +7255,12 @@
 {
     HMSVM_VALIDATE_EXIT_HANDLER_PARAMS();
-    HMSVM_ASSERT_NOT_IN_NESTED_GUEST(pCtx);
 
     HMSVM_CHECK_EXIT_DUE_TO_EVENT_DELIVERY();
 
     /* See AMD spec. 15.12.15 "#PF (Page Fault)". */
-    PSVMVMCB    pVmcb         = pVCpu->hm.s.svm.pVmcb;
-    uint32_t    u32ErrCode    = pVmcb->ctrl.u64ExitInfo1;
-    RTGCUINTPTR uFaultAddress = pVmcb->ctrl.u64ExitInfo2;
-    PVM         pVM           = pVCpu->CTX_SUFF(pVM);
+    PVM             pVM           = pVCpu->CTX_SUFF(pVM);
+    PSVMVMCB        pVmcb         = hmR0SvmGetCurrentVmcb(pVCpu, pCtx);
+    uint32_t        uErrCode      = pVmcb->ctrl.u64ExitInfo1;
+    uint64_t const  uFaultAddress = pVmcb->ctrl.u64ExitInfo2;
 
 #if defined(HMSVM_ALWAYS_TRAP_ALL_XCPTS) || defined(HMSVM_ALWAYS_TRAP_PF)
@@ -7266,10 +7268,11 @@
     {
         pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
-        if (!pSvmTransient->fVectoringDoublePF)
+        if (   !pSvmTransient->fVectoringDoublePF
+            || CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
         {
             /* A genuine guest #PF, reflect it to the guest. */
-            hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
-            Log4(("#PF: Guest page fault at %04X:%RGv FaultAddr=%RGv ErrCode=%#x\n", pCtx->cs.Sel, (RTGCPTR)pCtx->rip,
-                  uFaultAddress, u32ErrCode));
+            hmR0SvmSetPendingXcptPF(pVCpu, pCtx, uErrCode, uFaultAddress);
+            Log4(("#PF: Guest page fault at %04X:%RGv FaultAddr=%RX64 ErrCode=%#x\n", pCtx->cs.Sel, (RTGCPTR)pCtx->rip,
+                  uFaultAddress, uErrCode));
         }
         else
@@ -7291,5 +7294,6 @@
     if (   pVM->hm.s.fTprPatchingAllowed
         && (uFaultAddress & 0xfff) == XAPIC_OFF_TPR
-        && !(u32ErrCode & X86_TRAP_PF_P)              /* Not present. */
+        && !(uErrCode & X86_TRAP_PF_P)                /* Not present. */
+        && !CPUMIsGuestInSvmNestedHwVirtMode(pCtx)
         && !CPUMIsGuestInLongModeEx(pCtx)
         && !CPUMGetGuestCPL(pVCpu)
@@ -7313,6 +7317,6 @@
     }
 
-    Log4(("#PF: uFaultAddress=%#RX64 CS:RIP=%#04x:%#RX64 u32ErrCode %#RX32 cr3=%#RX64\n", uFaultAddress, pCtx->cs.Sel,
-          pCtx->rip, u32ErrCode, pCtx->cr3));
+    Log4(("#PF: uFaultAddress=%#RX64 CS:RIP=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", uFaultAddress, pCtx->cs.Sel,
+          pCtx->rip, uErrCode, pCtx->cr3));
 
     /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
@@ -7324,8 +7328,8 @@
     }
 
-    TRPMAssertXcptPF(pVCpu, uFaultAddress, u32ErrCode);
-    int rc = PGMTrap0eHandler(pVCpu, u32ErrCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
-
-    Log4(("#PF rc=%Rrc\n", rc));
+    TRPMAssertXcptPF(pVCpu, uFaultAddress, uErrCode);
+    int rc = PGMTrap0eHandler(pVCpu, uErrCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
+
+    Log4(("#PF: rc=%Rrc\n", rc));
 
     if (rc == VINF_SUCCESS)
@@ -7337,14 +7341,29 @@
         return rc;
     }
-    else if (rc == VINF_EM_RAW_GUEST_TRAP)
+
+    if (rc == VINF_EM_RAW_GUEST_TRAP)
     {
         pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
 
-        if (!pSvmTransient->fVectoringDoublePF)
-        {
-            /* It's a guest page fault and needs to be reflected to the guest. */
-            u32ErrCode = TRPMGetErrorCode(pVCpu);        /* The error code might have been changed. */
+        /*
+         * If a nested-guest delivers a #PF and that causes a #PF which is -not- a shadow #PF,
+         * we should simply forward the #PF to the guest and is up to the nested-hypervisor to
+         * determine whether it is a nested-shadow #PF or a #DF, see @bugref{7243#c121}.
+         */
+        if (  !pSvmTransient->fVectoringDoublePF
+            || CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
+        {
+            /* It's a guest (or nested-guest) page fault and needs to be reflected. */
+            uErrCode = TRPMGetErrorCode(pVCpu);        /* The error code might have been changed. */
             TRPMResetTrap(pVCpu);
-            hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
+
+#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
+            /* If the nested-guest is intercepting #PFs, cause a #PF #VMEXIT. */
+            if (   CPUMIsGuestInSvmNestedHwVirtMode(pCtx)
+                && HMIsGuestSvmXcptInterceptSet(pVCpu, pCtx, X86_XCPT_PF))
+                return VBOXSTRICTRC_TODO(IEMExecSvmVmexit(pVCpu, SVM_EXIT_XCPT_PF, uErrCode, uFaultAddress));
+#endif
+
+            hmR0SvmSetPendingXcptPF(pVCpu, pCtx, uErrCode, uFaultAddress);
         }
         else
@@ -7594,75 +7613,4 @@
 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM
 /**
- * \#VMEXIT handler for #PF occuring while in nested-guest execution
- * (SVM_EXIT_XCPT_14). Conditional \#VMEXIT.
- */
-HMSVM_EXIT_DECL hmR0SvmExitXcptPFNested(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient)
-{
-    HMSVM_VALIDATE_EXIT_HANDLER_PARAMS();
-
-    HMSVM_CHECK_EXIT_DUE_TO_EVENT_DELIVERY();
-
-    /* See AMD spec. 15.12.15 "#PF (Page Fault)". */
-    PSVMVMCB       pVmcb         = hmR0SvmGetCurrentVmcb(pVCpu, pCtx);
-    uint32_t       u32ErrCode    = pVmcb->ctrl.u64ExitInfo1;
-    uint64_t const uFaultAddress = pVmcb->ctrl.u64ExitInfo2;
-
-    Log4(("#PFNested: uFaultAddress=%#RX64 CS:RIP=%#04x:%#RX64 u32ErrCode=%#RX32 CR3=%#RX64\n", uFaultAddress, pCtx->cs.Sel,
-          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{6607}. */
-    if (pSvmTransient->fVectoringPF)
-    {
-        Assert(pVCpu->hm.s.Event.fPending);
-        return VINF_EM_RAW_INJECT_TRPM_EVENT;
-    }
-
-    Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
-
-    TRPMAssertXcptPF(pVCpu, uFaultAddress, u32ErrCode);
-    int rc = PGMTrap0eHandler(pVCpu, u32ErrCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress);
-
-    Log4(("#PFNested: rc=%Rrc\n", rc));
-
-    if (rc == VINF_SUCCESS)
-    {
-        /* Successfully synced shadow pages tables or emulated an MMIO instruction. */
-        TRPMResetTrap(pVCpu);
-        STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
-        HMCPU_CF_SET(pVCpu, HM_CHANGED_ALL_GUEST);
-        return rc;
-    }
-
-    if (rc == VINF_EM_RAW_GUEST_TRAP)
-    {
-        pVCpu->hm.s.Event.fPending = false;     /* In case it's a contributory or vectoring #PF. */
-
-        if (!pSvmTransient->fVectoringDoublePF)
-        {
-            /* It's a nested-guest page fault and needs to be reflected to the nested-guest. */
-            u32ErrCode = TRPMGetErrorCode(pVCpu);        /* The error code might have been changed. */
-            TRPMResetTrap(pVCpu);
-            hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress);
-        }
-        else
-        {
-            /* A nested-guest page-fault occurred during delivery of a page-fault. Inject #DF. */
-            TRPMResetTrap(pVCpu);
-            hmR0SvmSetPendingXcptDF(pVCpu);
-            Log4(("#PF: Pending #DF due to vectoring #PF\n"));
-        }
-
-        STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
-        return VINF_SUCCESS;
-    }
-
-    TRPMResetTrap(pVCpu);
-    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
-    return rc;
-}
-
-
-/**
  * \#VMEXIT handler for CLGI (SVM_EXIT_CLGI). Conditional \#VMEXIT.
  */
