Index: /trunk/include/VBox/pgm.h
===================================================================
--- /trunk/include/VBox/pgm.h	(revision 30325)
+++ /trunk/include/VBox/pgm.h	(revision 30326)
@@ -312,6 +312,16 @@
 #endif
 VMMDECL(int)        PGMShwGetPage(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys);
-VMMDECL(int)        PGMShwSetPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags);
-VMMDECL(int)        PGMShwModifyPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask);
+VMMDECL(int)        PGMShwMakePageReadonly(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+VMMDECL(int)        PGMShwMakePageWritable(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+VMMDECL(int)        PGMShwMakePageNotPresent(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+/** @name Flags for PGMShwMakePageReadonly, PGMShwMakePageWritable and
+ *        PGMShwMakePageNotPresent
+ * @{ */
+/** The call is from an access handler for dealing with the a faulting write
+ * operation.  The virtual address is within the same page. */
+#define PGM_MK_PG_IS_WRITE_FAULT     RT_BIT(0)
+/** The page is an MMIO2. */
+#define PGM_MK_PG_IS_MMIO2           RT_BIT(1)
+/** @}*/
 VMMDECL(int)        PGMGstGetPage(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys);
 VMMDECL(bool)       PGMGstIsPagePresent(PVMCPU pVCpu, RTGCPTR GCPtr);
Index: /trunk/src/VBox/Devices/Graphics/DevVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 30325)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 30326)
@@ -3898,5 +3898,6 @@
     {
 #ifndef IN_RING3
-        rc = PGMShwModifyPage(PDMDevHlpGetVMCPU(pThis->CTX_SUFF(pDevIns)), GCPtr, 1, X86_PTE_RW, ~(uint64_t)X86_PTE_RW);
+        rc = PGMShwMakePageWritable(PDMDevHlpGetVMCPU(pThis->CTX_SUFF(pDevIns)), GCPtr,
+                                    PGM_MK_PG_IS_MMIO2 | PGM_MK_PG_IS_WRITE_FAULT);
         PDMCritSectLeave(&pThis->lock);
         AssertMsgReturn(    rc == VINF_SUCCESS
@@ -3906,16 +3907,13 @@
                         ("PGMShwModifyPage -> GCPtr=%RGv rc=%d\n", GCPtr, rc),
                         rc);
-        return VINF_SUCCESS;
 #else /* IN_RING3 : We don't have any virtual page address of the access here. */
         PDMCritSectLeave(&pThis->lock);
         Assert(GCPtr == 0);
+#endif
         return VINF_SUCCESS;
-#endif
-    }
-    else
-    {
-        PDMCritSectLeave(&pThis->lock);
-        AssertMsgFailed(("PGMHandlerPhysicalPageTempOff -> rc=%d\n", rc));
-    }
+    }
+
+    PDMCritSectLeave(&pThis->lock);
+    AssertMsgFailed(("PGMHandlerPhysicalPageTempOff -> rc=%d\n", rc));
     return rc;
 }
Index: /trunk/src/VBox/VMM/PATM/CSAM.cpp
===================================================================
--- /trunk/src/VBox/VMM/PATM/CSAM.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/PATM/CSAM.cpp	(revision 30326)
@@ -1794,5 +1794,5 @@
         AssertRC(rc);
 
-        rc = PGMShwModifyPage(pVCpu, GCPtr, 1, 0, ~(uint64_t)X86_PTE_RW);
+        rc = PGMShwMakePageReadonly(pVCpu, GCPtr, 0 /*fFlags*/);
         Assert(rc == VINF_SUCCESS || rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT);
 
@@ -1906,5 +1906,5 @@
         AssertRC(rc);
 
-        rc = PGMShwModifyPage(pVCpu, pPageAddrGC, 1, 0, ~(uint64_t)X86_PTE_RW);
+        rc = PGMShwMakePageReadonly(pVCpu, pPageAddrGC, 0 /*fFlags*/);
         Assert(rc == VINF_SUCCESS || rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT);
 
@@ -1928,5 +1928,5 @@
 
         /* Make sure it's readonly. Page invalidation may have modified the attributes. */
-        rc = PGMShwModifyPage(pVCpu, pPageAddrGC, 1, 0, ~(uint64_t)X86_PTE_RW);
+        rc = PGMShwMakePageReadonly(pVCpu, pPageAddrGC, 0 /*fFlags*/);
         Assert(rc == VINF_SUCCESS || rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT);
     }
@@ -1950,5 +1950,5 @@
         AssertRC(rc);
         /* The page was changed behind our back. It won't be made read-only until the next SyncCR3, so force it here. */
-        rc = PGMShwModifyPage(pVCpu, pPageAddrGC, 1, 0, ~(uint64_t)X86_PTE_RW);
+        rc = PGMShwMakePageReadonly(pVCpu, pPageAddrGC, 0 /*fFlags*/);
         Assert(rc == VINF_SUCCESS || rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT);
     }
@@ -2330,5 +2330,5 @@
 
         /* Enable write protection again. (use the fault address as it might be an alias) */
-        rc = PGMShwModifyPage(pVCpu, pVM->csam.s.pvDirtyFaultPage[i], 1, 0, ~(uint64_t)X86_PTE_RW);
+        rc = PGMShwMakePageReadonly(pVCpu, pVM->csam.s.pvDirtyFaultPage[i], 0 /*fFlags*/);
         Assert(rc == VINF_SUCCESS || rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT);
 
@@ -2374,5 +2374,5 @@
 
         Log(("csamR3FlushCodePages: %RRv\n", GCPtr));
-        PGMShwSetPage(pVCpu, GCPtr, 1, 0);
+        PGMShwMakePageNotPresent(pVCpu, GCPtr, 0 /*fFlags*/);
         /* Resync the page to make sure instruction fetch will fault */
         CSAMMarkPage(pVM, GCPtr, false);
Index: /trunk/src/VBox/VMM/PATM/PATM.cpp
===================================================================
--- /trunk/src/VBox/VMM/PATM/PATM.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/PATM/PATM.cpp	(revision 30326)
@@ -6136,5 +6136,5 @@
 
             /* Typical pushf (most patches)/push (call patch) trap because of a monitored page. */
-            rc = PGMShwModifyPage(pVCpu, pCtx->esp, 1, X86_PTE_RW, ~(uint64_t)X86_PTE_RW);
+            rc = PGMShwMakePageWritable(pVCpu, pCtx->esp, 0 /*fFlags*/);
             AssertMsgRC(rc, ("PGMShwModifyPage -> rc=%Rrc\n", rc));
             if (rc == VINF_SUCCESS)
Index: /trunk/src/VBox/VMM/PATM/VMMGC/CSAMGC.cpp
===================================================================
--- /trunk/src/VBox/VMM/PATM/VMMGC/CSAMGC.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/PATM/VMMGC/CSAMGC.cpp	(revision 30326)
@@ -86,5 +86,5 @@
          * Make this particular page R/W.
          */
-        rc = PGMShwModifyPage(pVCpu, pvFault, 1, X86_PTE_RW, ~(uint64_t)X86_PTE_RW);
+        rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
         AssertMsgRC(rc, ("PGMShwModifyPage -> rc=%Rrc\n", rc));
         ASMInvalidatePage((void *)(uintptr_t)pvFault);
@@ -127,5 +127,5 @@
      */
     Log(("CSAMGCCodePageWriteHandler: enabled r/w for page %RGv\n", pvFault));
-    rc = PGMShwModifyPage(pVCpu, pvFault, 1, X86_PTE_RW, ~(uint64_t)X86_PTE_RW);
+    rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
     AssertMsgRC(rc, ("PGMShwModifyPage -> rc=%Rrc\n", rc));
     ASMInvalidatePage((void *)(uintptr_t)pvFault);
Index: /trunk/src/VBox/VMM/PATM/VMMGC/PATMGC.cpp
===================================================================
--- /trunk/src/VBox/VMM/PATM/VMMGC/PATMGC.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/PATM/VMMGC/PATMGC.cpp	(revision 30326)
@@ -101,5 +101,5 @@
 #ifdef LOG_ENABLED
     if (pPatchPage)
-        Log(("PATMIsWriteToPatchPage: Found page %RRv for write to %RRv %d bytes (page low:high %RRv:%RRv\n", pPatchPage->Core.Key, GCPtr, cbWrite, pPatchPage->pLowestAddrGC, pPatchPage->pHighestAddrGC));
+        Log(("PATMGCHandleWriteToPatchPage: Found page %RRv for write to %RRv %d bytes (page low:high %RRv:%RRv\n", pPatchPage->Core.Key, GCPtr, cbWrite, pPatchPage->pLowestAddrGC, pPatchPage->pHighestAddrGC));
 #endif
 
Index: /trunk/src/VBox/VMM/PGMHandler.cpp
===================================================================
--- /trunk/src/VBox/VMM/PGMHandler.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/PGMHandler.cpp	(revision 30326)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
Index: /trunk/src/VBox/VMM/PGMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/PGMInternal.h	(revision 30325)
+++ /trunk/src/VBox/VMM/PGMInternal.h	(revision 30326)
@@ -233,24 +233,4 @@
 # define PGM_HCPHYS_2_PTR(pVM, HCPhys, ppv) \
      MMPagePhys2PageEx(pVM, HCPhys, (void **)(ppv))
-#endif
-
-/** @def PGM_HCPHYS_2_PTR_BY_PGM
- * Maps a HC physical page pool address to a virtual address.
- *
- * @returns VBox status code.
- * @param   pPGM    The PGM instance data.
- * @param   HCPhys  The HC physical address to map to a virtual one.
- * @param   ppv     Where to store the virtual address. No need to cast this.
- *
- * @remark  In GC this uses PGMGCDynMapHCPage(), so it will consume of the
- *          small page window employeed by that function. Be careful.
- * @remark  There is no need to assert on the result.
- */
-#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
-# define PGM_HCPHYS_2_PTR_BY_PGM(pPGM, HCPhys, ppv) \
-     pgmR0DynMapHCPageInlined(pPGM, HCPhys, (void **)(ppv))
-#else
-# define PGM_HCPHYS_2_PTR_BY_PGM(pPGM, HCPhys, ppv) \
-     PGM_HCPHYS_2_PTR(PGM2VM(pPGM), HCPhys, (void **)(ppv))
 #endif
 
@@ -2415,11 +2395,11 @@
     DECLR3CALLBACKMEMBER(int,       pfnR3ShwExit,(PVMCPU pVCpu));
     DECLR3CALLBACKMEMBER(int,       pfnR3ShwGetPage,(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
-    DECLR3CALLBACKMEMBER(int,       pfnR3ShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
+    DECLR3CALLBACKMEMBER(int,       pfnR3ShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags));
 
     DECLRCCALLBACKMEMBER(int,       pfnRCShwGetPage,(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
-    DECLRCCALLBACKMEMBER(int,       pfnRCShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
+    DECLRCCALLBACKMEMBER(int,       pfnRCShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags));
 
     DECLR0CALLBACKMEMBER(int,       pfnR0ShwGetPage,(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
-    DECLR0CALLBACKMEMBER(int,       pfnR0ShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
+    DECLR0CALLBACKMEMBER(int,       pfnR0ShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags));
     /** @} */
 
@@ -3049,11 +3029,11 @@
     DECLR3CALLBACKMEMBER(int,       pfnR3ShwExit,(PVMCPU pVCpu));
     DECLR3CALLBACKMEMBER(int,       pfnR3ShwGetPage,(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
-    DECLR3CALLBACKMEMBER(int,       pfnR3ShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
+    DECLR3CALLBACKMEMBER(int,       pfnR3ShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags));
 
     DECLRCCALLBACKMEMBER(int,       pfnRCShwGetPage,(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
-    DECLRCCALLBACKMEMBER(int,       pfnRCShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
+    DECLRCCALLBACKMEMBER(int,       pfnRCShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags));
 
     DECLR0CALLBACKMEMBER(int,       pfnR0ShwGetPage,(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys));
-    DECLR0CALLBACKMEMBER(int,       pfnR0ShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask));
+    DECLR0CALLBACKMEMBER(int,       pfnR0ShwModifyPage,(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags));
 
     /** @} */
Index: /trunk/src/VBox/VMM/PGMPhys.cpp
===================================================================
--- /trunk/src/VBox/VMM/PGMPhys.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/PGMPhys.cpp	(revision 30326)
@@ -3864,5 +3864,5 @@
 
             /* Make sure what we return is writable. */
-            if (fWritable && rc != VINF_PGM_PHYS_TLB_CATCH_WRITE)
+            if (fWritable)
                 switch (PGM_PAGE_GET_STATE(pPage))
                 {
@@ -3874,4 +3874,6 @@
                     case PGM_PAGE_STATE_ZERO:
                     case PGM_PAGE_STATE_SHARED:
+                        if (rc == VINF_PGM_PHYS_TLB_CATCH_WRITE)
+                            break;
                     case PGM_PAGE_STATE_WRITE_MONITORED:
                         rc2 = pgmPhysPageMakeWritable(pVM, pPage, GCPhys & ~(RTGCPHYS)PAGE_OFFSET_MASK);
Index: /trunk/src/VBox/VMM/PGMPool.cpp
===================================================================
--- /trunk/src/VBox/VMM/PGMPool.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/PGMPool.cpp	(revision 30326)
@@ -606,5 +606,5 @@
 
     pgmLock(pVM);
-    Log(("pgmR3PoolClearAllRendezvous: cUsedPages=%d\n", pPool->cUsedPages));
+    Log(("pgmR3PoolClearAllRendezvous: cUsedPages=%d fpvFlushRemTbl=%RTbool\n", pPool->cUsedPages, !!fpvFlushRemTbl));
 
     /*
Index: /trunk/src/VBox/VMM/PGMSavedState.cpp
===================================================================
--- /trunk/src/VBox/VMM/PGMSavedState.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/PGMSavedState.cpp	(revision 30326)
@@ -1237,13 +1237,15 @@
  * @param   iPage               The page index.
  */
-static void pgmR3StateVerifyCrc32ForPage(void const *pvPage, PPGMRAMRANGE pCur, PPGMLIVESAVERAMPAGE paLSPages, uint32_t iPage)
+static void pgmR3StateVerifyCrc32ForPage(void const *pvPage, PPGMRAMRANGE pCur, PPGMLIVESAVERAMPAGE paLSPages, uint32_t iPage, const  char *pszWhere)
 {
     if (paLSPages[iPage].u32Crc != UINT32_MAX)
     {
         uint32_t u32Crc = RTCrc32(pvPage, PAGE_SIZE);
-        Assert((!PGM_PAGE_IS_ZERO(&pCur->aPages[iPage]) && !PGM_PAGE_IS_BALLOONED(&pCur->aPages[iPage])) || u32Crc == PGM_STATE_CRC32_ZERO_PAGE);
+        Assert(   (   !PGM_PAGE_IS_ZERO(&pCur->aPages[iPage])
+                   && !PGM_PAGE_IS_BALLOONED(&pCur->aPages[iPage]))
+               || u32Crc == PGM_STATE_CRC32_ZERO_PAGE);
         AssertMsg(paLSPages[iPage].u32Crc == u32Crc,
-                  ("%08x != %08x for %RGp %R[pgmpage]\n", paLSPages[iPage].u32Crc, u32Crc,
-                   pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), &pCur->aPages[iPage]));
+                  ("%08x != %08x for %RGp %R[pgmpage] %s\n", paLSPages[iPage].u32Crc, u32Crc,
+                   pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), &pCur->aPages[iPage], pszWhere));
     }
 }
@@ -1259,5 +1261,5 @@
  * @param   iPage               The page index.
  */
-static void pgmR3StateVerifyCrc32ForRamPage(PVM pVM, PPGMRAMRANGE pCur, PPGMLIVESAVERAMPAGE paLSPages, uint32_t iPage)
+static void pgmR3StateVerifyCrc32ForRamPage(PVM pVM, PPGMRAMRANGE pCur, PPGMLIVESAVERAMPAGE paLSPages, uint32_t iPage, const char *pszWhere)
 {
     if (paLSPages[iPage].u32Crc != UINT32_MAX)
@@ -1267,5 +1269,5 @@
         int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, &pCur->aPages[iPage], GCPhys, &pvPage);
         if (RT_SUCCESS(rc))
-            pgmR3StateVerifyCrc32ForPage(pvPage, pCur, paLSPages, iPage);
+            pgmR3StateVerifyCrc32ForPage(pvPage, pCur, paLSPages, iPage, pszWhere);
     }
 }
@@ -1370,5 +1372,5 @@
                                         pgmR3StateCalcCrc32ForRamPage(pVM, pCur, paLSPages, iPage);
                                     else
-                                        pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage);
+                                        pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage, "scan");
 #endif
                                     paLSPages[iPage].fWriteMonitoredJustNow = 0;
@@ -1568,5 +1570,5 @@
 #ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
                             if (PGM_PAGE_GET_TYPE(&pCur->aPages[iPage]) != PGMPAGETYPE_RAM)
-                                pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage);
+                                pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage, "save#1");
 #endif
                             continue;
@@ -1597,5 +1599,5 @@
 #ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
                             if (paLSPages)
-                                pgmR3StateVerifyCrc32ForPage(abPage, pCur, paLSPages, iPage);
+                                pgmR3StateVerifyCrc32ForPage(abPage, pCur, paLSPages, iPage, "save#3");
 #endif
                         }
@@ -1619,5 +1621,5 @@
 #ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
                         if (paLSPages)
-                            pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage);
+                            pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage, "save#2");
 #endif
                         pgmUnlock(pVM);
Index: /trunk/src/VBox/VMM/PGMShw.h
===================================================================
--- /trunk/src/VBox/VMM/PGMShw.h	(revision 30325)
+++ /trunk/src/VBox/VMM/PGMShw.h	(revision 30326)
@@ -123,5 +123,5 @@
 /* all */
 PGM_SHW_DECL(int, GetPage)(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys);
-PGM_SHW_DECL(int, ModifyPage)(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask);
+PGM_SHW_DECL(int, ModifyPage)(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags);
 RT_C_DECLS_END
 
Index: /trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAll.cpp	(revision 30326)
@@ -825,20 +825,4 @@
 
 /**
- * Sets (replaces) the page flags for a range of pages in the shadow context.
- *
- * @returns VBox status.
- * @param   pVCpu       VMCPU handle.
- * @param   GCPtr       The address of the first page.
- * @param   cb          The size of the range in bytes.
- * @param   fFlags      Page flags X86_PTE_*, excluding the page mask of course.
- * @remark  You must use PGMMapSetPage() for pages in a mapping.
- */
-VMMDECL(int) PGMShwSetPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags)
-{
-    return PGMShwModifyPage(pVCpu, GCPtr, cb, fFlags, 0);
-}
-
-
-/**
  * Modify page flags for a range of pages in the shadow context.
  *
@@ -848,31 +832,74 @@
  * @param   pVCpu       VMCPU handle.
  * @param   GCPtr       Virtual address of the first page in the range.
- * @param   cb          Size (in bytes) of the range to apply the modification to.
  * @param   fFlags      The OR  mask - page flags X86_PTE_*, excluding the page mask of course.
  * @param   fMask       The AND mask - page flags X86_PTE_*.
  *                      Be very CAREFUL when ~'ing constants which could be 32-bit!
+ * @param   fOpFlags    A combination of the PGM_MK_PK_XXX flags.
  * @remark  You must use PGMMapModifyPage() for pages in a mapping.
  */
-VMMDECL(int) PGMShwModifyPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
+DECLINLINE(int) pdmShwModifyPage(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags)
 {
     AssertMsg(!(fFlags & X86_PTE_PAE_PG_MASK), ("fFlags=%#llx\n", fFlags));
-    Assert(cb);
-
-    /*
-     * Align the input.
-     */
-    cb     += GCPtr & PAGE_OFFSET_MASK;
-    cb      = RT_ALIGN_Z(cb, PAGE_SIZE);
-    GCPtr   = (GCPtr & PAGE_BASE_GC_MASK); /** @todo this ain't necessary, right... */
-
-    /*
-     * Call worker.
-     */
+    Assert(!(fOpFlags & ~(PGM_MK_PG_IS_MMIO2 | PGM_MK_PG_IS_WRITE_FAULT)));
+
+    GCPtr &= PAGE_BASE_GC_MASK; /** @todo this ain't necessary, right... */
+
     PVM pVM = pVCpu->CTX_SUFF(pVM);
     pgmLock(pVM);
-    int rc = PGM_SHW_PFN(ModifyPage, pVCpu)(pVCpu, GCPtr, cb, fFlags, fMask);
+    int rc = PGM_SHW_PFN(ModifyPage, pVCpu)(pVCpu, GCPtr, PAGE_SIZE, fFlags, fMask, fOpFlags);
     pgmUnlock(pVM);
     return rc;
 }
+
+
+/**
+ * Changing the page flags for a single page in the shadow page tables so as to
+ * make it read-only.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       VMCPU handle.
+ * @param   GCPtr       Virtual address of the first page in the range.
+ * @param   fOpFlags    A combination of the PGM_MK_PK_XXX flags.
+ */
+VMMDECL(int) PGMShwMakePageReadonly(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
+{
+    return pdmShwModifyPage(pVCpu, GCPtr, 0, ~(uint64_t)X86_PTE_RW, fOpFlags);
+}
+
+
+/**
+ * Changing the page flags for a single page in the shadow page tables so as to
+ * make it writable.
+ *
+ * The call must know with 101% certainty that the guest page tables maps this
+ * as writable too.  This function will deal shared, zero and write monitored
+ * pages.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       VMCPU handle.
+ * @param   GCPtr       Virtual address of the first page in the range.
+ * @param   fMmio2      Set if it is an MMIO2 page.
+ * @param   fOpFlags    A combination of the PGM_MK_PK_XXX flags.
+ */
+VMMDECL(int) PGMShwMakePageWritable(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
+{
+    return pdmShwModifyPage(pVCpu, GCPtr, X86_PTE_RW, ~(uint64_t)0, fOpFlags);
+}
+
+
+/**
+ * Changing the page flags for a single page in the shadow page tables so as to
+ * make it not present.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       VMCPU handle.
+ * @param   GCPtr       Virtual address of the first page in the range.
+ * @param   fOpFlags    A combination of the PGM_MK_PG_XXX flags.
+ */
+VMMDECL(int) PGMShwMakePageNotPresent(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fOpFlags)
+{
+    return pdmShwModifyPage(pVCpu, GCPtr, 0, 0, fOpFlags);
+}
+
 
 /**
@@ -2156,4 +2183,39 @@
 #if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
 
+/** Common worker for PGMDynMapGCPage and PGMDynMapGCPageOff. */
+DECLINLINE(int) pgmDynMapGCPageInternal(PVM pVM, RTGCPHYS GCPhys, void **ppv)
+{
+    pgmLock(pVM);
+
+    /*
+     * Convert it to a writable page and it on to PGMDynMapHCPage.
+     */
+    int rc;
+    PPGMPAGE pPage = pgmPhysGetPage(&pVM->pgm.s, GCPhys);
+    if (RT_LIKELY(pPage))
+    {
+        rc = pgmPhysPageMakeWritable(pVM, pPage, GCPhys);
+        if (RT_SUCCESS(rc))
+        {
+            //Log(("PGMDynMapGCPage: GCPhys=%RGp pPage=%R[pgmpage]\n", GCPhys, pPage));
+#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
+            rc = pgmR0DynMapHCPageInlined(&pVM->pgm.s, PGM_PAGE_GET_HCPHYS(pPage), ppv);
+#else
+            rc = PGMDynMapHCPage(pVM, PGM_PAGE_GET_HCPHYS(pPage), ppv);
+#endif
+        }
+        else
+            AssertRC(rc);
+    }
+    else
+    {
+        AssertMsgFailed(("Invalid physical address %RGp!\n", GCPhys));
+        rc = VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
+    }
+
+    pgmUnlock(pVM);
+    return rc;
+}
+
 /**
  * Temporarily maps one guest page specified by GC physical address.
@@ -2171,28 +2233,5 @@
 {
     AssertMsg(!(GCPhys & PAGE_OFFSET_MASK), ("GCPhys=%RGp\n", GCPhys));
-
-    /*
-     * Get the ram range.
-     */
-    PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
-    while (pRam && GCPhys - pRam->GCPhys >= pRam->cb)
-        pRam = pRam->CTX_SUFF(pNext);
-    if (!pRam)
-    {
-        AssertMsgFailed(("Invalid physical address %RGp!\n", GCPhys));
-        return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
-    }
-
-    /*
-     * Pass it on to PGMDynMapHCPage.
-     */
-    RTHCPHYS HCPhys = PGM_PAGE_GET_HCPHYS(&pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT]);
-    //Log(("PGMDynMapGCPage: GCPhys=%RGp HCPhys=%RHp\n", GCPhys, HCPhys));
-#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
-    pgmR0DynMapHCPageInlined(&pVM->pgm.s, HCPhys, ppv);
-#else
-    PGMDynMapHCPage(pVM, HCPhys, ppv);
-#endif
-    return VINF_SUCCESS;
+    return pgmDynMapGCPageInternal(pVM, GCPhys, ppv);
 }
 
@@ -2215,27 +2254,12 @@
 VMMDECL(int) PGMDynMapGCPageOff(PVM pVM, RTGCPHYS GCPhys, void **ppv)
 {
-    /*
-     * Get the ram range.
-     */
-    PPGMRAMRANGE pRam = pVM->pgm.s.CTX_SUFF(pRamRanges);
-    while (pRam && GCPhys - pRam->GCPhys >= pRam->cb)
-        pRam = pRam->CTX_SUFF(pNext);
-    if (!pRam)
-    {
-        AssertMsgFailed(("Invalid physical address %RGp!\n", GCPhys));
-        return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
-    }
-
-    /*
-     * Pass it on to PGMDynMapHCPage.
-     */
-    RTHCPHYS HCPhys = PGM_PAGE_GET_HCPHYS(&pRam->aPages[(GCPhys - pRam->GCPhys) >> PAGE_SHIFT]);
-#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
-    pgmR0DynMapHCPageInlined(&pVM->pgm.s, HCPhys, ppv);
-#else
-    PGMDynMapHCPage(pVM, HCPhys, ppv);
-#endif
-    *ppv = (void *)((uintptr_t)*ppv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
-    return VINF_SUCCESS;
+    void *pv;
+    int rc = pgmDynMapGCPageInternal(pVM, GCPhys, &pv);
+    if (RT_SUCCESS(rc))
+    {
+        *ppv = (void *)((uintptr_t)pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
+        return VINF_SUCCESS;
+    }
+    return rc;
 }
 
@@ -2381,5 +2405,5 @@
 VMMDECL(void) PGMDynCheckLocks(PVM pVM)
 {
-    for (unsigned i=0;i<RT_ELEMENTS(pVM->pgm.s.aLockedDynPageMapCache);i++)
+    for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.aLockedDynPageMapCache); i++)
         Assert(!pVM->pgm.s.aLockedDynPageMapCache[i]);
 }
@@ -2394,7 +2418,7 @@
  * @copydoc FNRTSTRFORMATTYPE */
 static DECLCALLBACK(size_t) pgmFormatTypeHandlerPage(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput,
-                                                    const char *pszType, void const *pvValue,
-                                                    int cchWidth, int cchPrecision, unsigned fFlags,
-                                                    void *pvUser)
+                                                     const char *pszType, void const *pvValue,
+                                                     int cchWidth, int cchPrecision, unsigned fFlags,
+                                                     void *pvUser)
 {
     size_t    cch;
@@ -2490,5 +2514,4 @@
 
 #endif /* !IN_R0 || LOG_ENABLED */
-
 
 /**
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp	(revision 30325)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp	(revision 30326)
@@ -1332,5 +1332,5 @@
             if (rc == VINF_SUCCESS)
             {
-                rc = PGMShwModifyPage(pVCpu, pvFault, 1, X86_PTE_RW, ~(uint64_t)X86_PTE_RW);
+                rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
                 AssertMsg(rc == VINF_SUCCESS
                         /* In the SMP case the page table might be removed while we wait for the PGM lock in the trap handler. */
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllShw.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllShw.h	(revision 30325)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllShw.h	(revision 30326)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -118,5 +118,5 @@
 RT_C_DECLS_BEGIN
 PGM_SHW_DECL(int, GetPage)(PVMCPU pVCpu, RTGCUINTPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys);
-PGM_SHW_DECL(int, ModifyPage)(PVMCPU pVCpu, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask);
+PGM_SHW_DECL(int, ModifyPage)(PVMCPU pVCpu, RTGCUINTPTR GCPtr, size_t cbPages, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags);
 RT_C_DECLS_END
 
@@ -272,7 +272,8 @@
  * @param   fMask       The AND mask - page flags X86_PTE_*.
  *                      Be extremely CAREFUL with ~'ing values because they can be 32-bit!
+ * @param   fOpFlags    A combination of the PGM_MK_PK_XXX flags.
  * @remark  You must use PGMMapModifyPage() for pages in a mapping.
  */
-PGM_SHW_DECL(int, ModifyPage)(PVMCPU pVCpu, RTGCUINTPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask)
+PGM_SHW_DECL(int, ModifyPage)(PVMCPU pVCpu, RTGCUINTPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask, uint32_t fOpFlags)
 {
 # if PGM_SHW_TYPE == PGM_TYPE_NESTED
@@ -353,9 +354,42 @@
             if (pPT->a[iPTE].n.u1Present)
             {
-                SHWPTE Pte;
-
-                Pte.u = (pPT->a[iPTE].u & (fMask | SHW_PTE_PG_MASK)) | (fFlags & ~SHW_PTE_PG_MASK);
-                ASMAtomicWriteSize(&pPT->a[iPTE], Pte.u);
-                Assert(pPT->a[iPTE].n.u1Present);
+                SHWPTE const    OrgPte = pPT->a[iPTE];
+                SHWPTE          NewPte;
+
+                NewPte.u = (OrgPte.u & (fMask | SHW_PTE_PG_MASK)) | (fFlags & ~SHW_PTE_PG_MASK);
+                Assert(NewPte.n.u1Present);
+                if (!NewPte.n.u1Present)
+                {
+                    /** @todo Some CSAM code path might end up here and upset
+                     *  the page pool. */
+                    AssertFailed();
+                }
+                else if (   NewPte.n.u1Write
+                         && !OrgPte.n.u1Write
+                         && !(fOpFlags & PGM_MK_PG_IS_MMIO2) )
+                {
+                    /** @todo Optimize \#PF handling by caching data.  We can
+                     *        then use this when PGM_MK_PG_IS_WRITE_FAULT is
+                     *        set instead of resolving the guest physical
+                     *        address yet again. */
+                    RTGCPHYS GCPhys;
+                    uint64_t fGstPte;
+                    rc = PGMGstGetPage(pVCpu, GCPtr, &fGstPte, &GCPhys);
+                    AssertRC(rc);
+                    if (RT_SUCCESS(rc))
+                    {
+                        Assert(fGstPte & X86_PTE_RW);
+                        PPGMPAGE pPage = pgmPhysGetPage(&pVCpu->CTX_SUFF(pVM)->pgm.s, GCPhys);
+                        Assert(pPage);
+                        if (pPage)
+                        {
+                            rc = pgmPhysPageMakeWritable(pVM, pPage, GCPhys);
+                            AssertRCReturn(rc, rc);
+                            Log(("%s: pgmPhysPageMakeWritable on %RGv / %RGp %R[pgmpage]\n", __PRETTY_FUNCTION__, GCPtr, GCPhys, pPage));
+                        }
+                    }
+                }
+
+                ASMAtomicWriteSize(&pPT->a[iPTE], NewPte.u);
 # if PGM_SHW_TYPE == PGM_TYPE_EPT
                 HWACCMInvalidatePhysPage(pVM, (RTGCPHYS)GCPtr);
Index: /trunk/src/VBox/VMM/VMMGC/VMMGC.def
===================================================================
--- /trunk/src/VBox/VMM/VMMGC/VMMGC.def	(revision 30325)
+++ /trunk/src/VBox/VMM/VMMGC/VMMGC.def	(revision 30326)
@@ -29,5 +29,5 @@
     PDMQueueInsert
     PGMHandlerPhysicalPageTempOff
-    PGMShwModifyPage
+    PGMShwMakePageWritable
     PGMPhysSimpleWriteGCPhys
     PGMPhysSimpleReadGCPtr
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.def
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.def	(revision 30325)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.def	(revision 30326)
@@ -29,5 +29,5 @@
     PDMQueueInsert
     PGMHandlerPhysicalPageTempOff
-    PGMShwModifyPage
+    PGMShwMakePageWritable
     PGMPhysSimpleWriteGCPhys
     PGMPhysSimpleReadGCPtr
