Index: /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 42192)
+++ /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 42193)
@@ -78,6 +78,5 @@
 
 
-#if defined(VBOX_WITH_RAW_MODE) && !defined(IN_RING0)
-
+#ifdef VBOX_WITH_RAW_MODE_NOT_R0
 
 /**
@@ -156,5 +155,5 @@
 }
 
-#endif
+#endif /* VBOX_WITH_RAW_MODE_NOT_R0 */
 
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 42192)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 42193)
@@ -77,4 +77,5 @@
 #define LOG_GROUP   LOG_GROUP_IEM
 #include <VBox/vmm/iem.h>
+#include <VBox/vmm/cpum.h>
 #include <VBox/vmm/pgm.h>
 #include <internal/pgm.h>
@@ -83,4 +84,7 @@
 #include <VBox/vmm/tm.h>
 #include <VBox/vmm/dbgf.h>
+#ifdef VBOX_WITH_RAW_MODE_NOT_R0
+# include <VBox/vmm/patm.h>
+#endif
 #ifdef IEM_VERIFICATION_MODE
 # include <VBox/vmm/rem.h>
@@ -629,5 +633,7 @@
     PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
 
+#ifdef VBOX_WITH_RAW_MODE_NOT_R0
     CPUMGuestLazyLoadHiddenCsAndSs(IEMCPU_TO_VMCPU(pIemCpu));
+#endif
     pIemCpu->uCpl               = CPUMGetGuestCPL(IEMCPU_TO_VMCPU(pIemCpu));
     IEMMODE enmMode = CPUMIsGuestIn64BitCodeEx(pCtx)
@@ -697,4 +703,20 @@
     if (RT_FAILURE(rc))
     {
+#if defined(IN_RC) && defined(VBOX_WITH_RAW_MODE)
+        /* Allow interpretation of patch manager code blocks since they can for
+           instance throw #PFs for perfectly good reasons. */
+        if (   (pCtx->cs.Sel & X86_SEL_RPL) == 1
+            && PATMIsPatchGCAddr(IEMCPU_TO_VM(pIemCpu), GCPtrPC))
+        {
+            uint32_t cbLeftOnPage = PAGE_SIZE - (GCPtrPC & PAGE_OFFSET_MASK);
+            if (cbToTryRead > cbLeftOnPage)
+                cbToTryRead = cbLeftOnPage;
+            if (cbToTryRead > sizeof(pIemCpu->abOpcode))
+                cbToTryRead = sizeof(pIemCpu->abOpcode);
+            memcpy(pIemCpu->abOpcode, (void const *)(uintptr_t)GCPtrPC, cbToTryRead);
+            pIemCpu->cbOpcode = cbToTryRead;
+            return VINF_SUCCESS;
+        }
+#endif
         Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - rc=%Rrc\n", GCPtrPC, rc));
         return iemRaisePageFault(pIemCpu, GCPtrPC, IEM_ACCESS_INSTRUCTION, rc);
@@ -2644,17 +2666,26 @@
  * @param   iSegReg             The segment register.
  */
-static PCPUMSELREGHID iemSRegGetHid(PIEMCPU pIemCpu, uint8_t iSegReg)
-{
-    PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx);
+static PCPUMSELREG iemSRegGetHid(PIEMCPU pIemCpu, uint8_t iSegReg)
+{
+    PCPUMCTX    pCtx = pIemCpu->CTX_SUFF(pCtx);
+    PCPUMSELREG pSReg;
     switch (iSegReg)
     {
-        case X86_SREG_ES: return &pCtx->es;
-        case X86_SREG_CS: return &pCtx->cs;
-        case X86_SREG_SS: return &pCtx->ss;
-        case X86_SREG_DS: return &pCtx->ds;
-        case X86_SREG_FS: return &pCtx->fs;
-        case X86_SREG_GS: return &pCtx->gs;
-    }
-    AssertFailedReturn(NULL);
+        case X86_SREG_ES: pSReg = &pCtx->es; break;
+        case X86_SREG_CS: pSReg = &pCtx->cs; break;
+        case X86_SREG_SS: pSReg = &pCtx->ss; break;
+        case X86_SREG_DS: pSReg = &pCtx->ds; break;
+        case X86_SREG_FS: pSReg = &pCtx->fs; break;
+        case X86_SREG_GS: pSReg = &pCtx->gs; break;
+        default:
+            AssertFailedReturn(NULL);
+    }
+#ifdef VBOX_WITH_RAW_MODE_NOT_R0
+    if (!CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pSReg))
+        CPUMGuestLazyLoadHiddenSelectorReg(IEMCPU_TO_VMCPU(pIemCpu), pSReg);
+#else
+    Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pSReg));
+#endif
+    return pSReg;
 }
 
@@ -4408,6 +4439,7 @@
  * @param   fAccess             The intended access.
  * @param   ppvMem              Where to return the mapping address.
- */
-static int iemMemPageMap(PIEMCPU pIemCpu, RTGCPHYS GCPhysMem, uint32_t fAccess, void **ppvMem)
+ * @param   pLock               The PGM lock.
+ */
+static int iemMemPageMap(PIEMCPU pIemCpu, RTGCPHYS GCPhysMem, uint32_t fAccess, void **ppvMem, PPGMPAGEMAPLOCK pLock)
 {
 #ifdef IEM_VERIFICATION_MODE
@@ -4423,4 +4455,5 @@
     /** @todo need some better API. */
 #ifdef IN_RING3
+    RT_ZERO(*pLock);
     return PGMR3PhysTlbGCPhys2Ptr(IEMCPU_TO_VM(pIemCpu),
                                   GCPhysMem,
@@ -4428,14 +4461,13 @@
                                   ppvMem);
 #else
-//# error "Implement me"
     if (fAccess & IEM_ACCESS_TYPE_WRITE)
         return PGMPhysGCPhys2CCPtr(IEMCPU_TO_VM(pIemCpu),
                                    GCPhysMem,
                                    ppvMem,
-                                   /** @todo pLock */ NULL);
+                                   pLock);
     return PGMPhysGCPhys2CCPtrReadOnly(IEMCPU_TO_VM(pIemCpu),
                                        GCPhysMem,
                                        (void const **)ppvMem,
-                                       /** @todo pLock */ NULL);
+                                       pLock);
 #endif
 }
@@ -4451,6 +4483,7 @@
  * @param   fAccess             The intended access.
  * @param   pvMem               What iemMemPageMap returned.
- */
-DECLINLINE(void) iemMemPageUnmap(PIEMCPU pIemCpu, RTGCPHYS GCPhysMem, uint32_t fAccess, const void *pvMem)
+ * @param   pLock               The PGM lock.
+ */
+DECLINLINE(void) iemMemPageUnmap(PIEMCPU pIemCpu, RTGCPHYS GCPhysMem, uint32_t fAccess, const void *pvMem, PPGMPAGEMAPLOCK pLock)
 {
     NOREF(pIemCpu);
@@ -4458,4 +4491,7 @@
     NOREF(fAccess);
     NOREF(pvMem);
+#ifndef IN_RING3
+    PGMPhysReleasePageMappingLock(IEMCPU_TO_VM(pIemCpu), pLock);
+#endif
 }
 
@@ -4857,5 +4893,5 @@
 
     void *pvMem;
-    rcStrict = iemMemPageMap(pIemCpu, GCPhysFirst, fAccess, &pvMem);
+    rcStrict = iemMemPageMap(pIemCpu, GCPhysFirst, fAccess, &pvMem, &pIemCpu->aMemMappingLocks[iMemMap].Lock);
     if (rcStrict != VINF_SUCCESS)
         return iemMemBounceBufferMapPhys(pIemCpu, iMemMap, ppvMem, cbMem, GCPhysFirst, fAccess, rcStrict);
@@ -4896,4 +4932,9 @@
         == (IEM_ACCESS_BOUNCE_BUFFERED | IEM_ACCESS_TYPE_WRITE))
         return iemMemBounceBufferCommitAndUnmap(pIemCpu, iMemMap);
+
+#ifndef IN_RING3
+    /* Unlock it. */
+    PGMPhysReleasePageMappingLock(IEMCPU_TO_VM(pIemCpu), &pIemCpu->aMemMappingLocks[iMemMap].Lock);
+#endif
 
     /* Free the entry. */
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 42192)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 42193)
@@ -130,10 +130,12 @@
              * until the end of the current page.
              */
+            PGMPAGEMAPLOCK PgLockSrc2Mem;
             OP_TYPE const *puSrc2Mem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, (void **)&puSrc2Mem);
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, (void **)&puSrc2Mem, &PgLockSrc2Mem);
             if (rcStrict == VINF_SUCCESS)
             {
+                PGMPAGEMAPLOCK PgLockSrc1Mem;
                 OP_TYPE const *puSrc1Mem;
-                rcStrict = iemMemPageMap(pIemCpu, GCPhysSrc1Mem, IEM_ACCESS_DATA_R, (void **)&puSrc1Mem);
+                rcStrict = iemMemPageMap(pIemCpu, GCPhysSrc1Mem, IEM_ACCESS_DATA_R, (void **)&puSrc1Mem, &PgLockSrc1Mem);
                 if (rcStrict == VINF_SUCCESS)
                 {
@@ -168,10 +170,10 @@
                     pCtx->eflags.u = uEFlags;
 
-                    iemMemPageUnmap(pIemCpu, GCPhysSrc1Mem, IEM_ACCESS_DATA_R, puSrc1Mem);
-                    iemMemPageUnmap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, puSrc2Mem);
+                    iemMemPageUnmap(pIemCpu, GCPhysSrc1Mem, IEM_ACCESS_DATA_R, puSrc1Mem, &PgLockSrc1Mem);
+                    iemMemPageUnmap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, puSrc2Mem, &PgLockSrc2Mem);
                     continue;
                 }
             }
-            iemMemPageUnmap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, puSrc2Mem);
+            iemMemPageUnmap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, puSrc2Mem, &PgLockSrc2Mem);
         }
 
@@ -288,9 +290,11 @@
              */
             OP_TYPE const *puSrc2Mem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, (void **)&puSrc2Mem);
+            PGMPAGEMAPLOCK PgLockSrc2Mem;
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, (void **)&puSrc2Mem, &PgLockSrc2Mem);
             if (rcStrict == VINF_SUCCESS)
             {
                 OP_TYPE const *puSrc1Mem;
-                rcStrict = iemMemPageMap(pIemCpu, GCPhysSrc1Mem, IEM_ACCESS_DATA_R, (void **)&puSrc1Mem);
+                PGMPAGEMAPLOCK PgLockSrc1Mem;
+                rcStrict = iemMemPageMap(pIemCpu, GCPhysSrc1Mem, IEM_ACCESS_DATA_R, (void **)&puSrc1Mem, &PgLockSrc1Mem);
                 if (rcStrict == VINF_SUCCESS)
                 {
@@ -325,9 +329,9 @@
                     pCtx->eflags.u = uEFlags;
 
-                    iemMemPageUnmap(pIemCpu, GCPhysSrc1Mem, IEM_ACCESS_DATA_R, puSrc1Mem);
-                    iemMemPageUnmap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, puSrc2Mem);
+                    iemMemPageUnmap(pIemCpu, GCPhysSrc1Mem, IEM_ACCESS_DATA_R, puSrc1Mem, &PgLockSrc1Mem);
+                    iemMemPageUnmap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, puSrc2Mem, &PgLockSrc2Mem);
                     continue;
                 }
-                iemMemPageUnmap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, puSrc2Mem);
+                iemMemPageUnmap(pIemCpu, GCPhysSrc2Mem, IEM_ACCESS_DATA_R, puSrc2Mem, &PgLockSrc2Mem);
             }
         }
@@ -427,6 +431,7 @@
              * until the end of the current page.
              */
+            PGMPAGEMAPLOCK PgLockMem;
             OP_TYPE const *puMem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem);
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem, &PgLockMem);
             if (rcStrict == VINF_SUCCESS)
             {
@@ -447,5 +452,5 @@
                 pCtx->eflags.u = uEFlags;
                 Assert(!(uEFlags & X86_EFL_ZF) == (i < cLeftPage));
-                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem);
+                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem, &PgLockMem);
                 if (fQuit)
                     break;
@@ -551,6 +556,7 @@
              * until the end of the current page.
              */
+            PGMPAGEMAPLOCK PgLockMem;
             OP_TYPE const *puMem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem);
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem, &PgLockMem);
             if (rcStrict == VINF_SUCCESS)
             {
@@ -571,5 +577,5 @@
                 pCtx->eflags.u = uEFlags;
                 Assert((!(uEFlags & X86_EFL_ZF) != (i < cLeftPage)) || (i == cLeftPage));
-                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem);
+                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem, &PgLockMem);
                 if (fQuit)
                     break;
@@ -693,10 +699,12 @@
              * until the end of the current page.
              */
+            PGMPAGEMAPLOCK PgLockDstMem;
             OP_TYPE *puDstMem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysDstMem, IEM_ACCESS_DATA_W, (void **)&puDstMem);
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysDstMem, IEM_ACCESS_DATA_W, (void **)&puDstMem, &PgLockDstMem);
             if (rcStrict == VINF_SUCCESS)
             {
+                PGMPAGEMAPLOCK PgLockSrcMem;
                 OP_TYPE const *puSrcMem;
-                rcStrict = iemMemPageMap(pIemCpu, GCPhysSrcMem, IEM_ACCESS_DATA_R, (void **)&puSrcMem);
+                rcStrict = iemMemPageMap(pIemCpu, GCPhysSrcMem, IEM_ACCESS_DATA_R, (void **)&puSrcMem, &PgLockSrcMem);
                 if (rcStrict == VINF_SUCCESS)
                 {
@@ -709,9 +717,9 @@
                     pCtx->ADDR_rCX = uCounterReg -= cLeftPage;
 
-                    iemMemPageUnmap(pIemCpu, GCPhysSrcMem, IEM_ACCESS_DATA_R, puSrcMem);
-                    iemMemPageUnmap(pIemCpu, GCPhysDstMem, IEM_ACCESS_DATA_W, puDstMem);
+                    iemMemPageUnmap(pIemCpu, GCPhysSrcMem, IEM_ACCESS_DATA_R, puSrcMem, &PgLockSrcMem);
+                    iemMemPageUnmap(pIemCpu, GCPhysDstMem, IEM_ACCESS_DATA_W, puDstMem, &PgLockDstMem);
                     continue;
                 }
-                iemMemPageUnmap(pIemCpu, GCPhysDstMem, IEM_ACCESS_DATA_W, puDstMem);
+                iemMemPageUnmap(pIemCpu, GCPhysDstMem, IEM_ACCESS_DATA_W, puDstMem, &PgLockDstMem);
             }
         }
@@ -805,6 +813,7 @@
              * until the end of the current page.
              */
+            PGMPAGEMAPLOCK PgLockMem;
             OP_TYPE *puMem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, (void **)&puMem);
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, (void **)&puMem, &PgLockMem);
             if (rcStrict == VINF_SUCCESS)
             {
@@ -823,5 +832,5 @@
 #endif
 
-                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, puMem);
+                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, puMem, &PgLockMem);
 
                 /* If unaligned, we drop thru and do the page crossing access
@@ -917,6 +926,7 @@
              * just reading the last value on the page.
              */
+            PGMPAGEMAPLOCK PgLockMem;
             OP_TYPE const *puMem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem);
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem, &PgLockMem);
             if (rcStrict == VINF_SUCCESS)
             {
@@ -929,5 +939,5 @@
                 pCtx->ADDR_rCX = uCounterReg -= cLeftPage;
                 pCtx->ADDR_rSI = uAddrReg    += cLeftPage * cbIncr;
-                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem);
+                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem, &PgLockMem);
 
                 /* If unaligned, we drop thru and do the page crossing access
@@ -1093,6 +1103,7 @@
              *        mapped buffers instead of leaving those bits to the
              *        device implementation? */
+            PGMPAGEMAPLOCK PgLockMem;
             OP_TYPE *puMem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, (void **)&puMem);
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, (void **)&puMem, &PgLockMem);
             if (rcStrict == VINF_SUCCESS)
             {
@@ -1116,10 +1127,10 @@
                         if (uCounterReg == 0)
                             iemRegAddToRip(pIemCpu, cbInstr);
-                        iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, puMem);
+                        iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, puMem, &PgLockMem);
                         return rcStrict;
                     }
                     off++;
                 }
-                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, puMem);
+                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_W, puMem, &PgLockMem);
 
                 /* If unaligned, we drop thru and do the page crossing access
@@ -1293,6 +1304,7 @@
              *        mapped buffers instead of leaving those bits to the
              *        device implementation? */
+            PGMPAGEMAPLOCK PgLockMem;
             OP_TYPE const *puMem;
-            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem);
+            rcStrict = iemMemPageMap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, (void **)&puMem, &PgLockMem);
             if (rcStrict == VINF_SUCCESS)
             {
@@ -1315,10 +1327,10 @@
                         if (uCounterReg == 0)
                             iemRegAddToRip(pIemCpu, cbInstr);
-                        iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem);
+                        iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem, &PgLockMem);
                         return rcStrict;
                     }
                     off++;
                 }
-                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem);
+                iemMemPageUnmap(pIemCpu, GCPhysMem, IEM_ACCESS_DATA_R, puMem, &PgLockMem);
 
                 /* If unaligned, we drop thru and do the page crossing access
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 42192)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 42193)
@@ -310,4 +310,11 @@
 #endif
     } aMemMappings[3];
+
+    /** Locking records for the mapped memory. */
+    union
+    {
+        PGMPAGEMAPLOCK      Lock;
+        uint64_t            au64Padding[2];
+    } aMemMappingLocks[3];
 
     /** Bounce buffer info.
