Index: /trunk/src/VBox/VMM/PGMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/PGMInternal.h	(revision 16839)
+++ /trunk/src/VBox/VMM/PGMInternal.h	(revision 16840)
@@ -2979,6 +2979,7 @@
 
 #ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
-void            pgmMapClearShadowPDEs(PVM pVM, PPGMMAPPING pMap, unsigned iOldPDE);
+void            pgmMapClearShadowPDEs(PVM pVM, PPGMPOOLPAGE pShwPageCR3, PPGMMAPPING pMap, unsigned iOldPDE);
 void            pgmMapSetShadowPDEs(PVM pVM, PPGMMAPPING pMap, unsigned iNewPDE);
+int             pgmMapDeactivateCR3(PVM pVM, PPGMPOOLPAGE pShwPageCR3);
 #endif
 
@@ -4290,4 +4291,29 @@
 }
 
+/**
+ * Gets the shadow page directory for the specified address, PAE.
+ *
+ * @returns Pointer to the shadow PD.
+ * @param   pPGM        Pointer to the PGM instance data.
+ * @param   GCPtr       The address.
+ */
+DECLINLINE(PX86PDPAE) pgmShwGetPaePDPtr(PPGM pPGM, PX86PDPT pPdpt, RTGCPTR GCPtr)
+{
+#ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
+    const unsigned  iPdpt = (GCPtr >> X86_PDPT_SHIFT) & X86_PDPT_MASK_PAE;
+
+    if (!pPdpt->a[iPdpt].n.u1Present)
+        return NULL;
+
+    /* Fetch the pgm pool shadow descriptor. */
+    PPGMPOOLPAGE    pShwPde = pgmPoolGetPageByHCPhys(PGM2VM(pPGM), pPdpt->a[iPdpt].u & X86_PDPE_PG_MASK);
+    AssertReturn(pShwPde, NULL);
+
+    return (PX86PDPAE)PGMPOOL_PAGE_2_PTR_BY_PGM(pPGM, pShwPde);
+#else
+    AssertFailed();
+    return NULL;
+#endif
+}
 
 /**
Index: /trunk/src/VBox/VMM/PGMMap.cpp
===================================================================
--- /trunk/src/VBox/VMM/PGMMap.cpp	(revision 16839)
+++ /trunk/src/VBox/VMM/PGMMap.cpp	(revision 16840)
@@ -929,5 +929,5 @@
 
 #ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
-    pgmMapClearShadowPDEs(pVM, pMap, iOldPDE);
+    pgmMapClearShadowPDEs(pVM, pVM->pgm.s.CTX_SUFF(pShwPageCR3), pMap, iOldPDE);
 #endif
 
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 16839)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 16840)
@@ -4633,30 +4633,11 @@
      * 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))
-    {
-        /* Remove the hypervisor mappings from the shadow page table. */
-        PGMMapDeactivateAll(pVM);
-
-        /* 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), pVM->pgm.s.iShwUser, pVM->pgm.s.iShwUserTable);
-        pVM->pgm.s.pShwPageCR3R3 = 0;
-        pVM->pgm.s.pShwPageCR3RC = 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;
-        pVM->pgm.s.iShwUser      = 0;
-        pVM->pgm.s.iShwUserTable = 0;
-    }
+    PPGMPOOL     pPool             = pVM->pgm.s.CTX_SUFF(pPool);
+    PPGMPOOLPAGE pOldShwPageCR3    = pVM->pgm.s.CTX_SUFF(pShwPageCR3);
+    uint32_t     iOldShwUserTable  = pVM->pgm.s.iShwUserTable;
+    uint32_t     iOldShwUser       = pVM->pgm.s.iShwUser;
 
     Assert(!(GCPhysCR3 >> (PAGE_SHIFT + 32)));
-    pVM->pgm.s.iShwUser      = SHW_POOL_ROOT_IDX;
-    pVM->pgm.s.iShwUserTable = GCPhysCR3 >> PAGE_SHIFT;
-    rc = pgmPoolAlloc(pVM, GCPhysCR3 & GST_CR3_PAGE_MASK, BTH_PGMPOOLKIND_ROOT, pVM->pgm.s.iShwUser, pVM->pgm.s.iShwUserTable, &pVM->pgm.s.CTX_SUFF(pShwPageCR3));
+    rc = pgmPoolAlloc(pVM, GCPhysCR3 & GST_CR3_PAGE_MASK, BTH_PGMPOOLKIND_ROOT, SHW_POOL_ROOT_IDX, GCPhysCR3 >> PAGE_SHIFT, &pVM->pgm.s.CTX_SUFF(pShwPageCR3));
     if (rc == VERR_PGM_POOL_FLUSHED)
     {
@@ -4666,4 +4647,6 @@
     }
     AssertRCReturn(rc, rc);
+    pVM->pgm.s.iShwUser      = SHW_POOL_ROOT_IDX;
+    pVM->pgm.s.iShwUserTable = GCPhysCR3 >> PAGE_SHIFT;
 #  ifdef IN_RING0
     pVM->pgm.s.pShwPageCR3R3 = MMHyperCCToR3(pVM, pVM->pgm.s.CTX_SUFF(pShwPageCR3));
@@ -4683,6 +4666,22 @@
     pVM->pgm.s.HCPhysShwCR3  = pVM->pgm.s.CTX_SUFF(pShwPageCR3)->Core.Key;
 
+#  ifndef PGM_WITHOUT_MAPPINGS
     /* Apply all hypervisor mappings to the new CR3. */
     rc = PGMMapActivateAll(pVM);
+    AssertRC(rc);
+#  endif
+    /* Clean up the old CR3 root. */
+    if (pOldShwPageCR3)
+    {
+#  ifndef PGM_WITHOUT_MAPPINGS
+        /* Remove the hypervisor mappings from the shadow page table. */
+        pgmMapDeactivateCR3(pVM, pOldShwPageCR3);
+#  endif
+        /* It might have been freed already by a pool flush (see e.g. PGMR3MappingsUnfix). */
+        /** @todo Coordinate this better with the pool. */
+        if (pOldShwPageCR3->enmKind != PGMPOOLKIND_FREE)
+            pgmPoolFreeByPage(pPool, pOldShwPageCR3, iOldShwUser, iOldShwUserTable);
+    }
+
 # endif
 #endif /* VBOX_WITH_PGMPOOL_PAGING_ONLY */
@@ -4754,7 +4753,7 @@
 #endif
 
-#ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
+#if defined(VBOX_WITH_PGMPOOL_PAGING_ONLY) && !defined(IN_RC) /* In RC we rely on MapCR3 to do the shadow part for us at a safe time */
     /* Update shadow paging info. */
-# if  (   (   PGM_SHW_TYPE == PGM_TYPE_32BIT \
+# if  (   (   PGM_SHW_TYPE == PGM_TYPE_32BIT  \
            || PGM_SHW_TYPE == PGM_TYPE_PAE    \
            || PGM_SHW_TYPE == PGM_TYPE_AMD64) \
@@ -4764,7 +4763,8 @@
     Assert(!HWACCMIsNestedPagingActive(pVM));
 
-    /* @todo: dangerous as it's the current CR3! */
+# ifndef PGM_WITHOUT_MAPPINGS
     /* Remove the hypervisor mappings from the shadow page table. */
     PGMMapDeactivateAll(pVM);
+# endif
 
     pVM->pgm.s.pShwRootR3 = 0;
@@ -4783,5 +4783,5 @@
     }
 # endif
-#endif /* VBOX_WITH_PGMPOOL_PAGING_ONLY */
+#endif /* VBOX_WITH_PGMPOOL_PAGING_ONLY && !IN_RC*/
 
     return rc;
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllMap.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllMap.cpp	(revision 16839)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllMap.cpp	(revision 16840)
@@ -209,4 +209,5 @@
 
 
+#ifndef IN_RING0
 /**
  * Sets all PDEs involved with the mapping in the shadow page table.
@@ -313,11 +314,11 @@
  *
  * @param   pVM         The VM handle.
+ * @param   pShwPageCR3 CR3 root page
  * @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);
+void pgmMapClearShadowPDEs(PVM pVM, PPGMPOOLPAGE pShwPageCR3, PPGMMAPPING pMap, unsigned iOldPDE)
+{
+    Assert(pShwPageCR3);
 
     if (!pgmMapAreMappingsEnabled(&pVM->pgm.s))
@@ -329,4 +330,7 @@
 #endif
 
+    unsigned i = pMap->cPTs;
+    PGMMODE  enmShadowMode = PGMGetShadowMode(pVM);
+
     iOldPDE += i;
     while (i-- > 0)
@@ -338,5 +342,5 @@
             case PGMMODE_32_BIT:
             {
-                PX86PD pShw32BitPd = pgmShwGet32BitPDPtr(&pVM->pgm.s);
+                PX86PD pShw32BitPd = (PX86PD)PGMPOOL_PAGE_2_PTR_BY_PGM(&pVM->pgm.s, pShwPageCR3);
                 AssertFatal(pShw32BitPd);
 
@@ -353,6 +357,6 @@
                 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));
+                pPdpt     = (PX86PDPT)PGMPOOL_PAGE_2_PTR_BY_PGM(&pVM->pgm.s, pShwPageCR3);
+                pShwPaePd = pgmShwGetPaePDPtr(&pVM->pgm.s, pPdpt, (iPD << X86_PDPT_SHIFT));
                 AssertFatal(pShwPaePd);
 
@@ -374,4 +378,5 @@
     }
 }
+#endif /* !IN_RING0 */
 
 /**
@@ -389,7 +394,11 @@
         return VINF_SUCCESS;
 
-#ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
+#ifdef IN_RING0
+    AssertFailed();
+    return VERR_INTERNAL_ERROR;
+#else
+# ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
     Assert(pVM->pgm.s.CTX_SUFF(pShwPageCR3));
-#endif
+# endif
 
     /*
@@ -402,6 +411,6 @@
         pgmMapSetShadowPDEs(pVM, pCur, iPDE);
     }
-
     return VINF_SUCCESS;
+#endif /* IN_RING0 */
 }
 
@@ -420,7 +429,11 @@
         return VINF_SUCCESS;
 
-#ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
+#ifdef IN_RING0
+    AssertFailed();
+    return VERR_INTERNAL_ERROR;
+#else
+# ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
     Assert(pVM->pgm.s.CTX_SUFF(pShwPageCR3));
-#endif
+# endif
 
     /*
@@ -431,6 +444,44 @@
         unsigned iPDE = pCur->GCPtr >> X86_PD_SHIFT;
 
-        pgmMapClearShadowPDEs(pVM, pCur, iPDE);
+        pgmMapClearShadowPDEs(pVM, pVM->pgm.s.CTX_SUFF(pShwPageCR3), pCur, iPDE);
     }
     return VINF_SUCCESS;
-}
+#endif /* IN_RING0 */
+}
+
+
+/**
+ * Remove the hypervisor mappings from the specified CR3
+ *
+ * @returns VBox status.
+ * @param   pVM         The virtual machine.
+ * @param   pShwPageCR3 CR3 root page
+ */
+int pgmMapDeactivateCR3(PVM pVM, PPGMPOOLPAGE pShwPageCR3)
+{
+    /*
+     * Can skip this if mappings are safely fixed.
+     */
+    if (pVM->pgm.s.fMappingsFixed)
+        return VINF_SUCCESS;
+
+#ifdef IN_RING0
+    AssertFailed();
+    return VERR_INTERNAL_ERROR;
+#else
+# ifdef VBOX_WITH_PGMPOOL_PAGING_ONLY
+    Assert(pVM->pgm.s.CTX_SUFF(pShwPageCR3));
+# endif
+
+    /*
+     * 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, pShwPageCR3, pCur, iPDE);
+    }
+    return VINF_SUCCESS;
+#endif /* IN_RING0 */
+}
