Index: /trunk/src/VBox/VMM/PGM.cpp
===================================================================
--- /trunk/src/VBox/VMM/PGM.cpp	(revision 13932)
+++ /trunk/src/VBox/VMM/PGM.cpp	(revision 13933)
@@ -1142,10 +1142,16 @@
     pVM->pgm.s.fA20Enabled      = true;
     pVM->pgm.s.GCPhys4MBPSEMask = RT_BIT_64(32) - 1; /* default; checked later */
-    pVM->pgm.s.pGstPaePDPTHC    = NULL;
-    pVM->pgm.s.pGstPaePDPTGC    = 0;
-    for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.apGstPaePDsHC); i++)
-    {
-        pVM->pgm.s.apGstPaePDsHC[i]             = NULL;
-        pVM->pgm.s.apGstPaePDsGC[i]             = 0;
+    pVM->pgm.s.pGstPaePDPTR3    = NULL;
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+    pVM->pgm.s.pGstPaePDPTR0    = NIL_RTR0PTR;
+#endif
+    pVM->pgm.s.pGstPaePDPTRC    = NIL_RTRCPTR;
+    for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.apGstPaePDsR3); i++)
+    {
+        pVM->pgm.s.apGstPaePDsR3[i]             = NULL;
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+        pVM->pgm.s.apGstPaePDsR0[i]             = NIL_RTR0PTR;
+#endif
+        pVM->pgm.s.apGstPaePDsRC[i]             = NIL_RTRCPTR;
         pVM->pgm.s.aGCPhysGstPaePDs[i]          = NIL_RTGCPHYS;
         pVM->pgm.s.aGCPhysGstPaePDsMonitored[i] = NIL_RTGCPHYS;
@@ -1885,11 +1891,11 @@
     pVM->pgm.s.pGC32BitPD    += offDelta;
     pVM->pgm.s.pGuestPDRC    += offDelta;
-    AssertCompile(RT_ELEMENTS(pVM->pgm.s.apGCPaePDs) == RT_ELEMENTS(pVM->pgm.s.apGstPaePDsGC));
+    AssertCompile(RT_ELEMENTS(pVM->pgm.s.apGCPaePDs) == RT_ELEMENTS(pVM->pgm.s.apGstPaePDsRC));
     for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.apGCPaePDs); i++)
     {
         pVM->pgm.s.apGCPaePDs[i]    += offDelta;
-        pVM->pgm.s.apGstPaePDsGC[i] += offDelta;
-    }
-    pVM->pgm.s.pGstPaePDPTGC += offDelta;
+        pVM->pgm.s.apGstPaePDsRC[i] += offDelta;
+    }
+    pVM->pgm.s.pGstPaePDPTRC += offDelta;
     pVM->pgm.s.pGCPaePDPT    += offDelta;
 
Index: /trunk/src/VBox/VMM/PGMGst.h
===================================================================
--- /trunk/src/VBox/VMM/PGMGst.h	(revision 13932)
+++ /trunk/src/VBox/VMM/PGMGst.h	(revision 13933)
@@ -352,9 +352,9 @@
         for (unsigned i = 0; i < 4; i++)
         {
-            if (    pVM->pgm.s.pGstPaePDPTHC->a[i].n.u1Present
-                &&  (pVM->pgm.s.pGstPaePDPTHC->a[i].u & X86_PDPE_PG_MASK) != pVM->pgm.s.aGCPhysGstPaePDsMonitored[i])
+            if (    pVM->pgm.s.pGstPaePDPTR3->a[i].n.u1Present
+                &&  (pVM->pgm.s.pGstPaePDPTR3->a[i].u & X86_PDPE_PG_MASK) != pVM->pgm.s.aGCPhysGstPaePDsMonitored[i])
             {
                 Log(("pgmR3GstPAEWriteHandlerCR3: detected updated PDPE; [%d] = %#llx, Old GCPhys=%RGp\n",
-                     i, pVM->pgm.s.pGstPaePDPTHC->a[i].u, pVM->pgm.s.aGCPhysGstPaePDsMonitored[i]));
+                     i, pVM->pgm.s.pGstPaePDPTR3->a[i].u, pVM->pgm.s.aGCPhysGstPaePDsMonitored[i]));
                 /*
                  * The PD has changed.
Index: /trunk/src/VBox/VMM/PGMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/PGMInternal.h	(revision 13932)
+++ /trunk/src/VBox/VMM/PGMInternal.h	(revision 13933)
@@ -2003,23 +2003,25 @@
      * @{ */
     /** The guest's page directory pointer table, static GC mapping. */
-    RCPTRTYPE(PX86PDPT)             pGstPaePDPTGC;
-    /** The guest's page directory pointer table, HC pointer. */
-#if 0///@todo def VBOX_WITH_2X_4GB_ADDR_SPACE
-    R3PTRTYPE(PX86PDPT)             pGstPaePDPTHC;
-#else
-    R3R0PTRTYPE(PX86PDPT)           pGstPaePDPTHC;
-#endif
-    /** The guest's page directories, HC pointers.
+    RCPTRTYPE(PX86PDPT)             pGstPaePDPTRC;
+    /** The guest's page directory pointer table, R3 pointer. */
+    R3PTRTYPE(PX86PDPT)             pGstPaePDPTR3;
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+    /** The guest's page directory pointer table, R0 pointer. */
+    R0PTRTYPE(PX86PDPT)             pGstPaePDPTR0;
+#endif
+
+    /** The guest's page directories, R3 pointers.
      * These are individual pointers and don't have to be adjecent.
      * These don't have to be up-to-date - use pgmGstGetPaePD() to access them. */
-#if 0///@todo def VBOX_WITH_2X_4GB_ADDR_SPACE
-    R3PTRTYPE(PX86PDPAE)            apGstPaePDsHC[4];
-#else
-    R3R0PTRTYPE(PX86PDPAE)          apGstPaePDsHC[4];
+    R3PTRTYPE(PX86PDPAE)            apGstPaePDsR3[4];
+    /** The guest's page directories, R0 pointers.
+     * Same restrictions as apGstPaePDsR3. */
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+    R0PTRTYPE(PX86PDPAE)            apGstPaePDsR0[4];
 #endif
     /** The guest's page directories, static GC mapping.
-     * Unlike the HC array the first entry can be accessed as a 2048 entry PD.
+     * Unlike the R3/R0 array the first entry can be accessed as a 2048 entry PD.
      * These don't have to be up-to-date - use pgmGstGetPaePD() to access them. */
-    RCPTRTYPE(PX86PDPAE)            apGstPaePDsGC[4];
+    RCPTRTYPE(PX86PDPAE)            apGstPaePDsRC[4];
     /** The physical addresses of the guest page directories (PAE) pointed to by apGstPagePDsHC/GC. */
     RTGCPHYS                        aGCPhysGstPaePDs[4];
@@ -3347,5 +3349,25 @@
 
 /**
- * Gets the page directory for the specified address.
+ * Gets the guest page directory pointer table.
+ *
+ * @returns Pointer to the page directory in question.
+ * @returns NULL if the page directory is not present or on an invalid page.
+ * @param   pPGM        Pointer to the PGM instance data.
+ */
+DECLINLINE(PX86PDPT) pgmGstGetPaePDPTPtr(PPGM pPGM)
+{
+#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+    PX86PDPT pGuestPDPT = 0;
+    int rc = PGMDynMapGCPage(PGM2VM(pPGM), pPGM->GCPhysCR3, (void **)pGuestPDPT);
+    AssertRCReturn(rc, 0);
+    return pGuestPDPT;
+#else
+    return pPGM->CTX_SUFF(pGstPaePDPT);
+#endif
+}
+
+
+/**
+ * Gets the guest page directory pointer table entry for the specified address.
  *
  * @returns Pointer to the page directory in question.
@@ -3354,19 +3376,52 @@
  * @param   GCPtr       The address.
  */
+DECLINLINE(PX86PDPE) pgmGstGetPaePDPEPtr(PPGM pPGM, RTGCPTR GCPtr)
+{
+    AssertGCPtr32(GCPtr);
+
+#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+    PX86PDPT pGuestPDPT = 0;
+    int rc = PGMDynMapGCPage(PGM2VM(pPGM), pPGM->GCPhysCR3, (void **)pGuestPDPT);
+    AssertRCReturn(rc, 0);
+    return &pGuestPDPT->a[(GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE];
+#else
+    return &pPGM->CTX_SUFF(pGstPaePDPT)->a[(GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE];
+#endif
+}
+
+
+/**
+ * Gets the page directory for the specified address.
+ *
+ * @returns Pointer to the page directory in question.
+ * @returns NULL if the page directory is not present or on an invalid page.
+ * @param   pPGM        Pointer to the PGM instance data.
+ * @param   GCPtr       The address.
+ */
 DECLINLINE(PX86PDPAE) pgmGstGetPaePD(PPGM pPGM, RTGCUINTPTR GCPtr)
 {
-    const unsigned iPdPt = GCPtr >> X86_PDPT_SHIFT;
-    if (CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].n.u1Present)
+    AssertGCPtr32(GCPtr);
+
+#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+    PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
+    AssertReturn(pGuestPDPT, 0);
+#else
+    PX86PDPT pGuestPDPT = pPGM->CTX_SUFF(pGstPaePDPT);
+#endif
+    const unsigned iPdPt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
+    if (pGuestPDPT->a[iPdPt].n.u1Present)
     {
-        if ((CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
-            return CTXSUFF(pPGM->apGstPaePDs)[iPdPt];
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+        if ((pGuestPDPT->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
+            return pPGM->CTX_SUFF(apGstPaePDs)[iPdPt];
+#endif
 
         /* cache is out-of-sync. */
         PX86PDPAE pPD;
-        int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
+        int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), pGuestPDPT->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
         if (RT_SUCCESS(rc))
             return pPD;
-        AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u));
-        /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page of some kind emulated as all 0s. */
+        AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, pGuestPDPT->a[iPdPt].u));
+        /* returning NULL is ok if we assume it's just an invalid page of some kind emulated as all 0s. (not quite true) */
     }
     return NULL;
@@ -3384,18 +3439,28 @@
 DECLINLINE(PX86PDEPAE) pgmGstGetPaePDEPtr(PPGM pPGM, RTGCUINTPTR GCPtr)
 {
-    const unsigned iPdPt = GCPtr >> X86_PDPT_SHIFT;
-    if (CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].n.u1Present)
+    AssertGCPtr32(GCPtr);
+
+#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+    PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
+    AssertReturn(pGuestPDPT, 0);
+#else
+    PX86PDPT pGuestPDPT = pPGM->CTX_SUFF(pGstPaePDPT);
+#endif
+    const unsigned iPdPt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
+    if (pGuestPDPT->a[iPdPt].n.u1Present)
     {
         const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
-        if ((CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
-            return &CTXSUFF(pPGM->apGstPaePDs)[iPdPt]->a[iPD];
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+        if ((pGuestPDPT->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
+            return &pPGM->CTX_SUFF(apGstPaePDs)[iPdPt]->a[iPD];
+#endif
 
         /* The cache is out-of-sync. */
         PX86PDPAE pPD;
-        int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
+        int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), pGuestPDPT->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
         if (RT_SUCCESS(rc))
             return &pPD->a[iPD];
-        AssertMsgFailed(("Impossible! rc=%Rrc PDPE=%RX64\n", rc, CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u));
-        /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page or something which we'll emulate as all 0s. */
+        AssertMsgFailed(("Impossible! rc=%Rrc PDPE=%RX64\n", rc, pGuestPDPT->a[iPdPt].u));
+        /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page or something which we'll emulate as all 0s. (not quite true) */
     }
     return NULL;
@@ -3413,19 +3478,29 @@
 DECLINLINE(uint64_t) pgmGstGetPaePDE(PPGM pPGM, RTGCUINTPTR GCPtr)
 {
-    const unsigned iPdPt = GCPtr >> X86_PDPT_SHIFT;
-    if (CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].n.u1Present)
+    AssertGCPtr32(GCPtr);
+
+#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+    PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
+    AssertReturn(pGuestPDPT, 0);
+#else
+    PX86PDPT pGuestPDPT = pPGM->CTX_SUFF(pGstPaePDPT);
+#endif
+    const unsigned iPdPt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
+    if (pGuestPDPT->a[iPdPt].n.u1Present)
     {
         const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
-        if ((CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
-            return CTXSUFF(pPGM->apGstPaePDs)[iPdPt]->a[iPD].u;
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+        if ((pGuestPDPT->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
+            return pPGM->CTX_SUFF(apGstPaePDs)[iPdPt]->a[iPD].u;
+#endif
 
         /* cache is out-of-sync. */
         PX86PDPAE pPD;
-        int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
+        int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), pGuestPDPT->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
         if (RT_SUCCESS(rc))
             return pPD->a[iPD].u;
-        AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u));
+        AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, pGuestPDPT->a[iPdPt].u));
     }
-    return 0ULL;
+    return 0;
 }
 
@@ -3440,20 +3515,33 @@
  * @param   GCPtr       The address.
  * @param   piPD        Receives the index into the returned page directory
- */
-DECLINLINE(PX86PDPAE) pgmGstGetPaePDPtr(PPGM pPGM, RTGCUINTPTR GCPtr, unsigned *piPD)
-{
-    const unsigned iPdPt = GCPtr >> X86_PDPT_SHIFT;
-    if (CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].n.u1Present)
+ * @param   pPdpe       Receives the page directory pointer entry. Optional.
+ */
+DECLINLINE(PX86PDPAE) pgmGstGetPaePDPtr(PPGM pPGM, RTGCUINTPTR GCPtr, unsigned *piPD, PX86PDPE pPdpe)
+{
+    AssertGCPtr32(GCPtr);
+
+#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+    PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(pPGM);
+    AssertReturn(pGuestPDPT, 0);
+#else
+    PX86PDPT pGuestPDPT = pPGM->CTX_SUFF(pGstPaePDPT);
+#endif
+    const unsigned iPdPt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
+    if (pPdpe)
+        *pPdpe = pGuestPDPT->a[iPdPt];
+    if (pGuestPDPT->a[iPdPt].n.u1Present)
     {
         const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
-        if ((CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+        if ((pGuestPDPT->a[iPdPt].u & X86_PDPE_PG_MASK) == pPGM->aGCPhysGstPaePDs[iPdPt])
         {
             *piPD = iPD;
-            return CTXSUFF(pPGM->apGstPaePDs)[iPdPt];
+            return pPGM->CTX_SUFF(apGstPaePDs)[iPdPt];
         }
+#endif
 
         /* cache is out-of-sync. */
         PX86PDPAE pPD;
-        int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
+        int rc = PGM_GCPHYS_2_PTR(PGM2VM(pPGM), pGuestPDPT->a[iPdPt].u & X86_PDPE_PG_MASK, &pPD);
         if (RT_SUCCESS(rc))
         {
@@ -3461,5 +3549,5 @@
             return pPD;
         }
-        AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt].u));
+        AssertMsgFailed(("Impossible! rc=%d PDPE=%#llx\n", rc, pGuestPDPT->a[iPdPt].u));
         /* returning NIL_RTGCPHYS is ok if we assume it's just an invalid page of some kind emulated as all 0s. */
     }
@@ -3523,5 +3611,5 @@
         {
             AssertFailed();
-            return 0ULL;
+            return 0;
         }
 
@@ -3536,5 +3624,5 @@
             {
                 AssertFailed();
-                return 0ULL;
+                return 0;
             }
             const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
@@ -3542,5 +3630,5 @@
         }
     }
-    return 0ULL;
+    return 0;
 }
 
@@ -3566,5 +3654,5 @@
         {
             AssertFailed();
-            return 0ULL;
+            return 0;
         }
 
@@ -3578,5 +3666,5 @@
             {
                 AssertFailed();
-                return 0ULL;
+                return 0;
             }
             const unsigned iPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
@@ -3584,5 +3672,5 @@
         }
     }
-    return 0ULL;
+    return 0;
 }
 
@@ -3654,5 +3742,5 @@
         {
             AssertFailed();
-            return 0ULL;
+            return 0;
         }
 
@@ -3667,5 +3755,5 @@
             {
                 AssertFailed();
-                return 0ULL;
+                return 0;
             }
             *piPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
@@ -3673,5 +3761,5 @@
         }
     }
-    return 0ULL;
+    return 0;
 }
 
@@ -3701,5 +3789,5 @@
         {
             AssertFailed();
-            return 0ULL;
+            return 0;
         }
 
@@ -3714,5 +3802,5 @@
             {
                 AssertFailed();
-                return 0ULL;
+                return 0;
             }
             *piPD = (GCPtr >> X86_PD_PAE_SHIFT) & X86_PD_PAE_MASK;
@@ -3720,5 +3808,5 @@
         }
     }
-    return 0ULL;
+    return 0;
 }
 
Index: /trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 13932)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 13933)
@@ -826,5 +826,5 @@
         &&  !(pPdpe->u & X86_PDPE_PG_MASK))
     {
-        PX86PDPE pPdptGst = &CTXSUFF(pPGM->pGstPaePDPT)->a[iPdPt];
+        PX86PDPE pPdptGst = pgmGstGetPaePDPEPtr(pPGM, GCPtr);
 
         Assert(!(pPdpe->u & X86_PDPE_PG_MASK));
@@ -1230,5 +1230,5 @@
 {
     Assert(iPdpt <= 3);
-    return pVM->pgm.s.CTXSUFF(pGstPaePDPT)->a[iPdpt & 3];
+    return pgmGstGetPaePDPTPtr(&pVM->pgm.s)->a[iPdpt & 3];
 }
 
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 13932)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 13933)
@@ -109,5 +109,5 @@
 #    if PGM_GST_TYPE == PGM_TYPE_PAE
     unsigned        iPDSrc;
-    PGSTPD          pPDSrc = pgmGstGetPaePDPtr(&pVM->pgm.s, (RTGCUINTPTR)pvFault, &iPDSrc);
+    PGSTPD          pPDSrc = pgmGstGetPaePDPtr(&pVM->pgm.s, (RTGCUINTPTR)pvFault, &iPDSrc, NULL);
 
 #    elif PGM_GST_TYPE == PGM_TYPE_AMD64
@@ -959,6 +959,6 @@
     unsigned        iPDSrc;
 #  if PGM_GST_TYPE == PGM_TYPE_PAE
-    PX86PDPAE       pPDSrc      = pgmGstGetPaePDPtr(&pVM->pgm.s, GCPtrPage, &iPDSrc);
-    X86PDPE         PdpeSrc     = CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[iPdpte];
+    X86PDPE         PdpeSrc;
+    PX86PDPAE       pPDSrc      = pgmGstGetPaePDPtr(&pVM->pgm.s, GCPtrPage, &iPDSrc, &PdpeSrc);
 #  else /* AMD64 */
     PX86PML4E       pPml4eSrc;
@@ -1095,5 +1095,8 @@
 
 # if PGM_GST_TYPE == PGM_TYPE_PAE
-    /* Note: This shouldn't actually be necessary as we monitor the PDPT page for changes. */
+    /*
+     * Update the shadow PDPE and free all the shadow PD entries if the PDPE is marked not present.
+     * Note: This shouldn't actually be necessary as we monitor the PDPT page for changes.
+     */
     if (!pPDSrc)
     {
@@ -1103,16 +1106,17 @@
         PPGMPOOL   pPool   = pVM->pgm.s.CTX_SUFF(pPool);
 
-        Assert(!(CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[iPdpte].n.u1Present));
+        Assert(!PdpeSrc.n.u1Present);
         LogFlow(("InvalidatePage: guest PDPE %d not present; clear shw pdpe\n", iPdpte));
- 	    /* for each page directory entry */
- 	    for (unsigned iPD = 0; iPD < X86_PG_PAE_ENTRIES; iPD++)
+
+        /* for each page directory entry */
+ 	for (unsigned iPD = 0; iPD < X86_PG_PAE_ENTRIES; iPD++)
+ 	{
+ 	    if (   pPDEDst[iPD].n.u1Present
+ 	        && !(pPDEDst[iPD].u & PGM_PDFLAGS_MAPPING))
  	    {
- 	        if (   pPDEDst[iPD].n.u1Present
- 	            && !(pPDEDst[iPD].u & PGM_PDFLAGS_MAPPING))
- 	        {
-                    pgmPoolFreeByPage(pPool, pgmPoolGetPage(pPool, pPDEDst[iPD].u & SHW_PDE_PG_MASK), SHW_POOL_ROOT_IDX, iPdpte * X86_PG_PAE_ENTRIES + iPD);
-                    pPDEDst[iPD].u = 0;
- 	        }
-	    }
+                pgmPoolFreeByPage(pPool, pgmPoolGetPage(pPool, pPDEDst[iPD].u & SHW_PDE_PG_MASK), SHW_POOL_ROOT_IDX, iPdpte * X86_PG_PAE_ENTRIES + iPD);
+                pPDEDst[iPD].u = 0;
+ 	    }
+	}
         if (!(pPdptDst->a[iPdpte].u & PGM_PLXFLAGS_MAPPING))
  	        pPdptDst->a[iPdpte].n.u1Present = 0;
@@ -2020,7 +2024,7 @@
     Assert(pPdpeSrc);
 
-#  else /* PAE */
-    PX86PDPE pPdpeSrc = &pVM->pgm.s.CTXSUFF(pGstPaePDPT)->a[(GCPtrPage >> GST_PDPT_SHIFT) & GST_PDPT_MASK];
-#  endif
+#  else  /* PAE */
+    PX86PDPE pPdpeSrc = pgmGstGetPaePDPEPtr(&pVM->pgm.s, GCPtrPage);
+#  endif /* PAE */
 
     /*
@@ -2813,5 +2817,5 @@
 #  elif PGM_GST_TYPE == PGM_TYPE_PAE
     unsigned        iPDSrc;
-    PGSTPD          pPDSrc = pgmGstGetPaePDPtr(&pVM->pgm.s, GCPtrPage, &iPDSrc);
+    PGSTPD          pPDSrc = pgmGstGetPaePDPtr(&pVM->pgm.s, GCPtrPage, &iPDSrc, NULL);
     if (!pPDSrc)
         return VINF_SUCCESS; /* not present */
@@ -2932,5 +2936,5 @@
 #  elif PGM_GST_TYPE == PGM_TYPE_PAE
     unsigned        iPDSrc;
-    PGSTPD          pPDSrc = pgmGstGetPaePDPtr(&pVM->pgm.s, GCPtrPage, &iPDSrc);
+    PGSTPD          pPDSrc = pgmGstGetPaePDPtr(&pVM->pgm.s, GCPtrPage, &iPDSrc, NULL);
 
     if (pPDSrc)
@@ -3225,9 +3229,9 @@
             unsigned        iPDSrc;
 #   if PGM_GST_TYPE == PGM_TYPE_PAE
+            X86PDPE         PdpeSrc;
+            PGSTPD          pPDSrc    = pgmGstGetPaePDPtr(&pVM->pgm.s, iPdpte << X86_PDPT_SHIFT, &iPDSrc, &PdpeSrc);
             PX86PDPAE       pPDPAE    = pVM->pgm.s.CTXMID(ap,PaePDs)[0];
             PX86PDEPAE      pPDEDst   = &pPDPAE->a[iPdpte * X86_PG_PAE_ENTRIES];
-            PGSTPD          pPDSrc    = pgmGstGetPaePDPtr(&pVM->pgm.s, iPdpte << X86_PDPT_SHIFT, &iPDSrc);
             PX86PDPT        pPdptDst  = pVM->pgm.s.CTXMID(p,PaePDPT);   NOREF(pPdptDst);
-            X86PDPE         PdpeSrc   = CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[iPdpte];
 
             if (pPDSrc == NULL)
@@ -3655,5 +3659,5 @@
     rc = PGMShwGetPage(pVM, (RTGCPTR)pPGM->pGuestPDRC, NULL, &HCPhysShw);
 #  else
-    rc = PGMShwGetPage(pVM, (RTGCPTR)pPGM->pGstPaePDPTGC, NULL, &HCPhysShw);
+    rc = PGMShwGetPage(pVM, (RTGCPTR)pPGM->pGstPaePDPTRC, NULL, &HCPhysShw);
 #  endif
     AssertRCReturn(rc, 1);
@@ -3764,8 +3768,8 @@
             RTGCPHYS        GCPhysPdeSrc;
 #   if PGM_GST_TYPE == PGM_TYPE_PAE
+            X86PDPE         PdpeSrc;
+            PGSTPD          pPDSrc    = pgmGstGetPaePDPtr(&pVM->pgm.s, GCPtr, &iPDSrc, &PdpeSrc);
             PX86PDPAE       pPDDst    = pVM->pgm.s.CTXMID(ap,PaePDs)[0];
-            PGSTPD          pPDSrc    = pgmGstGetPaePDPtr(&pVM->pgm.s, GCPtr, &iPDSrc);
             PX86PDPT        pPdptDst  = pVM->pgm.s.CTXMID(p,PaePDPT);
-            X86PDPE         PdpeSrc   = CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[iPdpte];
 #   else
             PX86PML4E       pPml4eSrc;
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllGst.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllGst.h	(revision 13932)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllGst.h	(revision 13933)
@@ -459,20 +459,24 @@
 
 # elif PGM_GST_TYPE == PGM_TYPE_PAE
-            unsigned offset = GCPhysCR3 & GST_CR3_PAGE_MASK & PAGE_OFFSET_MASK;
-            pVM->pgm.s.pGstPaePDPTHC = (R3R0PTRTYPE(PX86PDPT)) HCPtrGuestCR3;
-            pVM->pgm.s.pGstPaePDPTGC = (RCPTRTYPE(PX86PDPT))   ((RCPTRTYPE(uint8_t *))pVM->pgm.s.GCPtrCR3Mapping + offset);
-            Log(("Cached mapping %RGv\n", pVM->pgm.s.pGstPaePDPTGC));
+            unsigned off = GCPhysCR3 & GST_CR3_PAGE_MASK & PAGE_OFFSET_MASK;
+            pVM->pgm.s.pGstPaePDPTR3 = (R3PTRTYPE(PX86PDPT))HCPtrGuestCR3;
+#  ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+            pVM->pgm.s.pGstPaePDPTR0 = (R0PTRTYPE(PX86PDPT))HCPtrGuestCR3;
+#  endif
+            pVM->pgm.s.pGstPaePDPTRC = (RCPTRTYPE(PX86PDPT))((RCPTRTYPE(uint8_t *))pVM->pgm.s.GCPtrCR3Mapping + off);
+            Log(("Cached mapping %RGv\n", pVM->pgm.s.pGstPaePDPTRC));
 
             /*
              * Map the 4 PDs too.
              */
+            PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(&pVM->pgm.s);
             RTGCUINTPTR GCPtr = (RTGCUINTPTR)pVM->pgm.s.GCPtrCR3Mapping + PAGE_SIZE;
             for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++, GCPtr += PAGE_SIZE)
             {
-                if (pVM->pgm.s.CTXSUFF(pGstPaePDPT)->a[i].n.u1Present)
+                if (pGuestPDPT->a[i].n.u1Present)
                 {
                     RTHCPTR     HCPtr;
                     RTHCPHYS    HCPhys;
-                    RTGCPHYS    GCPhys = pVM->pgm.s.CTXSUFF(pGstPaePDPT)->a[i].u & X86_PDPE_PG_MASK;
+                    RTGCPHYS    GCPhys = pGuestPDPT->a[i].u & X86_PDPE_PG_MASK;
                     int rc2 = pgmRamGCPhys2HCPtrAndHCPhysWithFlags(&pVM->pgm.s, GCPhys, &HCPtr, &HCPhys);
                     if (RT_SUCCESS(rc2))
@@ -480,8 +484,12 @@
                         rc = PGMMap(pVM, GCPtr, HCPhys & X86_PTE_PAE_PG_MASK, PAGE_SIZE, 0);
                         AssertRCReturn(rc, rc);
-                        pVM->pgm.s.apGstPaePDsHC[i]     = (R3R0PTRTYPE(PX86PDPAE))HCPtr;
-                        pVM->pgm.s.apGstPaePDsGC[i]     = (RCPTRTYPE(PX86PDPAE))GCPtr;
+
+                        pVM->pgm.s.apGstPaePDsR3[i]     = (R3PTRTYPE(PX86PDPAE))HCPtr;
+#  ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+                        pVM->pgm.s.apGstPaePDsR0[i]     = (R0PTRTYPE(PX86PDPAE))HCPtr;
+#  endif
+                        pVM->pgm.s.apGstPaePDsRC[i]     = (RCPTRTYPE(PX86PDPAE))GCPtr;
                         pVM->pgm.s.aGCPhysGstPaePDs[i]  = GCPhys;
-                        PGM_INVL_PG(GCPtr);
+                        PGM_INVL_PG(GCPtr); /** @todo This ends up calling HWACCMInvalidatePage, is that correct? */
                         continue;
                     }
@@ -489,8 +497,11 @@
                 }
 
-                pVM->pgm.s.apGstPaePDsHC[i]     = 0;
-                pVM->pgm.s.apGstPaePDsGC[i]     = 0;
+                pVM->pgm.s.apGstPaePDsR3[i]     = 0;
+#  ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+                pVM->pgm.s.apGstPaePDsR0[i]     = 0;
+#  endif
+                pVM->pgm.s.apGstPaePDsRC[i]     = 0;
                 pVM->pgm.s.aGCPhysGstPaePDs[i]  = NIL_RTGCPHYS;
-                PGM_INVL_PG(GCPtr);
+                PGM_INVL_PG(GCPtr); /** @todo this shouldn't be necessary? */
             }
 # elif PGM_GST_TYPE == PGM_TYPE_AMD64
@@ -560,10 +571,16 @@
 
 #elif PGM_GST_TYPE == PGM_TYPE_PAE
-    pVM->pgm.s.pGstPaePDPTHC = 0;
-    pVM->pgm.s.pGstPaePDPTGC = 0;
-    for (unsigned i=0; i < X86_PG_PAE_PDPE_ENTRIES; i++)
-    {
-        pVM->pgm.s.apGstPaePDsHC[i]    = 0;
-        pVM->pgm.s.apGstPaePDsGC[i]    = 0;
+    pVM->pgm.s.pGstPaePDPTR3 = 0;
+# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+    pVM->pgm.s.pGstPaePDPTR0 = 0;
+# endif
+    pVM->pgm.s.pGstPaePDPTRC = 0;
+    for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)
+    {
+        pVM->pgm.s.apGstPaePDsR3[i]    = 0;
+# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+        pVM->pgm.s.apGstPaePDsR0[i]    = 0;
+# endif
+        pVM->pgm.s.apGstPaePDsRC[i]    = 0;
         pVM->pgm.s.aGCPhysGstPaePDs[i] = NIL_RTGCPHYS;
     }
@@ -666,9 +683,10 @@
      * Do the 4 PDs.
      */
+    PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(&pVM->pgm.s);
     for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)
     {
-        if (CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[i].n.u1Present)
-        {
-            RTGCPHYS GCPhys = CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[i].u & X86_PDPE_PG_MASK;
+        if (pGuestPDPT->a[i].n.u1Present)
+        {
+            RTGCPHYS GCPhys = pGuestPDPT->a[i].u & X86_PDPE_PG_MASK;
             if (pVM->pgm.s.aGCPhysGstPaePDsMonitored[i] != GCPhys)
             {
@@ -1089,9 +1107,10 @@
          * We'll simply check all of them instead of figuring out which one/two to check.
          */
+        PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(&pVM->pgm.s);
         for (unsigned i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)
         {
-            if (    CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[i].n.u1Present
-                &&  (   CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[i].u & X86_PDPE_PG_MASK)
-                     != pVM->pgm.s.aGCPhysGstPaePDsMonitored[i])
+            if (    pGuestPDPT->a[i].n.u1Present
+                &&      (pGuestPDPT->a[i].u & X86_PDPE_PG_MASK)
+                    !=  pVM->pgm.s.aGCPhysGstPaePDsMonitored[i])
             {
                 /*
@@ -1107,5 +1126,5 @@
                 pVM->pgm.s.fSyncFlags |= PGM_SYNC_MONITOR_CR3;
                 Log(("pgmXXGstPaeWriteHandlerCR3: detected updated PDPE; [%d] = %#llx, Old GCPhys=%RGp\n",
-                     i, CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[i].u, pVM->pgm.s.aGCPhysGstPaePDsMonitored[i]));
+                     i, pGuestPDPT->a[i].u, pVM->pgm.s.aGCPhysGstPaePDsMonitored[i]));
             }
         }
@@ -1155,9 +1174,10 @@
          */
         RTGCUINTPTR i;
+        PX86PDPT pGuestPDPT = pgmGstGetPaePDPTPtr(&pVM->pgm.s);
         for (i = 0; i < X86_PG_PAE_PDPE_ENTRIES; i++)
-            if (CTXSUFF(pVM->pgm.s.pGstPaePDPT)->a[i].u == (GCPhysFault & X86_PTE_PAE_PG_MASK))
+            if (pGuestPDPT->a[i].u == (GCPhysFault & X86_PTE_PAE_PG_MASK))
             {
                 PX86PDPAE           pPDSrc = pgmGstGetPaePD(&pVM->pgm.s, i << X86_PDPT_SHIFT);
-                const RTGCUINTPTR offPD  = GCPhysFault & PAGE_OFFSET_MASK;
+                const RTGCUINTPTR   offPD  = GCPhysFault & PAGE_OFFSET_MASK;
                 const unsigned      iPD1   = offPD / sizeof(X86PDEPAE);
                 const unsigned      iPD2   = (offPD + cb - 1) / sizeof(X86PDEPAE);
@@ -1167,5 +1187,5 @@
                 Assert(iPD2 < X86_PG_PAE_ENTRIES);
 
-#ifdef DEBUG
+# ifdef LOG_ENABLED
                 Log(("pgmXXGstPaeWriteHandlerPD: emulated change to i=%d iPD1=%#05x (%x)\n",
                      i, iPD1, (i << X86_PDPT_SHIFT) | (iPD1 << X86_PD_PAE_SHIFT)));
@@ -1173,5 +1193,5 @@
                     Log(("pgmXXGstPaeWriteHandlerPD: emulated change to i=%d iPD2=%#05x (%x)\n",
                          i, iPD2, (i << X86_PDPT_SHIFT) | (iPD2 << X86_PD_PAE_SHIFT)));
-#endif
+# endif
 
                 if (!pVM->pgm.s.fMappingsFixed)
Index: /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp	(revision 13932)
+++ /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp	(revision 13933)
@@ -401,8 +401,14 @@
 #endif
     GEN_CHECK_OFF(PGM, pGuestPDRC);
-    GEN_CHECK_OFF(PGM, pGstPaePDPTHC);
-    GEN_CHECK_OFF(PGM, pGstPaePDPTGC);
-    GEN_CHECK_OFF(PGM, apGstPaePDsHC);
-    GEN_CHECK_OFF(PGM, apGstPaePDsGC);
+    GEN_CHECK_OFF(PGM, pGstPaePDPTR3);
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+    GEN_CHECK_OFF(PGM, pGstPaePDPTR0);
+#endif
+    GEN_CHECK_OFF(PGM, pGstPaePDPTRC);
+    GEN_CHECK_OFF(PGM, apGstPaePDsR3);
+#ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+    GEN_CHECK_OFF(PGM, apGstPaePDsR0);
+#endif
+    GEN_CHECK_OFF(PGM, apGstPaePDsRC);
     GEN_CHECK_OFF(PGM, aGCPhysGstPaePDs);
     GEN_CHECK_OFF(PGM, aGCPhysGstPaePDsMonitored);
