Index: trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 16317)
+++ trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 16321)
@@ -211,5 +211,5 @@
 # include "PGMAllShw.h"
 
-/* Guest - protected mode */
+/* Guest - protected mode (only used for AMD-V nested paging in 64 bits mode) */
 # define PGM_GST_TYPE               PGM_TYPE_PROT
 # define PGM_GST_NAME(name)         PGM_GST_NAME_PROT(name)
@@ -1418,9 +1418,5 @@
 VMMDECL(RTHCPHYS) PGMGetHyperAmd64CR3(PVM pVM)
 {
-#ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
     return pVM->pgm.s.HCPhysShwCR3;
-#else
-    return pVM->pgm.s.HCPhysShwCR3;
-#endif
 }
 
Index: trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 16317)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 16321)
@@ -4418,4 +4418,5 @@
 PGM_BTH_DECL(int, MapCR3)(PVM pVM, RTGCPHYS GCPhysCR3)
 {
+    /* Update guest paging info. */
 #if PGM_GST_TYPE == PGM_TYPE_32BIT \
  || PGM_GST_TYPE == PGM_TYPE_PAE \
@@ -4553,4 +4554,60 @@
     int rc = VINF_SUCCESS;
 #endif
+
+#ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
+    /* Update shadow paging info. */
+# if    PGM_SHW_TYPE == PGM_TYPE_32BITS \
+     || PGM_SHW_TYPE == PGM_TYPE_PAE    \
+     || PGM_SHW_TYPE == PGM_TYPE_AMD64
+
+    if (!HWACCMIsNestedPagingActive(pVM))
+    {
+        /* Apply all hypervisor mappings to the new CR3. */
+        PGMMapActivateAll(pVM);
+
+        /*
+         * Update the shadow root page as well since that's not fixed.
+         */
+        PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
+        if (pVM->pgm.s.CTX_SUFF(pShwPageCR3))
+        {
+            /* It might have been freed already by a pool flush (see e.g. PGMR3MappingsUnfix). */
+            /** @todo Coordinate this better with the pool. */
+            if (pVM->pgm.s.CTX_SUFF(pShwPageCR3)->enmKind != PGMPOOLKIND_FREE)
+                pgmPoolFreeByPage(pPool, pVM->pgm.s.CTX_SUFF(pShwPageCR3), SHW_POOL_ROOT_IDX, pVM->pgm.s.CTX_SUFF(pShwPageCR3)->GCPhys >> PAGE_SHIFT);
+            pVM->pgm.s.pShwPageCR3R3 = 0;
+            pVM->pgm.s.pShwPageCR3R0 = 0;
+            pVM->pgm.s.pShwRootR3    = 0;
+#  ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+            pVM->pgm.s.pShwRootR0    = 0;
+#  endif
+            pVM->pgm.s.HCPhysShwCR3  = 0;
+        }
+
+        Assert(!(GCPhysCR3 >> (PAGE_SHIFT + 32)));
+        rc = pgmPoolAlloc(pVM, GCPhysCR3, BTH_PGMPOOLKIND_ROOT, SHW_POOL_ROOT_IDX, GCPhysCR3 >> PAGE_SHIFT, &pVM->pgm.s.CTX_SUFF(pShwPageCR3));
+        if (rc == VERR_PGM_POOL_FLUSHED)
+        {
+            Log(("MapCR3: PGM pool flushed -> signal sync cr3\n"));
+            Assert(VM_FF_ISSET(pVM, VM_FF_PGM_SYNC_CR3));
+            return VINF_PGM_SYNC_CR3;
+        }
+        AssertRCReturn(rc, rc);
+#  ifdef IN_RING0
+        pVM->pgm.s.pShwPageCR3R3 = MMHyperCCToR3(pVM, pVM->pgm.s.CTX_SUFF(pShwPageCR3));
+#  else
+        pVM->pgm.s.pShwPageCR3R0 = MMHyperCCToR0(pVM, pVM->pgm.s.CTX_SUFF(pShwPageCR3));
+#  endif
+        pVM->pgm.s.pShwRootR3    = (R3PTRTYPE(void *))pVM->pgm.s.CTX_SUFF(pShwPageCR3)->pvPageR3;
+        Assert(pVM->pgm.s.pShwRootR3);
+#  ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+        pVM->pgm.s.pShwRootR0    = (R0PTRTYPE(void *))PGMPOOL_PAGE_2_PTR(pPool->CTX_SUFF(pVM), pVM->pgm.s.CTX_SUFF(pShwPageCR3));
+#  endif
+        pVM->pgm.s.HCPhysShwCR3  = pVM->pgm.s.CTX_SUFF(pShwPageCR3)->Core.Key;
+        rc = VINF_SUCCESS; /* clear it - pgmPoolAlloc returns hints. */
+    }
+# endif
+#endif /* VBOX_WITH_PGMPOOL_PAGING_ONLY */
+
     return rc;
 }
@@ -4568,4 +4625,5 @@
     int rc = VINF_SUCCESS;
 
+    /* Update guest paging info. */
 #if PGM_GST_TYPE == PGM_TYPE_32BIT
     pVM->pgm.s.pGst32BitPdR3 = 0;
@@ -4596,12 +4654,12 @@
     pVM->pgm.s.pGstAmd64Pml4R0 = 0;
 # endif
+# ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY
     if (!HWACCMIsNestedPagingActive(pVM))
     {
         pVM->pgm.s.pShwRootR3 = 0;
-# ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+#  ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
         pVM->pgm.s.pShwRootR0 = 0;
-# endif
+#  endif
         pVM->pgm.s.HCPhysShwCR3 = 0;
-# ifndef VBOX_WITH_PGMPOOL_PAGING_ONLY
         if (pVM->pgm.s.CTX_SUFF(pShwPageCR3))
         {
@@ -4611,10 +4669,39 @@
             pVM->pgm.s.pShwPageCR3R0 = 0;
         }
+    }
 # endif /* !VBOX_WITH_PGMPOOL_PAGING_ONLY */
-    }
 
 #else /* prot/real mode stub */
     /* nothing to do */
 #endif
+
+#ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
+    /* Update shadow paging info. */
+# if    PGM_SHW_TYPE == PGM_TYPE_32BITS \
+     || PGM_SHW_TYPE == PGM_TYPE_PAE    \
+     || PGM_SHW_TYPE == PGM_TYPE_AMD64
+
+    if (!HWACCMIsNestedPagingActive(pVM))
+    {
+        /* @todo: dangerous as it's the current CR3! */
+        /* Remove the hypervisor mappings from the shadow page table. */
+        PGMMapDeactivateAll(pVM);
+
+        pVM->pgm.s.pShwRootR3 = 0;
+#  ifndef VBOX_WITH_2X_4GB_ADDR_SPACE
+        pVM->pgm.s.pShwRootR0 = 0;
+#  endif
+        pVM->pgm.s.HCPhysShwCR3 = 0;
+        if (pVM->pgm.s.CTX_SUFF(pShwPageCR3))
+        {
+            PPGMPOOL pPool = pVM->pgm.s.CTX_SUFF(pPool);
+            pgmPoolFreeByPage(pPool, pVM->pgm.s.CTX_SUFF(pShwPageCR3), SHW_POOL_ROOT_IDX, pVM->pgm.s.CTX_SUFF(pShwPageCR3)->GCPhys >> PAGE_SHIFT);
+            pVM->pgm.s.pShwPageCR3R3 = 0;
+            pVM->pgm.s.pShwPageCR3R0 = 0;
+        }
+    }
+# endif
+#endif /* VBOX_WITH_PGMPOOL_PAGING_ONLY */
+
     return rc;
 }
Index: trunk/src/VBox/VMM/VMMAll/PGMAllMap.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllMap.cpp	(revision 16317)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllMap.cpp	(revision 16321)
@@ -210,2 +210,205 @@
 
 
+#ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
+
+/**
+ * Sets all PDEs involved with the mapping in the shadow page table.
+ *
+ * @param   pVM         The VM handle.
+ * @param   pMap        Pointer to the mapping in question.
+ * @param   iNewPDE     The index of the 32-bit PDE corresponding to the base of the mapping.
+ */
+void pgmMapSetShadowPDEs(PVM pVM, PPGMMAPPING pMap, unsigned iNewPDE)
+{
+    if (!pgmMapAreMappingsEnabled(&pVM->pgm.s))
+        return;
+
+    PGMMODE enmShadowMode = PGMGetShadowMode(pVM);
+    Assert(enmShadowMode <= PGMMODE_PAE_NX);
+
+    /*
+     * Init the page tables and insert them into the page directories.
+     */
+    unsigned i = pMap->cPTs;
+    iNewPDE += i;
+    while (i-- > 0)
+    {
+        iNewPDE--;
+
+        switch(enmShadowMode)
+        {
+        case PGMMODE_32_BIT:
+        {
+            PX86PD pShw32BitPd = pgmShwGet32BitPDPtr(&pVM->pgm.s);
+            AssertFatal(pShw32BitPd);
+
+            if (pShw32BitPd->a[iNewPDE].n.u1Present)
+            {
+                Assert(!(pShw32BitPd->a[iNewPDE].u & PGM_PDFLAGS_MAPPING));
+                pgmPoolFree(pVM, pShw32BitPd->a[iNewPDE].u & X86_PDE_PG_MASK, pVM->pgm.s.CTX_SUFF(pShwPageCR3)->idx, iNewPDE);
+            }
+
+            X86PDE Pde;
+            /* Default mapping page directory flags are read/write and supervisor; individual page attributes determine the final flags */
+            Pde.u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | (uint32_t)pMap->aPTs[i].HCPhysPT;
+            pShw32BitPd->a[iNewPDE]   = Pde;
+            break;
+        }
+
+        case PGMMODE_PAE:
+        case PGMMODE_PAE_NX:
+        {
+            PX86PDPT  pShwPdpt;
+            PX86PDPAE pShwPaePd;
+            const unsigned iPdPt = iNewPDE / 256;
+            unsigned iPDE = iNewPDE * 2 % 512;
+
+            pShwPdpt  = pgmShwGetPaePDPTPtr(&pVM->pgm.s);
+            Assert(pShwPdpt);
+            pShwPaePd = pgmShwGetPaePDPtr(&pVM->pgm.s, (iPdPt << X86_PDPT_SHIFT));
+            AssertFatal(pShwPaePd);
+
+            PPGMPOOLPAGE pPoolPagePde = pgmPoolGetPageByHCPhys(pVM, pShwPdpt->a[iPdPt].u & X86_PDPE_PG_MASK);
+            AssertFatal(pPoolPagePde);
+
+            if (pShwPaePd->a[iPDE].n.u1Present)
+            {
+                Assert(!(pShwPaePd->a[iPDE].u & PGM_PDFLAGS_MAPPING));
+                pgmPoolFree(pVM, pShwPaePd->a[iPDE].u & X86_PDE_PG_MASK, pPoolPagePde->idx, iNewPDE);
+            }
+
+            X86PDEPAE PdePae0;
+            PdePae0.u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | pMap->aPTs[i].HCPhysPaePT0;
+            pShwPaePd->a[iPDE] = PdePae0;
+
+            /* 2nd 2 MB PDE of the 4 MB region */
+            iPDE++;
+            AssertFatal(iPDE < 512);
+
+            if (pShwPaePd->a[iPDE].n.u1Present)
+            {
+                Assert(!(pShwPaePd->a[iPDE].u & PGM_PDFLAGS_MAPPING));
+                pgmPoolFree(pVM, pShwPaePd->a[iPDE].u & X86_PDE_PG_MASK, pPoolPagePde->idx, iNewPDE);
+            }
+
+            X86PDEPAE PdePae1;
+            PdePae1.u = PGM_PDFLAGS_MAPPING | X86_PDE_P | X86_PDE_A | X86_PDE_RW | X86_PDE_US | pMap->aPTs[i].HCPhysPaePT1;
+            pShwPaePd->a[iPDE] = PdePae1;
+
+            /* Set the PGM_PDFLAGS_MAPPING flag in the page directory pointer entry. (legacy PAE guest mode) */
+            pShwPdpt->a[iPdPt].u |= PGM_PLXFLAGS_MAPPING;
+        }
+        }
+    }
+}
+
+/**
+ * Clears all PDEs involved with the mapping in the shadow page table.
+ *
+ * @param   pVM         The VM handle.
+ * @param   pMap        Pointer to the mapping in question.
+ * @param   iOldPDE     The index of the 32-bit PDE corresponding to the base of the mapping.
+ */
+void pgmMapClearShadowPDEs(PVM pVM, PPGMMAPPING pMap, unsigned iOldPDE)
+{
+    unsigned i = pMap->cPTs;
+    PGMMODE  enmShadowMode = PGMGetShadowMode(pVM);
+
+    if (!pgmMapAreMappingsEnabled(&pVM->pgm.s))
+        return;
+
+    iOldPDE += i;
+    while (i-- > 0)
+    {
+        iOldPDE--;
+
+        switch(enmShadowMode)
+        {
+        case PGMMODE_32_BIT:
+        {
+            PX86PD pShw32BitPd = pgmShwGet32BitPDPtr(&pVM->pgm.s);
+            AssertFatal(pShw32BitPd);
+
+            pShw32BitPd->a[iOldPDE].u   = 0;
+            break;
+        }
+
+        case PGMMODE_PAE:
+        case PGMMODE_PAE_NX:
+        {
+            PX86PDPT  pPdpt = NULL;
+            PX86PDPAE pShwPaePd = NULL;
+
+            const unsigned iPD = iOldPDE / 256;         /* iOldPDE * 2 / 512; iOldPDE is in 4 MB pages */
+            unsigned iPDE = iOldPDE * 2 % 512;
+            pPdpt     = pgmShwGetPaePDPTPtr(&pVM->pgm.s);
+            pShwPaePd = pgmShwGetPaePDPtr(&pVM->pgm.s, (iPD << X86_PDPT_SHIFT));
+            AssertFatal(pShwPaePd);
+
+            pShwPaePd->a[iPDE].u = 0;
+
+            iPDE++;
+            AssertFatal(iPDE < 512);
+
+            pShwPaePd->a[iPDE].u = 0;
+            /* Clear the PGM_PDFLAGS_MAPPING flag for the page directory pointer entry. (legacy PAE guest mode) */
+            pPdpt->a[iPD].u &= ~PGM_PLXFLAGS_MAPPING;
+            break;
+        }
+        }
+    }
+}
+
+/**
+ * Apply the hypervisor mappings to the active CR3.
+ *
+ * @returns VBox status.
+ * @param   pVM         The virtual machine.
+ */
+VMMDECL(int) PGMMapActivateAll(PVM pVM)
+{
+    /*
+     * Can skip this if mappings are safely fixed.
+     */
+    if (pVM->pgm.s.fMappingsFixed)
+        return VINF_SUCCESS;
+
+    /*
+     * Iterate mappings.
+     */
+    for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
+    {
+        unsigned iPDE = pCur->GCPtr >> X86_PD_SHIFT;
+
+        pgmMapSetShadowPDEs(pVM, pCur, iPDE);
+    }
+
+    return VINF_SUCCESS;
+}
+
+/**
+ * Remove the hypervisor mappings from the active CR3
+ *
+ * @returns VBox status.
+ * @param   pVM         The virtual machine.
+ */
+VMMDECL(int) PGMMapDeactivateAll(PVM pVM)
+{
+    /*
+     * Can skip this if mappings are safely fixed.
+     */
+    if (pVM->pgm.s.fMappingsFixed)
+        return VINF_SUCCESS;
+
+    /*
+     * Iterate mappings.
+     */
+    for (PPGMMAPPING pCur = pVM->pgm.s.CTX_SUFF(pMappings); pCur; pCur = pCur->CTX_SUFF(pNext))
+    {
+        unsigned iPDE = pCur->GCPtr >> X86_PD_SHIFT;
+
+        pgmMapClearShadowPDEs(pVM, pCur, iPDE);
+    }
+    return VINF_SUCCESS;
+}
+#endif /* VBOX_WITH_PGMPOOL_PAGING_ONLY */
Index: trunk/src/VBox/VMM/VMMAll/PGMAllShw.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/PGMAllShw.h	(revision 16317)
+++ trunk/src/VBox/VMM/VMMAll/PGMAllShw.h	(revision 16321)
@@ -110,5 +110,5 @@
 #  define SHW_PDPE_PG_MASK      X86_PDPE_PG_MASK
 #  define SHW_TOTAL_PD_ENTRIES  (X86_PG_PAE_ENTRIES*X86_PG_PAE_PDPE_ENTRIES)
-#  define SHW_POOL_ROOT_IDX     PGMPOOL_IDX_PAE_PD
+#  define SHW_POOL_ROOT_IDX     PGMPOOL_IDX_PDPT
 
 # endif
