Index: trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 91580)
@@ -2325,8 +2325,8 @@
 
 /**
- * Sets the PAE PDPTEs for the guest.
+ * Sets the PAE PDPEs for the guest.
  *
  * @param   pVCpu       The cross context virtual CPU structure of the calling thread.
- * @param   paPaePdpes  The PAE PDPTEs to set.
+ * @param   paPaePdpes  The PAE PDPEs to set.
  */
 VMM_INT_DECL(void) CPUMSetGuestPaePdpes(PVMCPU pVCpu, PCX86PDPE paPaePdpes)
@@ -2336,4 +2336,19 @@
         pVCpu->cpum.s.Guest.aPaePdpes[i].u = paPaePdpes[i].u;
     pVCpu->cpum.s.Guest.fExtrn &= ~CPUMCTX_EXTRN_CR3;
+}
+
+
+/**
+ * Gets the PAE PDPTEs for the guest.
+ *
+ * @param   pVCpu       The cross context virtual CPU structure of the calling thread.
+ * @param   paPaePdpes  Where to store the PAE PDPEs.
+ */
+VMM_INT_DECL(void) CPUMGetGuestPaePdpes(PVMCPU pVCpu, PX86PDPE paPaePdpes)
+{
+    Assert(paPaePdpes);
+    CPUM_INT_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_CR3);
+    for (unsigned i = 0; i < RT_ELEMENTS(pVCpu->cpum.s.Guest.aPaePdpes); i++)
+        paPaePdpes[i].u = pVCpu->cpum.s.Guest.aPaePdpes[i].u;
 }
 
Index: trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/HMVMXAll.cpp	(revision 91580)
@@ -205,9 +205,5 @@
     VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPatMsr              , "GuestPatMsr"               ),
     VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPcide               , "GuestPcide"                ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPdpteCr3ReadPhys    , "GuestPdpteCr3ReadPhys"     ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPdpte0Rsvd          , "GuestPdpte0Rsvd"           ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPdpte1Rsvd          , "GuestPdpte1Rsvd"           ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPdpte2Rsvd          , "GuestPdpte2Rsvd"           ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPdpte3Rsvd          , "GuestPdpte3Rsvd"           ),
+    VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPdpte               , "GuestPdpteRsvd"            ),
     VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPndDbgXcptBsNoTf    , "GuestPndDbgXcptBsNoTf"     ),
     VMXV_DIAG_DESC(kVmxVDiag_Vmentry_GuestPndDbgXcptBsTf      , "GuestPndDbgXcptBsTf"       ),
@@ -362,9 +358,5 @@
     VMXV_DIAG_DESC(kVmxVDiag_Vmentry_VmxRoot                  , "VmxRoot"                   ),
     VMXV_DIAG_DESC(kVmxVDiag_Vmentry_Vpid                     , "Vpid"                      ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpteCr3ReadPhys      , "HostPdpteCr3ReadPhys"      ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte0Rsvd            , "HostPdpte0Rsvd"            ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte1Rsvd            , "HostPdpte1Rsvd"            ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte2Rsvd            , "HostPdpte2Rsvd"            ),
-    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte3Rsvd            , "HostPdpte3Rsvd"            ),
+    VMXV_DIAG_DESC(kVmxVDiag_Vmexit_HostPdpte                 , "HostPdpte"                 ),
     VMXV_DIAG_DESC(kVmxVDiag_Vmexit_MsrLoad                   , "MsrLoad"                   ),
     VMXV_DIAG_DESC(kVmxVDiag_Vmexit_MsrLoadCount              , "MsrLoadCount"              ),
Index: trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 91580)
@@ -4355,5 +4355,6 @@
 
         /* Inform PGM. */
-        rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, !(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PGE));
+        /** @todo Should we raise \#GP(0) here when PAE PDPEs are invalid? */
+        rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, !(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PGE), false /* fPdpesMapped */);
         AssertRCReturn(rc, rc);
         /* ignore informational status codes */
Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 91580)
@@ -3918,5 +3918,5 @@
     if ((uNewCr0 & X86_CR0_PE) != (uOldCr0 & X86_CR0_PE))
     {
-        int rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /* global */);
+        int rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /* global */, false /* fPdpesMapped */);
         AssertRCReturn(rc, rc);
         /* ignore informational status codes */
@@ -5698,4 +5698,26 @@
 
 /**
+ * Helper for mapping CR3 and PAE PDPEs for 'mov CRx,GReg'.
+ */
+#define IEM_MAP_PAE_PDPES_AT_CR3_RET(a_pVCpu, a_iCrReg, a_uCr3) \
+    do \
+    { \
+        int const rcX = PGMGstMapPaePdpesAtCr3(a_pVCpu, a_uCr3); \
+        if (RT_SUCCESS(rcX)) \
+        { /* likely */ } \
+        else \
+        { \
+            if (rcX == VERR_PGM_PAE_PDPE_RSVD) \
+            { \
+                Log(("iemCImpl_load_Cr%#x: Trying to load invalid PAE PDPEs\n", a_iCrReg)); \
+                return iemRaiseGeneralProtectionFault0(a_pVCpu); \
+            } \
+            Log(("iemCImpl_load_Cr%#x: PGMGstReadPaePdpesAtCr3 failed %Rrc\n", a_iCrReg, rcX)); \
+            return rcX; \
+        } \
+    } while (0)
+
+
+/**
  * Used to implemented 'mov CRx,GReg' and 'lmsw r/m16'.
  *
@@ -5807,6 +5829,4 @@
             }
 
-            /** @todo check reserved PDPTR bits as AMD states. */
-
             /*
              * SVM nested-guest CR0 write intercepts.
@@ -5832,16 +5852,10 @@
 
             /*
-             * Change CR0.
-             */
-            CPUMSetGuestCR0(pVCpu, uNewCrX);
-            Assert(pVCpu->cpum.GstCtx.cr0 == uNewCrX);
-
-            /*
              * Change EFER.LMA if entering or leaving long mode.
              */
+            uint64_t NewEFER = pVCpu->cpum.GstCtx.msrEFER;
             if (   (uNewCrX & X86_CR0_PG) != (uOldCrX & X86_CR0_PG)
                 && (pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME) )
             {
-                uint64_t NewEFER = pVCpu->cpum.GstCtx.msrEFER;
                 if (uNewCrX & X86_CR0_PG)
                     NewEFER |= MSR_K6_EFER_LMA;
@@ -5859,8 +5873,25 @@
                 !=  (uOldCrX & (X86_CR0_PG | X86_CR0_WP | X86_CR0_PE | X86_CR0_CD | X86_CR0_NW)) )
             {
-                rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /* global */);
+                bool fPdpesMapped;
+                if (    enmAccessCrX != IEMACCESSCRX_MOV_CRX
+                    || !CPUMIsPaePagingEnabled(uNewCrX, pVCpu->cpum.GstCtx.cr4, NewEFER)
+                    ||  CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu)))
+                    fPdpesMapped = false;
+                else
+                {
+                    IEM_MAP_PAE_PDPES_AT_CR3_RET(pVCpu, iCrReg, pVCpu->cpum.GstCtx.cr3);
+                    fPdpesMapped = true;
+                }
+                rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /* global */, fPdpesMapped);
                 AssertRCReturn(rc, rc);
                 /* ignore informational status codes */
             }
+
+            /*
+             * Change CR0.
+             */
+            CPUMSetGuestCR0(pVCpu, uNewCrX);
+            Assert(pVCpu->cpum.GstCtx.cr0 == uNewCrX);
+
             rcStrict = PGMChangeMode(pVCpu, pVCpu->cpum.GstCtx.cr0, pVCpu->cpum.GstCtx.cr4, pVCpu->cpum.GstCtx.msrEFER);
             break;
@@ -5935,6 +5966,21 @@
             }
 
-            /** @todo If we're in PAE mode we should check the PDPTRs for
-             *        invalid bits. */
+            /* Inform PGM. */
+            if (pVCpu->cpum.GstCtx.cr0 & X86_CR0_PG)
+            {
+                bool fPdpesMapped;
+                if (   !CPUMIsGuestInPAEModeEx(IEM_GET_CTX(pVCpu))
+                    ||  CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu)))
+                    fPdpesMapped = false;
+                else
+                {
+                    Assert(enmAccessCrX == IEMACCESSCRX_MOV_CRX);
+                    IEM_MAP_PAE_PDPES_AT_CR3_RET(pVCpu, iCrReg, uNewCrX);
+                    fPdpesMapped = true;
+                }
+                rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, !(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PGE), fPdpesMapped);
+                AssertRCReturn(rc, rc);
+                /* ignore informational status codes */
+            }
 
             /* Make the change. */
@@ -5942,11 +5988,4 @@
             AssertRCSuccessReturn(rc, rc);
 
-            /* Inform PGM. */
-            if (pVCpu->cpum.GstCtx.cr0 & X86_CR0_PG)
-            {
-                rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, !(pVCpu->cpum.GstCtx.cr4 & X86_CR4_PGE));
-                AssertRCReturn(rc, rc);
-                /* ignore informational status codes */
-            }
             rcStrict = VINF_SUCCESS;
             break;
@@ -6018,4 +6057,24 @@
 
             /*
+             * Notify PGM.
+             */
+            if ((uNewCrX ^ uOldCrX) & (X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE | X86_CR4_PCIDE /* | X86_CR4_SMEP */))
+            {
+                bool fPdpesMapped;
+                if (   !CPUMIsPaePagingEnabled(pVCpu->cpum.GstCtx.cr0, uNewCrX, pVCpu->cpum.GstCtx.msrEFER)
+                    || CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu)))
+                    fPdpesMapped = false;
+                else
+                {
+                    Assert(enmAccessCrX == IEMACCESSCRX_MOV_CRX);
+                    IEM_MAP_PAE_PDPES_AT_CR3_RET(pVCpu, iCrReg, pVCpu->cpum.GstCtx.cr3);
+                    fPdpesMapped = true;
+                }
+                rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /* global */, fPdpesMapped);
+                AssertRCReturn(rc, rc);
+                /* ignore informational status codes */
+            }
+
+            /*
              * Change it.
              */
@@ -6024,18 +6083,4 @@
             Assert(pVCpu->cpum.GstCtx.cr4 == uNewCrX);
 
-            /*
-             * Notify SELM and PGM.
-             */
-            /* SELM - VME may change things wrt to the TSS shadowing. */
-            if ((uNewCrX ^ uOldCrX) & X86_CR4_VME)
-                Log(("iemCImpl_load_CrX: VME %d -> %d\n", RT_BOOL(uOldCrX & X86_CR4_VME), RT_BOOL(uNewCrX & X86_CR4_VME) ));
-
-            /* PGM - flushing and mode. */
-            if ((uNewCrX ^ uOldCrX) & (X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE | X86_CR4_PCIDE /* | X86_CR4_SMEP */))
-            {
-                rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /* global */);
-                AssertRCReturn(rc, rc);
-                /* ignore informational status codes */
-            }
             rcStrict = PGMChangeMode(pVCpu, pVCpu->cpum.GstCtx.cr0, pVCpu->cpum.GstCtx.cr4, pVCpu->cpum.GstCtx.msrEFER);
             break;
@@ -6692,5 +6737,5 @@
 
                 /* Invalidate mappings for the linear address tagged with PCID except global translations. */
-                PGMFlushTLB(pVCpu, uCr3, false /* fGlobal */);
+                PGMFlushTLB(pVCpu, uCr3, false /* fGlobal */, false /* fPdpesMapped */);
                 break;
             }
@@ -6705,5 +6750,5 @@
                 }
                 /* Invalidate all mappings associated with PCID except global translations. */
-                PGMFlushTLB(pVCpu, uCr3, false /* fGlobal */);
+                PGMFlushTLB(pVCpu, uCr3, false /* fGlobal */, false /* fPdpesMapped */);
                 break;
             }
@@ -6711,5 +6756,5 @@
             case X86_INVPCID_TYPE_ALL_CONTEXT_INCL_GLOBAL:
             {
-                PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */);
+                PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */, false /* fPdpesMapped */);
                 break;
             }
@@ -6717,5 +6762,5 @@
             case X86_INVPCID_TYPE_ALL_CONTEXT_EXCL_GLOBAL:
             {
-                PGMFlushTLB(pVCpu, uCr3, false /* fGlobal */);
+                PGMFlushTLB(pVCpu, uCr3, false /* fGlobal */, false /* fPdpesMapped */);
                 break;
             }
Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImplSvmInstr.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImplSvmInstr.cpp.h	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImplSvmInstr.cpp.h	(revision 91580)
@@ -82,7 +82,8 @@
  *
  * @returns Strict VBox status code.
- * @param   pVCpu       The cross context virtual CPU structure.
- */
-DECLINLINE(VBOXSTRICTRC) iemSvmWorldSwitch(PVMCPUCC pVCpu)
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   fPdpesMapped    Whether the PAE PDPEs (and PDPT) have been mapped.
+ */
+DECLINLINE(VBOXSTRICTRC) iemSvmWorldSwitch(PVMCPUCC pVCpu, bool fPdpesMapped)
 {
     /*
@@ -106,5 +107,5 @@
     if (rc == VINF_SUCCESS)
     {
-        rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true);
+        rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /* fGlobal */, fPdpesMapped);
         AssertRCReturn(rc, rc);
     }
@@ -307,27 +308,43 @@
 
             /*
-             * Reload the guest's "host state".
+             * If we are switching to PAE mode host, validate the PDPEs first.
+             * Any invalid PDPEs here causes a VCPU shutdown.
              */
-            CPUMSvmVmExitRestoreHostState(pVCpu, IEM_GET_CTX(pVCpu));
-
-            /*
-             * Update PGM, IEM and others of a world-switch.
-             */
-            rcStrict = iemSvmWorldSwitch(pVCpu);
-            if (rcStrict == VINF_SUCCESS)
-                rcStrict = VINF_SVM_VMEXIT;
-            else if (RT_SUCCESS(rcStrict))
+            PCSVMHOSTSTATE pHostState = &pVCpu->cpum.GstCtx.hwvirt.svm.HostState;
+            bool const fHostInPaeMode = CPUMIsPaePagingEnabled(pHostState->uCr0, pHostState->uCr4, pHostState->uEferMsr);
+            if (fHostInPaeMode)
+                rcStrict = PGMGstMapPaePdpesAtCr3(pVCpu, pHostState->uCr3);
+            if (RT_LIKELY(rcStrict == VINF_SUCCESS))
             {
-                LogFlow(("iemSvmVmexit: Setting passup status from iemSvmWorldSwitch %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
-                iemSetPassUpStatus(pVCpu, rcStrict);
-                rcStrict = VINF_SVM_VMEXIT;
+                /*
+                 * Reload the host state.
+                 */
+                CPUMSvmVmExitRestoreHostState(pVCpu, IEM_GET_CTX(pVCpu));
+
+                /*
+                 * Update PGM, IEM and others of a world-switch.
+                 */
+                rcStrict = iemSvmWorldSwitch(pVCpu, fHostInPaeMode);
+                if (rcStrict == VINF_SUCCESS)
+                    rcStrict = VINF_SVM_VMEXIT;
+                else if (RT_SUCCESS(rcStrict))
+                {
+                    LogFlow(("iemSvmVmexit: Setting passup status from iemSvmWorldSwitch %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
+                    iemSetPassUpStatus(pVCpu, rcStrict);
+                    rcStrict = VINF_SVM_VMEXIT;
+                }
+                else
+                    LogFlow(("iemSvmVmexit: iemSvmWorldSwitch unexpected failure. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
             }
             else
-                LogFlow(("iemSvmVmexit: iemSvmWorldSwitch unexpected failure. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
+            {
+                Log(("iemSvmVmexit: PAE PDPEs invalid while restoring host state. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
+                rcStrict = VINF_EM_TRIPLE_FAULT;
+            }
         }
         else
         {
             AssertMsgFailed(("iemSvmVmexit: Mapping VMCB at %#RGp failed. rc=%Rrc\n", pVCpu->cpum.GstCtx.hwvirt.svm.GCPhysVmcb, VBOXSTRICTRC_VAL(rcStrict)));
-            rcStrict = VERR_SVM_VMEXIT_FAILED;
+            rcStrict = VINF_EM_TRIPLE_FAULT;
         }
     }
@@ -705,4 +722,24 @@
 
         /*
+         * Validate and map PAE PDPEs if the guest will be using PAE paging.
+         * Invalid PAE PDPEs here causes a #VMEXIT.
+         */
+        bool fPdpesMapped;
+        if (   !pVmcbCtrl->NestedPagingCtrl.n.u1NestedPaging
+            && CPUMIsPaePagingEnabled(pVmcbNstGst->u64CR0, pVmcbNstGst->u64CR4, uValidEfer))
+        {
+            rc = PGMGstMapPaePdpesAtCr3(pVCpu, pVmcbNstGst->u64CR3);
+            if (RT_SUCCESS(rc))
+                fPdpesMapped = true;
+            else
+            {
+                Log(("iemSvmVmrun: PAE PDPEs invalid -> #VMEXIT\n"));
+                return iemSvmVmexit(pVCpu, SVM_EXIT_INVALID, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+            }
+        }
+        else
+            fPdpesMapped = false;
+
+        /*
          * Copy the remaining guest state from the VMCB to the guest-CPU context.
          */
@@ -742,5 +779,5 @@
          * Update PGM, IEM and others of a world-switch.
          */
-        VBOXSTRICTRC rcStrict = iemSvmWorldSwitch(pVCpu);
+        VBOXSTRICTRC rcStrict = iemSvmWorldSwitch(pVCpu, fPdpesMapped);
         if (rcStrict == VINF_SUCCESS)
         { /* likely */ }
Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 91580)
@@ -1104,44 +1104,4 @@
 
 /**
- * Gets the instruction diagnostic for guest CR3 referenced PDPTE reserved bits
- * failure during VM-entry of a nested-guest.
- *
- * @param   iSegReg     The PDPTE entry index.
- */
-IEM_STATIC VMXVDIAG iemVmxGetDiagVmentryPdpteRsvd(unsigned iPdpte)
-{
-    Assert(iPdpte < X86_PG_PAE_PDPE_ENTRIES);
-    switch (iPdpte)
-    {
-        case 0: return kVmxVDiag_Vmentry_GuestPdpte0Rsvd;
-        case 1: return kVmxVDiag_Vmentry_GuestPdpte1Rsvd;
-        case 2: return kVmxVDiag_Vmentry_GuestPdpte2Rsvd;
-        case 3: return kVmxVDiag_Vmentry_GuestPdpte3Rsvd;
-        IEM_NOT_REACHED_DEFAULT_CASE_RET2(kVmxVDiag_Ipe_11);
-    }
-}
-
-
-/**
- * Gets the instruction diagnostic for host CR3 referenced PDPTE reserved bits
- * failure during VM-exit of a nested-guest.
- *
- * @param   iSegReg     The PDPTE entry index.
- */
-IEM_STATIC VMXVDIAG iemVmxGetDiagVmexitPdpteRsvd(unsigned iPdpte)
-{
-    Assert(iPdpte < X86_PG_PAE_PDPE_ENTRIES);
-    switch (iPdpte)
-    {
-        case 0: return kVmxVDiag_Vmexit_HostPdpte0Rsvd;
-        case 1: return kVmxVDiag_Vmexit_HostPdpte1Rsvd;
-        case 2: return kVmxVDiag_Vmexit_HostPdpte2Rsvd;
-        case 3: return kVmxVDiag_Vmexit_HostPdpte3Rsvd;
-        IEM_NOT_REACHED_DEFAULT_CASE_RET2(kVmxVDiag_Ipe_12);
-    }
-}
-
-
-/**
  * Saves the guest control registers, debug registers and some MSRs are part of
  * VM-exit.
@@ -1254,9 +1214,10 @@
 
 /**
- * Perform a VMX transition updated PGM, IEM and CPUM.
- *
- * @param   pVCpu   The cross context virtual CPU structure.
- */
-IEM_STATIC int iemVmxWorldSwitch(PVMCPUCC pVCpu)
+ * Performs the VMX transition to/from VMX non-root mode.
+ *
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   fPdpesMapped    Whether the PAE PDPTEs (and PDPT) have been mapped.
+*/
+IEM_STATIC int iemVmxTransition(PVMCPUCC pVCpu, bool fPdpesMapped)
 {
     /*
@@ -1280,5 +1241,5 @@
     if (rc == VINF_SUCCESS)
     {
-        rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true);
+        rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /* fGlobal */, fPdpesMapped);
         AssertRCReturn(rc, rc);
     }
@@ -1903,44 +1864,20 @@
 
 /**
- * Checks host PDPTes as part of VM-exit.
+ * Checks the host PAE PDPTEs assuming we are switching to a PAE mode host.
  *
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   uExitReason     The VM-exit reason (for logging purposes).
+ * @param   uExitReason     The VMX instruction name (for logging purposes).
+ *
+ * @remarks Caller must ensure the preconditions are met before calling this
+ *          function as failure here will trigger VMX aborts!
  */
 IEM_STATIC int iemVmxVmexitCheckHostPdptes(PVMCPUCC pVCpu, uint32_t uExitReason)
 {
-    /*
-     * Check host PDPTEs.
-     * See Intel spec. 27.5.4 "Checking and Loading Host Page-Directory-Pointer-Table Entries".
-     */
-    PCVMXVVMCS const    pVmcs           = &pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs;
-    const char * const  pszFailure      = "VMX-abort";
-    bool const          fHostInLongMode = RT_BOOL(pVmcs->u32ExitCtls & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE);
-
-    if (   (pVCpu->cpum.GstCtx.cr4 & X86_CR4_PAE)
-        && !fHostInLongMode)
-    {
-        uint64_t const uHostCr3 = pVCpu->cpum.GstCtx.cr3 & X86_CR3_PAE_PAGE_MASK;
-        X86PDPE aPdptes[X86_PG_PAE_PDPE_ENTRIES];
-        int rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), (void *)&aPdptes[0], uHostCr3, sizeof(aPdptes));
-        if (RT_SUCCESS(rc))
-        {
-            uint8_t idxInvalid;
-            bool const fValid = CPUMArePaePdpesValid(&aPdptes[0], &idxInvalid);
-            if (fValid)
-            { /* likely */ }
-            else
-            {
-                VMXVDIAG const enmDiag = iemVmxGetDiagVmexitPdpteRsvd(idxInvalid);
-                IEM_VMX_VMEXIT_FAILED_RET(pVCpu, uExitReason, pszFailure, enmDiag);
-            }
-        }
-        else
-            IEM_VMX_VMEXIT_FAILED_RET(pVCpu, uExitReason, pszFailure, kVmxVDiag_Vmexit_HostPdpteCr3ReadPhys);
-    }
-
-    NOREF(pszFailure);
-    NOREF(uExitReason);
-    return VINF_SUCCESS;
+    PCVMXVVMCS const   pVmcs      = &pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs;
+    const char * const pszFailure = "VMX-abort";
+    int const rc = PGMGstMapPaePdpesAtCr3(pVCpu, pVmcs->u64HostCr3.u);
+    if (RT_SUCCESS(rc))
+        return rc;
+    IEM_VMX_VMEXIT_FAILED_RET(pVCpu, uExitReason, pszFailure, kVmxVDiag_Vmexit_HostPdpte);
 }
 
@@ -1950,6 +1887,6 @@
  *
  * @returns VBox status code.
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   pszInstr    The VMX instruction name (for logging purposes).
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   uExitReason     The VMX instruction name (for logging purposes).
  */
 IEM_STATIC int iemVmxVmexitLoadHostAutoMsrs(PVMCPUCC pVCpu, uint32_t uExitReason)
@@ -2054,4 +1991,25 @@
     }
 
+    /*
+     * Check host PAE PDPTEs prior to loading the host state.
+     * See Intel spec. 26.5.4 "Checking and Loading Host Page-Directory-Pointer-Table Entries".
+     */
+    bool fPdpesMapped;
+    if (   (pVmcs->u64HostCr4.u & X86_CR4_PAE)
+        && !fHostInLongMode
+        && (   !CPUMIsGuestInPAEModeEx(&pVCpu->cpum.GstCtx)
+            || pVmcs->u64HostCr3.u != pVCpu->cpum.GstCtx.cr3))
+    {
+        int const rc = iemVmxVmexitCheckHostPdptes(pVCpu, uExitReason);
+        if (RT_FAILURE(rc))
+        {
+            Log(("VM-exit attempting to load invalid PDPTEs -> VMX-Abort\n"));
+            return iemVmxAbort(pVCpu, VMXBOART_HOST_PDPTE);
+        }
+        fPdpesMapped = true;
+    }
+    else
+        fPdpesMapped = false;
+
     iemVmxVmexitLoadHostControlRegsMsrs(pVCpu);
     iemVmxVmexitLoadHostSegRegs(pVCpu);
@@ -2069,19 +2027,10 @@
 
     /* Perform the VMX transition (PGM updates). */
-    VBOXSTRICTRC rcStrict = iemVmxWorldSwitch(pVCpu);
+    VBOXSTRICTRC rcStrict = iemVmxTransition(pVCpu, fPdpesMapped);
     if (rcStrict == VINF_SUCCESS)
-    {
-        /* Check host PDPTEs (only when we've fully switched page tables_. */
-        /** @todo r=ramshankar: I don't know if PGM does this for us already or not... */
-        int rc = iemVmxVmexitCheckHostPdptes(pVCpu, uExitReason);
-        if (RT_FAILURE(rc))
-        {
-            Log(("VM-exit failed while restoring host PDPTEs -> VMX-Abort\n"));
-            return iemVmxAbort(pVCpu, VMXBOART_HOST_PDPTE);
-        }
-    }
+    { /* likely */ }
     else if (RT_SUCCESS(rcStrict))
     {
-        Log3(("VM-exit: iemVmxWorldSwitch returns %Rrc (uExitReason=%u) -> Setting passup status\n", VBOXSTRICTRC_VAL(rcStrict),
+        Log3(("VM-exit: iemVmxTransition returns %Rrc (uExitReason=%u) -> Setting passup status\n", VBOXSTRICTRC_VAL(rcStrict),
               uExitReason));
         rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
@@ -2089,5 +2038,5 @@
     else
     {
-        Log3(("VM-exit: iemVmxWorldSwitch failed! rc=%Rrc (uExitReason=%u)\n", VBOXSTRICTRC_VAL(rcStrict), uExitReason));
+        Log3(("VM-exit: iemVmxTransition failed! rc=%Rrc (uExitReason=%u)\n", VBOXSTRICTRC_VAL(rcStrict), uExitReason));
         return VBOXSTRICTRC_VAL(rcStrict);
     }
@@ -5643,8 +5592,10 @@
  * Checks guest PDPTEs as part of VM-entry.
  *
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   pszInstr    The VMX instruction name (for logging purposes).
- */
-IEM_STATIC int iemVmxVmentryCheckGuestPdptes(PVMCPUCC pVCpu, const char *pszInstr)
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   pfPdpesMapped   Where to store whether PAE PDPTEs (and PDPT) have been
+ *                          mapped as part of checking guest state.
+ * @param   pszInstr        The VMX instruction name (for logging purposes).
+ */
+IEM_STATIC int iemVmxVmentryCheckGuestPdptes(PVMCPUCC pVCpu, bool *pfPdpesMapped, const char *pszInstr)
 {
     /*
@@ -5654,4 +5605,5 @@
     PVMXVVMCS const pVmcs = &pVCpu->cpum.GstCtx.hwvirt.vmx.Vmcs;
     const char * const pszFailure = "VM-exit";
+    *pfPdpesMapped = false;
 
     if (   !(pVmcs->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST)
@@ -5659,36 +5611,35 @@
         &&  (pVmcs->u64GuestCr0.u & X86_CR0_PG))
     {
-        /* Get the PDPTEs. */
-        X86PDPE aPdptes[X86_PG_PAE_PDPE_ENTRIES];
 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
         if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_EPT)
         {
-            aPdptes[0].u = pVmcs->u64GuestPdpte0.u;
-            aPdptes[1].u = pVmcs->u64GuestPdpte1.u;
-            aPdptes[2].u = pVmcs->u64GuestPdpte2.u;
-            aPdptes[3].u = pVmcs->u64GuestPdpte3.u;
-        }
-        else
-#endif
-        {
-            uint64_t const uGuestCr3 = pVmcs->u64GuestCr3.u & X86_CR3_PAE_PAGE_MASK;
-            int const rc = PGMPhysSimpleReadGCPhys(pVCpu->CTX_SUFF(pVM), (void *)&aPdptes[0], uGuestCr3, sizeof(aPdptes));
-            if (RT_FAILURE(rc))
+            /* Get PDPTEs from the VMCS. */
+            X86PDPE aPaePdptes[X86_PG_PAE_PDPE_ENTRIES];
+            aPaePdptes[0].u = pVmcs->u64GuestPdpte0.u;
+            aPaePdptes[1].u = pVmcs->u64GuestPdpte1.u;
+            aPaePdptes[2].u = pVmcs->u64GuestPdpte2.u;
+            aPaePdptes[3].u = pVmcs->u64GuestPdpte3.u;
+
+            /* Check validity of the PDPTEs. */
+            bool const fValid = PGMGstArePaePdpesValid(pVCpu, &aPaePdptes[0]);
+            if (fValid)
+            { /* likely */ }
+            else
             {
                 iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_PDPTE);
-                IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_GuestPdpteCr3ReadPhys);
+                IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_GuestPdpte);
             }
         }
-
-        /* Check validity of the PDPTEs. */
-        uint8_t idxInvalid;
-        bool const fValid = CPUMArePaePdpesValid(&aPdptes[0], &idxInvalid);
-        if (fValid)
-        { /* likely */ }
-        else
-        {
-            VMXVDIAG const enmDiag = iemVmxGetDiagVmentryPdpteRsvd(idxInvalid);
-            iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_PDPTE);
-            IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, enmDiag);
+        else
+#endif
+        {
+            int const rc = PGMGstMapPaePdpesAtCr3(pVCpu, pVmcs->u64GuestCr3.u);
+            if (rc == VINF_SUCCESS)
+                *pfPdpesMapped = true;
+            else
+            {
+                iemVmxVmcsSetExitQual(pVCpu, VMX_ENTRY_FAIL_QUAL_PDPTE);
+                IEM_VMX_VMENTRY_FAILED_RET(pVCpu, pszInstr, pszFailure, kVmxVDiag_Vmentry_GuestPdpte);
+            }
         }
     }
@@ -5704,8 +5655,10 @@
  *
  * @returns VBox status code.
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   pszInstr    The VMX instruction name (for logging purposes).
- */
-IEM_STATIC int iemVmxVmentryCheckGuestState(PVMCPUCC pVCpu, const char *pszInstr)
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   pfPdpesMapped   Where to store whether PAE PDPTEs (and PDPT) have been
+ *                          mapped as part of checking guest state.
+ * @param   pszInstr        The VMX instruction name (for logging purposes).
+ */
+IEM_STATIC int iemVmxVmentryCheckGuestState(PVMCPUCC pVCpu, bool *pfPdpesMapped, const char *pszInstr)
 {
     int rc = iemVmxVmentryCheckGuestControlRegsMsrs(pVCpu, pszInstr);
@@ -5723,5 +5676,5 @@
                     rc = iemVmxVmentryCheckGuestNonRegState(pVCpu, pszInstr);
                     if (RT_SUCCESS(rc))
-                        return iemVmxVmentryCheckGuestPdptes(pVCpu, pszInstr);
+                        return iemVmxVmentryCheckGuestPdptes(pVCpu, pfPdpesMapped, pszInstr);
                 }
             }
@@ -7419,5 +7372,6 @@
             iemVmxVmentrySaveNmiBlockingFF(pVCpu);
 
-            rc = iemVmxVmentryCheckGuestState(pVCpu, pszInstr);
+            bool fPdpesMapped;
+            rc = iemVmxVmentryCheckGuestState(pVCpu, &fPdpesMapped, pszInstr);
             if (RT_SUCCESS(rc))
             {
@@ -7435,10 +7389,10 @@
 
                         /* Perform the VMX transition (PGM updates). */
-                        VBOXSTRICTRC rcStrict = iemVmxWorldSwitch(pVCpu);
+                        VBOXSTRICTRC rcStrict = iemVmxTransition(pVCpu, fPdpesMapped);
                         if (rcStrict == VINF_SUCCESS)
                         { /* likely */ }
                         else if (RT_SUCCESS(rcStrict))
                         {
-                            Log3(("%s: iemVmxWorldSwitch returns %Rrc -> Setting passup status\n", pszInstr,
+                            Log3(("%s: iemVmxTransition returns %Rrc -> Setting passup status\n", pszInstr,
                                   VBOXSTRICTRC_VAL(rcStrict)));
                             rcStrict = iemSetPassUpStatus(pVCpu, rcStrict);
@@ -7446,5 +7400,5 @@
                         else
                         {
-                            Log3(("%s: iemVmxWorldSwitch failed! rc=%Rrc\n", pszInstr, VBOXSTRICTRC_VAL(rcStrict)));
+                            Log3(("%s: iemVmxTransition failed! rc=%Rrc\n", pszInstr, VBOXSTRICTRC_VAL(rcStrict)));
                             return rcStrict;
                         }
@@ -8437,5 +8391,5 @@
                         /* Invalidate mappings for the linear address tagged with VPID. */
                         /** @todo PGM support for VPID? Currently just flush everything. */
-                        PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */);
+                        PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */, false /* fPdpesMapped */);
                         iemVmxVmSucceed(pVCpu);
                     }
@@ -8464,5 +8418,5 @@
                     /* Invalidate all mappings with VPID. */
                     /** @todo PGM support for VPID? Currently just flush everything. */
-                    PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */);
+                    PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */, false /* fPdpesMapped */);
                     iemVmxVmSucceed(pVCpu);
                 }
@@ -8481,5 +8435,5 @@
                 /* Invalidate all mappings with non-zero VPIDs. */
                 /** @todo PGM support for VPID? Currently just flush everything. */
-                PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */);
+                PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */, false /* fPdpesMapped */);
                 iemVmxVmSucceed(pVCpu);
                 break;
@@ -8492,5 +8446,5 @@
                     /* Invalidate all mappings with VPID except global translations. */
                     /** @todo PGM support for VPID? Currently just flush everything. */
-                    PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */);
+                    PGMFlushTLB(pVCpu, uCr3, true /* fGlobal */, false /* fPdpesMapped */);
                     iemVmxVmSucceed(pVCpu);
                 }
Index: trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/NEMAllNativeTemplate-win.cpp.h	(revision 91580)
@@ -492,5 +492,8 @@
             return rc;
         if (rc == VERR_NEM_FLUSH_TLB)
-            return PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /*fGlobal*/);
+        {
+            rc = PGMFlushTLB(pVCpu, pVCpu->cpum.GstCtx.cr3, true /*fGlobal*/, false /*fPdpesMapped*/);
+            return rc;
+        }
         AssertLogRelRCReturn(rc, rc);
         return rc;
@@ -1104,6 +1107,9 @@
     if (fUpdateCr3)
     {
-        int rc = PGMUpdateCR3(pVCpu, pVCpu->cpum.GstCtx.cr3);
-        AssertMsgReturn(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc), RT_FAILURE_NP(rc) ? rc : VERR_NEM_IPE_2);
+        int rc = PGMUpdateCR3(pVCpu, pVCpu->cpum.GstCtx.cr3, false /*fPdpesMapped*/);
+        if (rc == VINF_SUCCESS)
+        { /* likely */ }
+        else
+            AssertMsgFailedReturn(("rc=%Rrc\n", rc), RT_FAILURE_NP(rc) ? rc : VERR_NEM_IPE_2);
     }
 
Index: trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 91580)
@@ -2187,4 +2187,29 @@
 
 /**
+ * Checks whether the given PAE PDPEs are potentially valid for the guest.
+ *
+ * @returns @c true if the PDPE is valid, @c false otherwise.
+ * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
+ * @param   paPaePdpes  The PAE PDPEs to validate.
+ *
+ * @remarks This function -only- checks the reserved bits in the PDPE entries.
+ */
+VMM_INT_DECL(bool) PGMGstArePaePdpesValid(PVMCPUCC pVCpu, PCX86PDPE paPaePdpes)
+{
+    Assert(paPaePdpes);
+    for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)
+    {
+        X86PDPE const PaePdpe = paPaePdpes[i];
+        if (   !(PaePdpe.u & X86_PDPE_P)
+            || !(PaePdpe.u & pVCpu->pgm.s.fGstPaeMbzPdpeMask))
+        { /* likely */ }
+        else
+            return false;
+    }
+    return true;
+}
+
+
+/**
  * Performs the lazy mapping of the 32-bit guest PD.
  *
@@ -2380,5 +2405,5 @@
  * @param   pVCpu   The cross context virtual CPU structure.
  */
-static void pgmGstUpdatePaePdpes(PVMCPU pVCpu)
+static void pgmGstFlushPaePdpes(PVMCPU pVCpu)
 {
     for (unsigned i = 0; i < RT_ELEMENTS(pVCpu->pgm.s.aGCPhysGstPaePDs); i++)
@@ -2392,4 +2417,33 @@
 
 /**
+ * Gets the PGM CR3 value masked according to the current guest mode.
+ *
+ * @returns The masked PGM CR3 value.
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   uCr3    The raw guest CR3 value.
+ */
+DECLINLINE(RTGCPHYS) pgmGetGuestMaskedCr3(PVMCPUCC pVCpu, uint64_t uCr3)
+{
+    RTGCPHYS GCPhysCR3;
+    switch (pVCpu->pgm.s.enmGuestMode)
+    {
+        case PGMMODE_PAE:
+        case PGMMODE_PAE_NX:
+            GCPhysCR3 = (RTGCPHYS)(uCr3 & X86_CR3_PAE_PAGE_MASK);
+            break;
+        case PGMMODE_AMD64:
+        case PGMMODE_AMD64_NX:
+            GCPhysCR3 = (RTGCPHYS)(uCr3 & X86_CR3_AMD64_PAGE_MASK);
+            break;
+        default:
+            GCPhysCR3 = (RTGCPHYS)(uCr3 & X86_CR3_PAGE_MASK);
+            break;
+    }
+    PGM_A20_APPLY_TO_VAR(pVCpu, GCPhysCR3);
+    return GCPhysCR3;
+}
+
+
+/**
  * Performs and schedules necessary updates following a CR3 load or reload.
  *
@@ -2399,9 +2453,10 @@
  * @retval  VINF_PGM_SYNC_CR3 if monitoring requires a CR3 sync. This can
  *          safely be ignored and overridden since the FF will be set too then.
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   cr3         The new cr3.
- * @param   fGlobal     Indicates whether this is a global flush or not.
- */
-VMMDECL(int) PGMFlushTLB(PVMCPUCC pVCpu, uint64_t cr3, bool fGlobal)
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   cr3             The new cr3.
+ * @param   fGlobal         Indicates whether this is a global flush or not.
+ * @param   fPdpesMapped    Whether the PAE PDPEs (and PDPT) have been mapped.
+ */
+VMMDECL(int) PGMFlushTLB(PVMCPUCC pVCpu, uint64_t cr3, bool fGlobal, bool fPdpesMapped)
 {
     STAM_PROFILE_START(&pVCpu->pgm.s.Stats.CTX_MID_Z(Stat,FlushTLB), a);
@@ -2423,22 +2478,6 @@
      */
     int rc = VINF_SUCCESS;
-    RTGCPHYS GCPhysCR3;
-    switch (pVCpu->pgm.s.enmGuestMode)
-    {
-        case PGMMODE_PAE:
-        case PGMMODE_PAE_NX:
-            GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAE_PAGE_MASK);
-            break;
-        case PGMMODE_AMD64:
-        case PGMMODE_AMD64_NX:
-            GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_AMD64_PAGE_MASK);
-            break;
-        default:
-            GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAGE_MASK);
-            break;
-    }
-    PGM_A20_APPLY_TO_VAR(pVCpu, GCPhysCR3);
-
     RTGCPHYS const GCPhysOldCR3 = pVCpu->pgm.s.GCPhysCR3;
+    RTGCPHYS const GCPhysCR3    = pgmGetGuestMaskedCr3(pVCpu, cr3);
     if (GCPhysOldCR3 != GCPhysCR3)
     {
@@ -2448,5 +2487,5 @@
 
         pVCpu->pgm.s.GCPhysCR3 = GCPhysCR3;
-        rc = g_aPgmBothModeData[idxBth].pfnMapCR3(pVCpu, GCPhysCR3);
+        rc = g_aPgmBothModeData[idxBth].pfnMapCR3(pVCpu, GCPhysCR3, fPdpesMapped);
         if (RT_LIKELY(rc == VINF_SUCCESS))
         {
@@ -2494,8 +2533,8 @@
 
         /*
-         * Update PAE PDPTEs.
+         * Flush PAE PDPTEs.
          */
         if (PGMMODE_IS_PAE(pVCpu->pgm.s.enmGuestMode))
-            pgmGstUpdatePaePdpes(pVCpu);
+            pgmGstFlushPaePdpes(pVCpu);
     }
 
@@ -2520,8 +2559,9 @@
  *          paging modes).  This can safely be ignored and overridden since the
  *          FF will be set too then.
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   cr3         The new cr3.
- */
-VMMDECL(int) PGMUpdateCR3(PVMCPUCC pVCpu, uint64_t cr3)
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   cr3             The new CR3.
+ * @param   fPdpesMapped    Whether the PAE PDPEs (and PDPT) have been mapped.
+ */
+VMMDECL(int) PGMUpdateCR3(PVMCPUCC pVCpu, uint64_t cr3, bool fPdpesMapped)
 {
     VMCPU_ASSERT_EMT(pVCpu);
@@ -2537,21 +2577,5 @@
      */
     int rc = VINF_SUCCESS;
-    RTGCPHYS GCPhysCR3;
-    switch (pVCpu->pgm.s.enmGuestMode)
-    {
-        case PGMMODE_PAE:
-        case PGMMODE_PAE_NX:
-            GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAE_PAGE_MASK);
-            break;
-        case PGMMODE_AMD64:
-        case PGMMODE_AMD64_NX:
-            GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_AMD64_PAGE_MASK);
-            break;
-        default:
-            GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAGE_MASK);
-            break;
-    }
-    PGM_A20_APPLY_TO_VAR(pVCpu, GCPhysCR3);
-
+    RTGCPHYS const GCPhysCR3 = pgmGetGuestMaskedCr3(pVCpu, cr3);
     if (pVCpu->pgm.s.GCPhysCR3 != GCPhysCR3)
     {
@@ -2561,13 +2585,13 @@
 
         pVCpu->pgm.s.GCPhysCR3 = GCPhysCR3;
-        rc = g_aPgmBothModeData[idxBth].pfnMapCR3(pVCpu, GCPhysCR3);
+        rc = g_aPgmBothModeData[idxBth].pfnMapCR3(pVCpu, GCPhysCR3, fPdpesMapped);
 
         AssertRCSuccess(rc); /* Assumes VINF_PGM_SYNC_CR3 doesn't apply to nested paging. */ /** @todo this isn't true for the mac, but we need hw to test/fix this. */
     }
     /*
-     * Update PAE PDPTEs.
+     * Flush PAE PDPTEs.
      */
     else if (PGMMODE_IS_PAE(pVCpu->pgm.s.enmGuestMode))
-        pgmGstUpdatePaePdpes(pVCpu);
+        pgmGstFlushPaePdpes(pVCpu);
 
     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
@@ -2636,22 +2660,6 @@
         pVCpu->pgm.s.fSyncFlags &= ~PGM_SYNC_MAP_CR3;
 
-        RTGCPHYS GCPhysCR3Old = pVCpu->pgm.s.GCPhysCR3; NOREF(GCPhysCR3Old);
-        RTGCPHYS GCPhysCR3;
-        switch (pVCpu->pgm.s.enmGuestMode)
-        {
-            case PGMMODE_PAE:
-            case PGMMODE_PAE_NX:
-                GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAE_PAGE_MASK);
-                break;
-            case PGMMODE_AMD64:
-            case PGMMODE_AMD64_NX:
-                GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_AMD64_PAGE_MASK);
-                break;
-            default:
-                GCPhysCR3 = (RTGCPHYS)(cr3 & X86_CR3_PAGE_MASK);
-                break;
-        }
-        PGM_A20_APPLY_TO_VAR(pVCpu, GCPhysCR3);
-
+        RTGCPHYS const GCPhysCR3Old = pVCpu->pgm.s.GCPhysCR3; NOREF(GCPhysCR3Old);
+        RTGCPHYS const GCPhysCR3    = pgmGetGuestMaskedCr3(pVCpu, cr3);
         if (pVCpu->pgm.s.GCPhysCR3 != GCPhysCR3)
         {
@@ -2660,5 +2668,5 @@
             AssertReturn(g_aPgmBothModeData[idxBth].pfnMapCR3, VERR_PGM_MODE_IPE);
             pVCpu->pgm.s.GCPhysCR3 = GCPhysCR3;
-            rc = g_aPgmBothModeData[idxBth].pfnMapCR3(pVCpu, GCPhysCR3);
+            rc = g_aPgmBothModeData[idxBth].pfnMapCR3(pVCpu, GCPhysCR3, false /* fPdpesMapped */);
         }
 
@@ -2724,4 +2732,130 @@
         PGM_INVL_VCPU_TLBS(pVCpu);
     return rc;
+}
+
+
+/**
+ * Maps all the PAE PDPE entries.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       The cross context virtual CPU structure of the calling EMT.
+ * @param   paPaePdpes  The new PAE PDPE values.
+ *
+ * @remarks This function may be invoked during the process of changing the guest
+ *          paging mode to PAE, hence the guest state (CR0, CR4 etc.) may not
+ *          reflect PAE paging just yet.
+ */
+VMM_INT_DECL(int) PGMGstMapPaePdpes(PVMCPUCC pVCpu, PCX86PDPE paPaePdpes)
+{
+    Assert(paPaePdpes);
+    for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)
+    {
+        X86PDPE const PaePdpe = paPaePdpes[i];
+
+        /*
+         * In some cases (e.g. in SVM with nested paging) the validation of the PAE PDPEs
+         * are deferred.[1] Also, different situations require different handling of invalid
+         * PDPE entries. Here we assume the caller has already validated or doesn't require
+         * validation of the PDPEs.
+         *
+         * [1] -- See AMD spec. 15.25.10 "Legacy PAE Mode".
+         */
+        if ((PaePdpe.u & (pVCpu->pgm.s.fGstPaeMbzPdpeMask | X86_PDPE_P)) == X86_PDPE_P)
+        {
+            PVMCC   pVM = pVCpu->CTX_SUFF(pVM);
+            RTHCPTR HCPtr;
+            RTGCPHYS const GCPhys = PGM_A20_APPLY(pVCpu, PaePdpe.u & X86_PDPE_PG_MASK);
+
+            PGM_LOCK_VOID(pVM);
+            PPGMPAGE    pPage  = pgmPhysGetPage(pVM, GCPhys);
+            AssertReturnStmt(pPage, PGM_UNLOCK(pVM), VERR_PGM_INVALID_PDPE_ADDR);
+            int const rc = pgmPhysGCPhys2CCPtrInternalDepr(pVM, pPage, GCPhys, (void **)&HCPtr);
+            PGM_UNLOCK(pVM);
+            if (RT_SUCCESS(rc))
+            {
+#  ifdef IN_RING3
+                pVCpu->pgm.s.apGstPaePDsR3[i]    = (PX86PDPAE)HCPtr;
+                pVCpu->pgm.s.apGstPaePDsR0[i]    = NIL_RTR0PTR;
+#  else
+                pVCpu->pgm.s.apGstPaePDsR3[i]    = NIL_RTR3PTR;
+                pVCpu->pgm.s.apGstPaePDsR0[i]    = (PX86PDPAE)HCPtr;
+#  endif
+                pVCpu->pgm.s.aGCPhysGstPaePDs[i] = GCPhys;
+                continue;
+            }
+            AssertMsgFailed(("PGMPhysMapPaePdpes: rc2=%d GCPhys=%RGp i=%d\n", rc, GCPhys, i));
+        }
+        pVCpu->pgm.s.apGstPaePDsR3[i]    = 0;
+        pVCpu->pgm.s.apGstPaePDsR0[i]    = 0;
+        pVCpu->pgm.s.aGCPhysGstPaePDs[i] = NIL_RTGCPHYS;
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Validates and maps the PDPT and PAE PDPEs referenced by the given CR3.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu   The cross context virtual CPU structure of the calling EMT.
+ * @param   cr3     The guest CR3 value.
+ *
+ * @remarks This function may be invoked during the process of changing the guest
+ *          paging mode to PAE but the guest state (CR0, CR4 etc.) may not reflect
+ *          PAE paging just yet.
+ */
+VMM_INT_DECL(int) PGMGstMapPaePdpesAtCr3(PVMCPUCC pVCpu, uint64_t cr3)
+{
+    /*
+     * Read the page-directory-pointer table (PDPT) at CR3.
+     */
+    PVMCC pVM = pVCpu->CTX_SUFF(pVM);
+    RTGCPHYS GCPhysCR3 = (cr3 & X86_CR3_PAE_PAGE_MASK);
+    PGM_A20_APPLY_TO_VAR(pVCpu, GCPhysCR3);
+
+    PGM_LOCK_VOID(pVM);
+    PPGMPAGE pPageCR3  = pgmPhysGetPage(pVM, GCPhysCR3);
+    AssertReturnStmt(pPageCR3, PGM_UNLOCK(pVM), VERR_PGM_INVALID_CR3_ADDR);
+
+    X86PDPE aPaePdpes[X86_PG_PAE_PDPE_ENTRIES];
+    RTHCPTR HCPtrGuestCr3;
+    int rc = pgmPhysGCPhys2CCPtrInternalDepr(pVM, pPageCR3, GCPhysCR3, (void **)&HCPtrGuestCr3);
+    PGM_UNLOCK(pVM);
+    AssertRCReturn(rc, rc);
+    memcpy(&aPaePdpes[0], HCPtrGuestCr3, sizeof(aPaePdpes));
+
+    /*
+     * Validate the page-directory-pointer table entries (PDPE).
+     */
+    if (PGMGstArePaePdpesValid(pVCpu, &aPaePdpes[0]))
+    {
+        /*
+         * Map the PDPT.
+         * We deliberately don't update PGM's GCPhysCR3 here as it's expected
+         * that PGMFlushTLB will be called soon and only a change to CR3 then
+         * will cause the shadow page tables to be updated.
+         */
+#  ifdef IN_RING3
+        pVCpu->pgm.s.pGstPaePdptR3 = (PX86PDPT)HCPtrGuestCr3;
+        pVCpu->pgm.s.pGstPaePdptR0 = NIL_RTR0PTR;
+#  else
+        pVCpu->pgm.s.pGstPaePdptR3 = NIL_RTR3PTR;
+        pVCpu->pgm.s.pGstPaePdptR0 = (PX86PDPT)HCPtrGuestCr3;
+#  endif
+
+        /*
+         * Update CPUM.
+         * We do this prior to mapping the PDPEs to keep the order consistent
+         * with what's used in HM. In practice, it doesn't really matter.
+         */
+        CPUMSetGuestPaePdpes(pVCpu, &aPaePdpes[0]);
+
+        /*
+         * Map the PDPEs.
+         */
+        return PGMGstMapPaePdpes(pVCpu, &aPaePdpes[0]);
+    }
+    return VERR_PGM_PAE_PDPE_RSVD;
 }
 
Index: trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 91580)
@@ -53,5 +53,5 @@
 PGM_BTH_DECL(unsigned, AssertCR3)(PVMCPUCC pVCpu, uint64_t cr3, uint64_t cr4, RTGCPTR GCPtr = 0, RTGCPTR cb = ~(RTGCPTR)0);
 #endif
-PGM_BTH_DECL(int, MapCR3)(PVMCPUCC pVCpu, RTGCPHYS GCPhysCR3);
+PGM_BTH_DECL(int, MapCR3)(PVMCPUCC pVCpu, RTGCPHYS GCPhysCR3, bool fPdpesMapped);
 PGM_BTH_DECL(int, UnmapCR3)(PVMCPUCC pVCpu);
 
@@ -4295,10 +4295,12 @@
  *
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   GCPhysCR3       The physical address in the CR3 register.  (A20
- *                          mask already applied.)
+ * @param   GCPhysCR3       The physical address in the CR3 register. (A20 mask
+ *                          already applied.)
+ * @param   fPdpesMapped    Whether the PAE PDPEs (and PDPT) have been mapped.
  */
-PGM_BTH_DECL(int, MapCR3)(PVMCPUCC pVCpu, RTGCPHYS GCPhysCR3)
+PGM_BTH_DECL(int, MapCR3)(PVMCPUCC pVCpu, RTGCPHYS GCPhysCR3, bool fPdpesMapped)
 {
     PVMCC pVM = pVCpu->CTX_SUFF(pVM); NOREF(pVM);
+    int rc = VINF_SUCCESS;
 
     /* Update guest paging info. */
@@ -4310,87 +4312,63 @@
     PGM_A20_ASSERT_MASKED(pVCpu, GCPhysCR3);
 
-    /*
-     * Map the page CR3 points at.
-     */
-    RTHCPTR     HCPtrGuestCR3;
-    PGM_LOCK_VOID(pVM);
-    PPGMPAGE    pPageCR3 = pgmPhysGetPage(pVM, GCPhysCR3);
-    AssertReturn(pPageCR3, VERR_PGM_INVALID_CR3_ADDR);
-    /** @todo this needs some reworking wrt. locking?  */
-    int rc = pgmPhysGCPhys2CCPtrInternalDepr(pVM, pPageCR3, GCPhysCR3 & GST_CR3_PAGE_MASK, (void **)&HCPtrGuestCR3); /** @todo r=bird: This GCPhysCR3 masking isn't necessary. */
-    PGM_UNLOCK(pVM);
-    if (RT_SUCCESS(rc))
-    {
+# if PGM_GST_TYPE == PGM_TYPE_PAE
+    if (!fPdpesMapped)
+# else
+    NOREF(fPdpesMapped);
+#endif
+    {
+        /*
+         * Map the page CR3 points at.
+         */
+        RTHCPTR     HCPtrGuestCR3;
+        PGM_LOCK_VOID(pVM);
+        PPGMPAGE    pPageCR3 = pgmPhysGetPage(pVM, GCPhysCR3);
+        AssertReturnStmt(pPageCR3, PGM_UNLOCK(pVM), VERR_PGM_INVALID_CR3_ADDR);
+        /** @todo this needs some reworking wrt. locking?  */
+        rc = pgmPhysGCPhys2CCPtrInternalDepr(pVM, pPageCR3, GCPhysCR3 & GST_CR3_PAGE_MASK, (void **)&HCPtrGuestCR3); /** @todo r=bird: This GCPhysCR3 masking isn't necessary. */
+        PGM_UNLOCK(pVM);
+        if (RT_SUCCESS(rc))
+        {
 # if PGM_GST_TYPE == PGM_TYPE_32BIT
 #  ifdef IN_RING3
-        pVCpu->pgm.s.pGst32BitPdR3 = (PX86PD)HCPtrGuestCR3;
-        pVCpu->pgm.s.pGst32BitPdR0 = NIL_RTR0PTR;
+            pVCpu->pgm.s.pGst32BitPdR3 = (PX86PD)HCPtrGuestCR3;
+            pVCpu->pgm.s.pGst32BitPdR0 = NIL_RTR0PTR;
 #  else
-        pVCpu->pgm.s.pGst32BitPdR3 = NIL_RTR3PTR;
-        pVCpu->pgm.s.pGst32BitPdR0 = (PX86PD)HCPtrGuestCR3;
+            pVCpu->pgm.s.pGst32BitPdR3 = NIL_RTR3PTR;
+            pVCpu->pgm.s.pGst32BitPdR0 = (PX86PD)HCPtrGuestCR3;
 #  endif
 
 # elif PGM_GST_TYPE == PGM_TYPE_PAE
 #  ifdef IN_RING3
-        pVCpu->pgm.s.pGstPaePdptR3 = (PX86PDPT)HCPtrGuestCR3;
-        pVCpu->pgm.s.pGstPaePdptR0 = NIL_RTR0PTR;
+            pVCpu->pgm.s.pGstPaePdptR3 = (PX86PDPT)HCPtrGuestCR3;
+            pVCpu->pgm.s.pGstPaePdptR0 = NIL_RTR0PTR;
 #  else
-        pVCpu->pgm.s.pGstPaePdptR3 = NIL_RTR3PTR;
-        pVCpu->pgm.s.pGstPaePdptR0 = (PX86PDPT)HCPtrGuestCR3;
-#  endif
-
-        /*
-         * Map the 4 PDs too.
-         */
-        X86PDPE aGstPaePdpes[X86_PG_PAE_PDPE_ENTRIES];
-        memcpy(&aGstPaePdpes, HCPtrGuestCR3, sizeof(aGstPaePdpes));
-        CPUMSetGuestPaePdpes(pVCpu, &aGstPaePdpes[0]);
-        for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)
-        {
-            X86PDPE PaePdpe = aGstPaePdpes[i];
-            if (PaePdpe.u & X86_PDPE_P)
-            {
-                RTHCPTR     HCPtr;
-                RTGCPHYS    GCPhys = PGM_A20_APPLY(pVCpu, PaePdpe.u & X86_PDPE_PG_MASK);
-                PGM_LOCK_VOID(pVM);
-                PPGMPAGE    pPage  = pgmPhysGetPage(pVM, GCPhys);
-                AssertReturn(pPage, VERR_PGM_INVALID_PDPE_ADDR);
-                int rc2 = pgmPhysGCPhys2CCPtrInternalDepr(pVM, pPage, GCPhys, (void **)&HCPtr);
-                PGM_UNLOCK(pVM);
-                if (RT_SUCCESS(rc2))
-                {
-#  ifdef IN_RING3
-                    pVCpu->pgm.s.apGstPaePDsR3[i]     = (PX86PDPAE)HCPtr;
-                    pVCpu->pgm.s.apGstPaePDsR0[i]     = NIL_RTR0PTR;
-#  else
-                    pVCpu->pgm.s.apGstPaePDsR3[i]     = NIL_RTR3PTR;
-                    pVCpu->pgm.s.apGstPaePDsR0[i]     = (PX86PDPAE)HCPtr;
-#  endif
-                    pVCpu->pgm.s.aGCPhysGstPaePDs[i]  = GCPhys;
-                    continue;
-                }
-                AssertMsgFailed(("pgmR3Gst32BitMapCR3: rc2=%d GCPhys=%RGp i=%d\n", rc2, GCPhys, i));
-            }
-
-            pVCpu->pgm.s.apGstPaePDsR3[i]     = 0;
-            pVCpu->pgm.s.apGstPaePDsR0[i]     = 0;
-            pVCpu->pgm.s.aGCPhysGstPaePDs[i]  = NIL_RTGCPHYS;
-        }
+            pVCpu->pgm.s.pGstPaePdptR3 = NIL_RTR3PTR;
+            pVCpu->pgm.s.pGstPaePdptR0 = (PX86PDPT)HCPtrGuestCR3;
+#  endif
+
+            /*
+             * Update CPUM and map the 4 PDs too.
+             */
+            X86PDPE aGstPaePdpes[X86_PG_PAE_PDPE_ENTRIES];
+            memcpy(&aGstPaePdpes, HCPtrGuestCR3, sizeof(aGstPaePdpes));
+            CPUMSetGuestPaePdpes(pVCpu, &aGstPaePdpes[0]);
+            PGMGstMapPaePdpes(pVCpu, &aGstPaePdpes[0]);
 
 # elif PGM_GST_TYPE == PGM_TYPE_AMD64
 #  ifdef IN_RING3
-        pVCpu->pgm.s.pGstAmd64Pml4R3 = (PX86PML4)HCPtrGuestCR3;
-        pVCpu->pgm.s.pGstAmd64Pml4R0 = NIL_RTR0PTR;
+            pVCpu->pgm.s.pGstAmd64Pml4R3 = (PX86PML4)HCPtrGuestCR3;
+            pVCpu->pgm.s.pGstAmd64Pml4R0 = NIL_RTR0PTR;
 #  else
-        pVCpu->pgm.s.pGstAmd64Pml4R3 = NIL_RTR3PTR;
-        pVCpu->pgm.s.pGstAmd64Pml4R0 = (PX86PML4)HCPtrGuestCR3;
-#  endif
-# endif
-    }
-    else
-        AssertMsgFailed(("rc=%Rrc GCPhysGuestPD=%RGp\n", rc, GCPhysCR3));
-
+            pVCpu->pgm.s.pGstAmd64Pml4R3 = NIL_RTR3PTR;
+            pVCpu->pgm.s.pGstAmd64Pml4R0 = (PX86PML4)HCPtrGuestCR3;
+#  endif
+# endif
+        }
+        else
+            AssertMsgFailed(("rc=%Rrc GCPhysGuestPD=%RGp\n", rc, GCPhysCR3));
+    }
 #else /* prot/real stub */
-    int rc = VINF_SUCCESS;
+    NOREF(fPdpesMapped);
 #endif
 
@@ -4422,9 +4400,7 @@
 
     Assert(!(GCPhysCR3 >> (PAGE_SHIFT + 32)));
-    rc = pgmPoolAlloc(pVM, GCPhysCR3 & GST_CR3_PAGE_MASK, BTH_PGMPOOLKIND_ROOT, PGMPOOLACCESS_DONTCARE, PGM_A20_IS_ENABLED(pVCpu),
-                      NIL_PGMPOOL_IDX, UINT32_MAX, true /*fLockPage*/,
-                      &pNewShwPageCR3);
-    AssertFatalRC(rc);
-    rc = VINF_SUCCESS;
+    int const rc2 = pgmPoolAlloc(pVM, GCPhysCR3 & GST_CR3_PAGE_MASK, BTH_PGMPOOLKIND_ROOT, PGMPOOLACCESS_DONTCARE,
+                                 PGM_A20_IS_ENABLED(pVCpu), NIL_PGMPOOL_IDX, UINT32_MAX, true /*fLockPage*/, &pNewShwPageCR3);
+    AssertFatalRC(rc2);
 
     pVCpu->pgm.s.CTX_SUFF(pShwPageCR3) = pNewShwPageCR3;
@@ -4444,6 +4420,6 @@
     Assert(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL) || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
 #   endif
-    rc = pgmMapActivateCR3(pVM, pNewShwPageCR3);
-    AssertRCReturn(rc, rc);
+    int const rc3 = pgmMapActivateCR3(pVM, pNewShwPageCR3);
+    AssertRCReturn(rc3, rc3);
 #  endif
 
Index: trunk/src/VBox/VMM/VMMAll/PGMAllGst.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllGst.h	(revision 91579)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllGst.h	(revision 91580)
@@ -53,5 +53,5 @@
     AssertReturn(idxBth < RT_ELEMENTS(g_aPgmBothModeData), VERR_PGM_MODE_IPE);
     AssertReturn(g_aPgmBothModeData[idxBth].pfnMapCR3, VERR_PGM_MODE_IPE);
-    return g_aPgmBothModeData[idxBth].pfnMapCR3(pVCpu, GCPhysCR3);
+    return g_aPgmBothModeData[idxBth].pfnMapCR3(pVCpu, GCPhysCR3, false /* fPdpesMapped */);
 }
 
Index: trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 91580)
@@ -2924,5 +2924,5 @@
     {
         AssertMsg(pCtx->cr3 == pVmcbGuest->u64CR3, ("cr3=%#RX64 vmcb_cr3=%#RX64\n", pCtx->cr3, pVmcbGuest->u64CR3));
-        PGMUpdateCR3(pVCpu, pCtx->cr3);
+        PGMUpdateCR3(pVCpu, pCtx->cr3, false /* fPdpesMapped */);
     }
 }
@@ -3994,5 +3994,5 @@
     /* Could happen as a result of longjump. */
     if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
-        PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
+        PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu), false /* fPdpesMapped */);
 
     /* Update pending interrupts into the APIC's IRR. */
Index: trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 91580)
@@ -8053,7 +8053,7 @@
         {
             Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
-            PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
-        }
-        Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
+            PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu), false /* fPdpesMapped */);
+            Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
+        }
     }
 
@@ -10902,5 +10902,5 @@
     {
         Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
-        int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
+        int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu), false /* fPdpesMapped */);
         AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
                         ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
Index: trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMR0/NEMR0Native-win.cpp	(revision 91580)
@@ -2190,6 +2190,9 @@
         {
             LogFlow(("nemR0WinImportState: -> PGMUpdateCR3!\n"));
-            rc = PGMUpdateCR3(pGVCpu, pCtx->cr3);
-            AssertMsgReturn(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc), RT_FAILURE_NP(rc) ? rc : VERR_NEM_IPE_2);
+            rc = PGMUpdateCR3(pGVCpu, pCtx->cr3, false /*fPdpesMapped*/);
+            if (rc == VINF_SUCCESS)
+            { /* likely */ }
+            else
+                AssertMsgFailedReturn(("rc=%Rrc\n", rc), RT_FAILURE_NP(rc) ? rc : VERR_NEM_IPE_2);
         }
         else
Index: trunk/src/VBox/VMM/VMMR3/EM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 91580)
@@ -1452,5 +1452,5 @@
     {
         CPUM_IMPORT_EXTRN_RCSTRICT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_EFER, rc);
-        int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
+        int const rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu), false /* fPdpesMapped */);
         if (RT_FAILURE(rc2))
             return rc2;
Index: trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp	(revision 91580)
@@ -1712,5 +1712,5 @@
                 {
                     LogFlow(("nemR3NativeRunGC: calling PGMFlushTLB...\n"));
-                    int rc = PGMFlushTLB(pVCpu, CPUMGetGuestCR3(pVCpu), true);
+                    int rc = PGMFlushTLB(pVCpu, CPUMGetGuestCR3(pVCpu), true /*fGlobal*/, false /*fPdpesMapped*/);
                     AssertRCReturn(rc, rc);
                     if (rcStrict == VINF_NEM_FLUSH_TLB)
Index: trunk/src/VBox/VMM/VMMR3/PGM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/PGM.cpp	(revision 91579)
+++ trunk/src/VBox/VMM/VMMR3/PGM.cpp	(revision 91580)
@@ -2343,5 +2343,5 @@
     uintptr_t idxBth = pVCpu->pgm.s.idxBothModeData;
     if (   idxBth < RT_ELEMENTS(g_aPgmBothModeData)
-        && g_aPgmBothModeData[idxBth].pfnMapCR3)
+        && g_aPgmBothModeData[idxBth].pfnUnmapCR3)
     {
         rc = g_aPgmBothModeData[idxBth].pfnUnmapCR3(pVCpu);
Index: trunk/src/VBox/VMM/include/PGMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/PGMInternal.h	(revision 91579)
+++ trunk/src/VBox/VMM/include/PGMInternal.h	(revision 91580)
@@ -2798,5 +2798,5 @@
     DECLCALLBACKMEMBER(int, pfnPrefetchPage,(PVMCPUCC pVCpu, RTGCPTR GCPtrPage));
     DECLCALLBACKMEMBER(int, pfnVerifyAccessSyncPage,(PVMCPUCC pVCpu, RTGCPTR GCPtrPage, unsigned fFlags, unsigned uError));
-    DECLCALLBACKMEMBER(int, pfnMapCR3,(PVMCPUCC pVCpu, RTGCPHYS GCPhysCR3));
+    DECLCALLBACKMEMBER(int, pfnMapCR3,(PVMCPUCC pVCpu, RTGCPHYS GCPhysCR3, bool fPdpesMapped));
     DECLCALLBACKMEMBER(int, pfnUnmapCR3,(PVMCPUCC pVCpu));
     DECLCALLBACKMEMBER(int, pfnEnter,(PVMCPUCC pVCpu, RTGCPHYS GCPhysCR3));
