Index: /trunk/include/VBox/vmm/patm.h
===================================================================
--- /trunk/include/VBox/vmm/patm.h	(revision 55936)
+++ /trunk/include/VBox/vmm/patm.h	(revision 55937)
@@ -165,7 +165,7 @@
  */
 
-VMMRC_INT_DECL(int)     PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
-VMMRC_INT_DECL(int)     PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite);
-VMMRC_INT_DECL(int)     PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
+VMMRC_INT_DECL(int)             PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
+VMMRC_INT_DECL(VBOXSTRICTRC)    PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite);
+VMMRC_INT_DECL(int)             PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
 
 /** @} */
Index: /trunk/src/VBox/VMM/VMMAll/CSAMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/CSAMAll.cpp	(revision 55936)
+++ /trunk/src/VBox/VMM/VMMAll/CSAMAll.cpp	(revision 55937)
@@ -29,4 +29,7 @@
 #include <VBox/vmm/hm.h>
 #include <VBox/vmm/mm.h>
+#ifdef VBOX_WITH_REM
+# include <VBox/vmm/rem.h>
+#endif
 #include <VBox/sup.h>
 #include <VBox/vmm/mm.h>
@@ -45,4 +48,125 @@
 #include <iprt/string.h>
 
+#ifdef IN_RING0
+# error "IN_RING3 & IN_RC only!"
+#endif
+
+
+/**
+ * Access handler callback for virtual access handler ranges.
+ *
+ * Important to realize that a physical page in a range can have aliases, and
+ * for ALL and WRITE handlers these will also trigger.
+ *
+ * @returns VINF_SUCCESS if the handler have carried out the operation.
+ * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
+ * @param   pVM             Pointer to the VM.
+ * @param   pVCpu       Pointer to the cross context CPU context for the
+ *                      calling EMT.
+ * @param   GCPtr           The virtual address the guest is writing to. (not correct if it's an alias!)
+ * @param   pvPtr           The HC mapping of that address.
+ * @param   pvBuf           What the guest is reading/writing.
+ * @param   cbBuf           How much it's reading/writing.
+ * @param   enmAccessType   The access type.
+ * @param   enmOrigin       Who is making this write.
+ * @param   pvUser          User argument.
+ */
+PGM_ALL_CB2_DECL(int) csamCodePageWriteHandler(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf,
+                                               PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
+{
+    RTGCPTR const GCPtrMonitored = (uintptr_t)pvUser | (GCPtr & PAGE_OFFSET_MASK);
+    Log(("csamCodePageWriteHandler: write to %RGv LB %zu\n", GCPtr, cbBuf));
+
+    Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType);
+    Assert(VMCPU_IS_EMT(pVCpu));
+
+    /*
+     * Check if it's a dummy write that doesn't change anything.
+     */
+    if (   PAGE_ADDRESS(pvPtr) == PAGE_ADDRESS((uintptr_t)pvPtr + cbBuf - 1)
+        && !memcmp(pvPtr, pvBuf, cbBuf))
+    {
+        Log(("csamCodePageWriteHandler: dummy write -> ignore\n"));
+        return VINF_PGM_HANDLER_DO_DEFAULT;
+    }
+
+#ifdef IN_RING3
+    /*
+     * Ring-3: Do proper handling.
+     */
+    int rc = PATMR3PatchWrite(pVM, GCPtrMonitored, (uint32_t)cbBuf);
+    AssertRC(rc);
+    return VINF_PGM_HANDLER_DO_DEFAULT;
+
+#else
+    /*
+     * Raw-mode: Try avoid needing to go to ring-3 (same as csamRCCodePageWritePfHandler).
+     */
+    uint32_t     const cpl            = CPUMGetGuestCPL(pVCpu);
+    bool         const fPatchCode     = PATMIsPatchGCAddr(pVM, CPUMGetGuestRIP(pVCpu));
+    PPATMGCSTATE       pPATMGCState   = PATMGetGCState(pVM);
+
+    Assert(pVM->csam.s.cDirtyPages < CSAM_MAX_DIRTY_PAGES);
+    Assert(pPATMGCState);
+    Assert(pPATMGCState->fPIF || fPatchCode);
+
+# ifdef VBOX_WITH_REM
+    /* Flush the recompilers translation block cache as the guest seems to be modifying instructions. */
+    /** @todo a bit overkill?? */
+    REMFlushTBs(pVM);
+# endif
+
+    /*
+     * When patch code is executing instructions that must complete, then we
+     * must *never* interrupt it.
+     */
+    if (!pPATMGCState->fPIF && fPatchCode)
+    {
+        Log(("csamRCCodePageWriteHandler: fPIF=0 -> stack fault in patch generated code at %08RX32!\n", CPUMGetGuestRIP(pVCpu)));
+        return VINF_PGM_HANDLER_DO_DEFAULT;
+    }
+
+    Log(("csamRCCodePageWriteHandler: code page write at %RGv original address %RGv (cpl=%d)\n", GCPtr, GCPtrMonitored, cpl));
+
+    /*
+     * If user code is modifying one of our monitored pages, then we can safely
+     * write to it as it's no longer being used for supervisor code.
+     */
+    if (cpl != 3)
+    {
+        VBOXSTRICTRC rcStrict = PATMRCHandleWriteToPatchPage(pVM, NULL /* pRegFrame = no interpret */,
+                                                             (RTRCPTR)GCPtrMonitored, cbBuf);
+        if (   rcStrict == VINF_PGM_HANDLER_DO_DEFAULT
+            || rcStrict == VINF_SUCCESS)
+            return VBOXSTRICTRC_TODO(rcStrict);
+        if (rcStrict == VINF_EM_RAW_EMULATE_INSTR)
+        {
+            STAM_COUNTER_INC(&pVM->csam.s.StatDangerousWrite);
+            return VINF_EM_RAW_EMULATE_INSTR;
+        }
+        Assert(rcStrict == VERR_PATCH_NOT_FOUND);
+    }
+
+    /*
+     * Schedule ring-3 activity.
+     * Note that GCPtr might be a different address in case of aliases.  So,
+     * take down both alternatives.
+     */
+    VMCPU_FF_SET(pVCpu, VMCPU_FF_CSAM_PENDING_ACTION);
+    pVM->csam.s.pvDirtyBasePage[pVM->csam.s.cDirtyPages]  = (RTRCPTR)GCPtrMonitored;
+    pVM->csam.s.pvDirtyFaultPage[pVM->csam.s.cDirtyPages] = (RTRCPTR)GCPtr;
+    if (++pVM->csam.s.cDirtyPages == CSAM_MAX_DIRTY_PAGES)
+        return VINF_CSAM_PENDING_ACTION;
+
+    /*
+     * Continue with the write. The VM_FF_CSAM_FLUSH_DIRTY_PAGE handler will reset it to readonly again.
+     */
+    Log(("csamRCCodePageWriteHandler: enabled r/w for page %RGv (%RGv)\n", GCPtr, GCPtrMonitored));
+    STAM_COUNTER_INC(&pVM->csam.s.StatCodePageModified);
+    return VINF_PGM_HANDLER_DO_DEFAULT;
+#endif
+}
+
+
 /**
  * Check if this page needs to be analysed by CSAM
Index: /trunk/src/VBox/VMM/VMMAll/PATMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PATMAll.cpp	(revision 55936)
+++ /trunk/src/VBox/VMM/VMMAll/PATMAll.cpp	(revision 55937)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2013 Oracle Corporation
+ * Copyright (C) 2006-2015 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -37,4 +37,41 @@
 #include <iprt/assert.h>
 #include <iprt/string.h>
+
+
+/**
+ * Access handler callback for virtual access handler ranges.
+ *
+ * Important to realize that a physical page in a range can have aliases, and
+ * for ALL and WRITE handlers these will also trigger.
+ *
+ * @returns VINF_SUCCESS if the handler have carried out the operation.
+ * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
+ * @param   pVM             Pointer to the VM.
+ * @param   pVCpu           Pointer to the cross context CPU context for the
+ *                          calling EMT.
+ * @param   GCPtr           The virtual address the guest is writing to. (not correct if it's an alias!)
+ * @param   pvPtr           The HC mapping of that address.
+ * @param   pvBuf           What the guest is reading/writing.
+ * @param   cbBuf           How much it's reading/writing.
+ * @param   enmAccessType   The access type.
+ * @param   enmOrigin       Who is making this write.
+ * @param   pvUser          The address of the guest page we're monitoring.
+ */
+PGM_ALL_CB2_DECL(int) patmVirtPageHandler(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf,
+                                          PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
+{
+    Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType);
+    NOREF(pvPtr); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(pvUser);
+    Assert(pvUser); Assert(!((uintptr_t)pvUser & PAGE_OFFSET_MASK));
+
+    pVM->patm.s.pvFaultMonitor = (RTRCPTR)((uintptr_t)pvUser + (GCPtr & PAGE_OFFSET_MASK));
+#ifdef IN_RING3
+    PATMR3HandleMonitoredPage(pVM);
+    return VINF_PGM_HANDLER_DO_DEFAULT;
+#else
+    /* RC: Go handle this in ring-3. */
+    return VINF_PATM_CHECK_PATCH_PAGE;
+#endif
+}
 
 
Index: /trunk/src/VBox/VMM/VMMR3/CSAM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CSAM.cpp	(revision 55936)
+++ /trunk/src/VBox/VMM/VMMR3/CSAM.cpp	(revision 55937)
@@ -72,5 +72,4 @@
 static DECLCALLBACK(int) csamR3Save(PVM pVM, PSSMHANDLE pSSM);
 static DECLCALLBACK(int) csamR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
-static FNPGMR3VIRTHANDLER    csamR3CodePageWriteHandler;
 static FNPGMR3VIRTINVALIDATE csamR3CodePageInvalidate;
 
@@ -255,5 +254,5 @@
     rc = PGMR3HandlerVirtualTypeRegister(pVM, PGMVIRTHANDLERKIND_WRITE, false /*fRelocUserRC*/,
                                          NULL /*pfnInvalidateR3 */,
-                                         csamR3CodePageWriteHandler,
+                                         csamCodePageWriteHandler,
                                          "csamRCCodePageWritePfHandler",
                                          "CSAM code page write handler",
@@ -262,5 +261,5 @@
     rc = PGMR3HandlerVirtualTypeRegister(pVM, PGMVIRTHANDLERKIND_WRITE, false /*fRelocUserRC*/,
                                          csamR3CodePageInvalidate,
-                                         csamR3CodePageWriteHandler,
+                                         csamCodePageWriteHandler,
                                          "csamRCCodePageWritePfHandler",
                                          "CSAM code page write and invlpg handler",
@@ -2164,57 +2163,4 @@
 
 /**
- * \#PF Handler callback for virtual access handler ranges.
- *
- * Important to realize that a physical page in a range can have aliases, and
- * for ALL and WRITE handlers these will also trigger.
- *
- * @returns VINF_SUCCESS if the handler have carried out the operation.
- * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
- * @param   pVM             Pointer to the VM.
- * @param   pVCpu       Pointer to the cross context CPU context for the
- *                      calling EMT.
- * @param   GCPtr           The virtual address the guest is writing to. (not correct if it's an alias!)
- * @param   pvPtr           The HC mapping of that address.
- * @param   pvBuf           What the guest is reading/writing.
- * @param   cbBuf           How much it's reading/writing.
- * @param   enmAccessType   The access type.
- * @param   enmOrigin       Who is making this write.
- * @param   pvUser          User argument.
- */
-static DECLCALLBACK(int) csamR3CodePageWriteHandler(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf,
-                                                    PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
-{
-    int rc;
-
-    Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType);
-    Log(("csamR3CodePageWriteHandler: write to %RGv size=%zu\n", GCPtr, cbBuf));
-    NOREF(pvUser);
-
-    if (    PAGE_ADDRESS(pvPtr) == PAGE_ADDRESS((uintptr_t)pvPtr + cbBuf - 1)
-         && !memcmp(pvPtr, pvBuf, cbBuf))
-    {
-        Log(("csamR3CodePageWriteHandler: dummy write -> ignore\n"));
-        return VINF_PGM_HANDLER_DO_DEFAULT;
-    }
-
-    if (VM_IS_EMT(pVM))
-        rc = PATMR3PatchWrite(pVM, GCPtr, (uint32_t)cbBuf);
-    else
-    {
-        AssertFailed(); /* PGM should make sure this does not happen anymore! */
-        /* Queue the write instead otherwise we'll get concurrency issues. */
-        /** @note in theory not correct to let it write the data first before disabling a patch!
-         *        (if it writes the same data as the patch jump and we replace it with obsolete opcodes)
-         */
-        Log(("csamR3CodePageWriteHandler: delayed write!\n"));
-        AssertCompileSize(RTRCPTR, 4);
-        rc = VMR3ReqCallVoidNoWait(pVM, VMCPUID_ANY, (PFNRT)CSAMDelayedWriteHandler, 3, pVM, (RTRCPTR)GCPtr, cbBuf);
-    }
-    AssertRC(rc);
-
-    return VINF_PGM_HANDLER_DO_DEFAULT;
-}
-
-/**
  * \#PF Handler callback for invalidation of virtual access handler ranges.
  *
@@ -2435,15 +2381,15 @@
     STAM_PROFILE_START(&pVM->csam.s.StatFlushDirtyPages, a);
 
-    for (uint32_t i=0;i<pVM->csam.s.cDirtyPages;i++)
+    for (uint32_t i = 0; i < pVM->csam.s.cDirtyPages; i++)
     {
         int          rc;
         PCSAMPAGEREC pPageRec;
-        RTRCPTR      GCPtr = pVM->csam.s.pvDirtyBasePage[i];
-
-        GCPtr = GCPtr & PAGE_BASE_GC_MASK;
+        RTRCPTR      GCPtr = pVM->csam.s.pvDirtyBasePage[i] & PAGE_BASE_GC_MASK;
 
 #ifdef VBOX_WITH_REM
          /* Notify the recompiler that this page has been changed. */
         REMR3NotifyCodePageChanged(pVM, pVCpu, GCPtr);
+        if (pVM->csam.s.pvDirtyFaultPage[i] != pVM->csam.s.pvDirtyBasePage[i])
+            REMR3NotifyCodePageChanged(pVM, pVCpu, pVM->csam.s.pvDirtyFaultPage[i] & PAGE_BASE_GC_MASK);
 #endif
 
Index: /trunk/src/VBox/VMM/VMMR3/PATM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/PATM.cpp	(revision 55936)
+++ /trunk/src/VBox/VMM/VMMR3/PATM.cpp	(revision 55937)
@@ -92,6 +92,4 @@
 *   Internal Functions                                                         *
 *******************************************************************************/
-static FNPGMR3VIRTHANDLER patmR3VirtPageHandler;
-
 static int          patmDisableUnusablePatch(PVM pVM, RTRCPTR pInstrGC, RTRCPTR pConflictAddr, PPATCHINFO pPatch);
 static int          patmActivateInt3Patch(PVM pVM, PPATCHINFO pPatch);
@@ -224,5 +222,5 @@
     rc = PGMR3HandlerVirtualTypeRegister(pVM, PGMVIRTHANDLERKIND_ALL, false /*fRelocUserRC*/,
                                          NULL /*pfnInvalidateR3*/,
-                                         patmR3VirtPageHandler,
+                                         patmVirtPageHandler,
                                          "patmRCVirtPagePfHandler",
                                          "PATMMonitorPatchJump", &pVM->patm.s.hMonitorPageType);
@@ -975,35 +973,4 @@
 }
 
-/**
- * \#PF Handler callback for virtual access handler ranges.
- *
- * Important to realize that a physical page in a range can have aliases, and
- * for ALL and WRITE handlers these will also trigger.
- *
- * @returns VINF_SUCCESS if the handler have carried out the operation.
- * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
- * @param   pVM             Pointer to the VM.
- * @param   pVCpu           Pointer to the cross context CPU context for the
- *                          calling EMT.
- * @param   GCPtr           The virtual address the guest is writing to. (not correct if it's an alias!)
- * @param   pvPtr           The HC mapping of that address.
- * @param   pvBuf           What the guest is reading/writing.
- * @param   cbBuf           How much it's reading/writing.
- * @param   enmAccessType   The access type.
- * @param   enmOrigin       Who is making this write.
- * @param   pvUser          The address of the guest page we're monitoring.
- */
-static DECLCALLBACK(int) patmR3VirtPageHandler(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf,
-                                               PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
-{
-    Assert(enmAccessType == PGMACCESSTYPE_WRITE); NOREF(enmAccessType);
-    NOREF(pVCpu); NOREF(pvPtr); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(pvUser);
-
-    /** @todo could be the wrong virtual address (alias) */
-    pVM->patm.s.pvFaultMonitor = GCPtr;
-    PATMR3HandleMonitoredPage(pVM);
-    return VINF_PGM_HANDLER_DO_DEFAULT;
-}
-
 #ifdef VBOX_WITH_DEBUGGER
 
Index: /trunk/src/VBox/VMM/VMMRC/CSAMRC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/CSAMRC.cpp	(revision 55936)
+++ /trunk/src/VBox/VMM/VMMRC/CSAMRC.cpp	(revision 55937)
@@ -72,5 +72,4 @@
     PPATMGCSTATE pPATMGCState;
     bool         fPatchCode = PATMIsPatchGCAddr(pVM, pRegFrame->eip);
-    int          rc;
     NOREF(uErrorCode);
 
@@ -96,5 +95,5 @@
          * Make this particular page R/W.
          */
-        rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
+        int rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
         AssertMsgRC(rc, ("PGMShwModifyPage -> rc=%Rrc\n", rc));
         ASMInvalidatePage((void *)(uintptr_t)pvFault);
@@ -114,13 +113,14 @@
     if (cpl != 3)
     {
-        rc = PATMRCHandleWriteToPatchPage(pVM, pRegFrame, (RTRCPTR)((RTRCUINTPTR)pvRange + offRange), 4 /** @todo */);
-        if (rc == VINF_SUCCESS)
-            return rc;
-        if (rc == VINF_EM_RAW_EMULATE_INSTR)
+        VBOXSTRICTRC rcStrict = PATMRCHandleWriteToPatchPage(pVM, pRegFrame, (RTRCPTR)((RTRCUINTPTR)pvRange + offRange),
+                                                             4 /** @todo */);
+        if (rcStrict == VINF_SUCCESS)
+            return rcStrict;
+        if (rcStrict == VINF_EM_RAW_EMULATE_INSTR)
         {
             STAM_COUNTER_INC(&pVM->csam.s.StatDangerousWrite);
             return VINF_EM_RAW_EMULATE_INSTR;
         }
-        Assert(rc == VERR_PATCH_NOT_FOUND);
+        Assert(rcStrict == VERR_PATCH_NOT_FOUND);
     }
 
@@ -129,5 +129,5 @@
     /* Note that pvFault might be a different address in case of aliases. So use pvRange + offset instead!. */
     pVM->csam.s.pvDirtyBasePage[pVM->csam.s.cDirtyPages] = (RTRCPTR)((RTRCUINTPTR)pvRange + offRange);
-    pVM->csam.s.pvDirtyFaultPage[pVM->csam.s.cDirtyPages] = (RTRCPTR)((RTRCUINTPTR)pvRange + offRange);
+    pVM->csam.s.pvDirtyFaultPage[pVM->csam.s.cDirtyPages] = (RTRCPTR)pvFault;
     if (++pVM->csam.s.cDirtyPages == CSAM_MAX_DIRTY_PAGES)
         return VINF_CSAM_PENDING_ACTION;
@@ -137,5 +137,5 @@
      */
     Log(("csamRCCodePageWriteHandler: enabled r/w for page %RGv\n", pvFault));
-    rc = PGMShwMakePageWritable(pVCpu, pvFault, PGM_MK_PG_IS_WRITE_FAULT);
+    int 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/VMMRC/PATMRC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/PATMRC.cpp	(revision 55936)
+++ /trunk/src/VBox/VMM/VMMRC/PATMRC.cpp	(revision 55937)
@@ -63,6 +63,7 @@
                                         RTGCPTR pvRange, uintptr_t offRange, void *pvUser)
 {
-    NOREF(pVCpu); NOREF(uErrorCode); NOREF(pRegFrame); NOREF(pvFault); NOREF(pvRange); NOREF(offRange); NOREF(pvUser);
-    pVM->patm.s.pvFaultMonitor = (RTRCPTR)(RTRCUINTPTR)pvFault;
+    NOREF(pVCpu); NOREF(uErrorCode); NOREF(pRegFrame); NOREF(pvFault); NOREF(pvRange); NOREF(offRange);
+    Assert(pvUser); Assert(!((uintptr_t)pvUser & PAGE_OFFSET_MASK));
+    pVM->patm.s.pvFaultMonitor = (RTRCPTR)((uintptr_t)pvUser + (pvFault & PAGE_OFFSET_MASK));
     return VINF_PATM_CHECK_PATCH_PAGE;
 }
@@ -73,46 +74,53 @@
  * (if so, then we are not allowed to turn on r/w)
  *
- * @returns VBox status
+ * @returns Strict VBox status code.
+ * @retval  VINF_SUCCESS if access interpreted (@a pRegFrame != NULL).
+ * @retval  VINF_PGM_HANDLER_DO_DEFAULT (@a pRegFrame == NULL).
+ * @retval  VINF_EM_RAW_EMULATE_INSTR on needing to go to ring-3 to do this.
+ * @retval  VERR_PATCH_NOT_FOUND if no patch was found.
+ *
  * @param   pVM         Pointer to the VM.
- * @param   pRegFrame   CPU context
- * @param   GCPtr       GC pointer to write address
- * @param   cbWrite     Nr of bytes to write
+ * @param   pRegFrame   CPU context if \#PF, NULL if other write..
+ * @param   GCPtr       GC pointer to write address.
+ * @param   cbWrite     Number of bytes to write.
  *
  */
-VMMRC_INT_DECL(int) PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite)
+VMMRC_INT_DECL(VBOXSTRICTRC) PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite)
 {
-    RTGCUINTPTR          pWritePageStart, pWritePageEnd;
-    PPATMPATCHPAGE       pPatchPage;
+    Assert(cbWrite > 0);
 
     /* Quick boundary check */
-    if (    PAGE_ADDRESS(GCPtr) < PAGE_ADDRESS(pVM->patm.s.pPatchedInstrGCLowest)
-        ||  PAGE_ADDRESS(GCPtr) > PAGE_ADDRESS(pVM->patm.s.pPatchedInstrGCHighest)
-       )
-       return VERR_PATCH_NOT_FOUND;
+    if (   PAGE_ADDRESS(GCPtr) < PAGE_ADDRESS(pVM->patm.s.pPatchedInstrGCLowest)
+        || PAGE_ADDRESS(GCPtr) > PAGE_ADDRESS(pVM->patm.s.pPatchedInstrGCHighest))
+        return VERR_PATCH_NOT_FOUND;
 
     STAM_PROFILE_ADV_START(&pVM->patm.s.StatPatchWriteDetect, a);
 
-    pWritePageStart = (RTRCUINTPTR)GCPtr & PAGE_BASE_GC_MASK;
-    pWritePageEnd   = ((RTRCUINTPTR)GCPtr + cbWrite - 1) & PAGE_BASE_GC_MASK;
-
-    pPatchPage = (PPATMPATCHPAGE)RTAvloU32Get(CTXSUFF(&pVM->patm.s.PatchLookupTree)->PatchTreeByPage, (AVLOU32KEY)pWritePageStart);
+    /*
+     * Lookup the patch page record for the write.
+     */
+    RTRCUINTPTR pWritePageStart = (RTRCUINTPTR)GCPtr & PAGE_BASE_GC_MASK;
+    RTRCUINTPTR pWritePageEnd   = ((RTRCUINTPTR)GCPtr + cbWrite - 1) & PAGE_BASE_GC_MASK;
+
+    PPATMPATCHPAGE pPatchPage;
+    pPatchPage = (PPATMPATCHPAGE)RTAvloU32Get(&pVM->patm.s.CTXSUFF(PatchLookupTree)->PatchTreeByPage, pWritePageStart);
     if (    !pPatchPage
-        &&  pWritePageStart != pWritePageEnd
-       )
-    {
-        pPatchPage = (PPATMPATCHPAGE)RTAvloU32Get(CTXSUFF(&pVM->patm.s.PatchLookupTree)->PatchTreeByPage, (AVLOU32KEY)pWritePageEnd);
-    }
-
-#ifdef LOG_ENABLED
-    if (pPatchPage)
-        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
-
+        &&  pWritePageStart != pWritePageEnd)
+        pPatchPage = (PPATMPATCHPAGE)RTAvloU32Get(&pVM->patm.s.CTXSUFF(PatchLookupTree)->PatchTreeByPage, pWritePageEnd);
     if (pPatchPage)
     {
-        if (    pPatchPage->pLowestAddrGC  > (RTRCPTR)((RTRCUINTPTR)GCPtr + cbWrite - 1)
-            ||  pPatchPage->pHighestAddrGC < (RTRCPTR)GCPtr)
+        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));
+        if (   (RTRCUINTPTR)pPatchPage->pLowestAddrGC  > (RTRCUINTPTR)GCPtr + cbWrite - 1U
+            || (RTRCUINTPTR)pPatchPage->pHighestAddrGC < (RTRCUINTPTR)GCPtr)
         {
-            /* This part of the page was not patched; try to emulate the instruction. */
+            /* This part of the page was not patched; try to emulate the instruction / tell the caller to do so. */
+            if (!pRegFrame)
+            {
+                LogFlow(("PATMHandleWriteToPatchPage: Allow writing %RRv LB %#x\n", pRegFrame->eip, GCPtr, cbWrite));
+                STAM_COUNTER_INC(&pVM->patm.s.StatPatchWriteInterpreted);
+                STAM_PROFILE_ADV_STOP(&pVM->patm.s.StatPatchWriteDetect, a);
+                return VINF_PGM_HANDLER_DO_DEFAULT;
+            }
             LogFlow(("PATMHandleWriteToPatchPage: Interpret %x accessing %RRv\n", pRegFrame->eip, GCPtr));
             int rc = EMInterpretInstruction(VMMGetCpu0(pVM), pRegFrame, (RTGCPTR)(RTRCUINTPTR)GCPtr);
Index: /trunk/src/VBox/VMM/include/CSAMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/CSAMInternal.h	(revision 55936)
+++ /trunk/src/VBox/VMM/include/CSAMInternal.h	(revision 55937)
@@ -283,6 +283,7 @@
 
 RT_C_DECLS_BEGIN
-DECLEXPORT(FNPGMRCVIRTPFHANDLER) csamRCCodePageWritePfHandler;
+DECLEXPORT(FNPGMRCVIRTPFHANDLER)    csamRCCodePageWritePfHandler;
 RT_C_DECLS_END
-
-#endif
+PGM_ALL_CB2_DECL(FNPGMR3VIRTHANDLER)  csamCodePageWriteHandler;
+
+#endif
Index: /trunk/src/VBox/VMM/include/PATMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/PATMInternal.h	(revision 55936)
+++ /trunk/src/VBox/VMM/include/PATMInternal.h	(revision 55937)
@@ -687,3 +687,5 @@
 void patmR3DbgAddPatch(PVM pVM, PPATMPATCHREC pPatchRec);
 
-#endif
+PGM_ALL_CB2_DECL(FNPGMPHYSHANDLER) patmVirtPageHandler;
+
+#endif
