Index: /trunk/include/VBox/vmm/pgm.h
===================================================================
--- /trunk/include/VBox/vmm/pgm.h	(revision 42452)
+++ /trunk/include/VBox/vmm/pgm.h	(revision 42453)
@@ -384,4 +384,5 @@
 VMMDECL(int)        PGMPhysInterpretedReadNoHandlers(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCUINTPTR GCPtrSrc, size_t cb, bool fRaiseTrap);
 VMMDECL(int)        PGMPhysInterpretedWriteNoHandlers(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, void const *pvSrc, size_t cb, bool fRaiseTrap);
+VMM_INT_DECL(int)   PGMPhysIemGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, bool fByPassHandlers, void **ppv, PPGMPAGEMAPLOCK pLock);
 #ifdef VBOX_STRICT
 VMMDECL(unsigned)   PGMAssertHandlerAndFlagsInSync(PVM pVM);
Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 42452)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 42453)
@@ -657,4 +657,44 @@
 
 /**
+ * Sets the pass up status.
+ *
+ * @returns VINF_SUCCESS.
+ * @param   pIemCpu             The per CPU IEM state of the calling thread.
+ * @param   rcPassUp            The pass up status.  Must be informational.
+ *                              VINF_SUCCESS is not allowed.
+ */
+static int iemSetPassUpStatus(PIEMCPU pIemCpu, VBOXSTRICTRC rcPassUp)
+{
+    AssertRC(VBOXSTRICTRC_VAL(rcPassUp)); Assert(rcPassUp != VINF_SUCCESS);
+
+    int32_t const rcOldPassUp = pIemCpu->rcPassUp;
+    if (rcOldPassUp == VINF_SUCCESS)
+        pIemCpu->rcPassUp = VBOXSTRICTRC_VAL(rcPassUp);
+    /* If both are EM scheduling code, use EM priority rules. */
+    else if (   rcOldPassUp >= VINF_EM_FIRST && rcOldPassUp <= VINF_EM_LAST
+             && rcPassUp    >= VINF_EM_FIRST && rcPassUp    <= VINF_EM_LAST)
+    {
+        if (rcPassUp < rcOldPassUp)
+        {
+            Log(("IEM: rcPassUp=%Rrc! rcOldPassUp=%Rrc\n", VBOXSTRICTRC_VAL(rcPassUp), rcOldPassUp));
+            pIemCpu->rcPassUp = VBOXSTRICTRC_VAL(rcPassUp);
+        }
+        else
+            Log(("IEM: rcPassUp=%Rrc  rcOldPassUp=%Rrc!\n", VBOXSTRICTRC_VAL(rcPassUp), rcOldPassUp));
+    }
+    /* Override EM scheduling with specific status code. */
+    else if (rcOldPassUp >= VINF_EM_FIRST && rcOldPassUp <= VINF_EM_LAST)
+    {
+        Log(("IEM: rcPassUp=%Rrc! rcOldPassUp=%Rrc\n", VBOXSTRICTRC_VAL(rcPassUp), rcOldPassUp));
+        pIemCpu->rcPassUp = VBOXSTRICTRC_VAL(rcPassUp);
+    }
+    /* Don't override specific status code, first come first served. */
+    else
+        Log(("IEM: rcPassUp=%Rrc  rcOldPassUp=%Rrc!\n", VBOXSTRICTRC_VAL(rcPassUp), rcOldPassUp));
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Initializes the decoder state.
  *
@@ -688,4 +728,5 @@
     pIemCpu->cActiveMappings    = 0;
     pIemCpu->iNextMapping       = 0;
+    pIemCpu->rcPassUp           = VINF_SUCCESS;
 }
 
@@ -802,5 +843,6 @@
     if (rc != VINF_SUCCESS)
     {
-        Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - read error - rc=%Rrc\n", GCPtrPC, rc));
+        /** @todo status code handling */
+        Log(("iemInitDecoderAndPrefetchOpcodes: %RGv - read error - rc=%Rrc (!!)\n", GCPtrPC, rc));
         return rc;
     }
@@ -891,5 +933,6 @@
     if (rc != VINF_SUCCESS)
     {
-        Log(("iemOpcodeFetchMoreBytes: %RGv - read error - rc=%Rrc\n", GCPtrNext, rc));
+        /** @todo status code handling */
+        Log(("iemOpcodeFetchMoreBytes: %RGv - read error - rc=%Rrc (!!)\n", GCPtrNext, rc));
         return rc;
     }
@@ -4486,26 +4529,14 @@
 #endif
 
-    /*
-     * If we can map the page without trouble, do a block processing
-     * until the end of the current page.
-     */
-    /** @todo need some better API. */
-#ifdef IN_RING3
-    RT_ZERO(*pLock);
-    return PGMR3PhysTlbGCPhys2Ptr(IEMCPU_TO_VM(pIemCpu),
-                                  GCPhysMem,
-                                  RT_BOOL(fAccess & IEM_ACCESS_TYPE_WRITE),
-                                  ppvMem);
-#else
-    if (fAccess & IEM_ACCESS_TYPE_WRITE)
-        return PGMPhysGCPhys2CCPtr(IEMCPU_TO_VM(pIemCpu),
-                                   GCPhysMem,
-                                   ppvMem,
-                                   pLock);
-    return PGMPhysGCPhys2CCPtrReadOnly(IEMCPU_TO_VM(pIemCpu),
-                                       GCPhysMem,
-                                       (void const **)ppvMem,
-                                       pLock);
-#endif
+    /** @todo This API may require some improving later.  A private deal with PGM
+     *        regarding locking and unlocking needs to be struct.  A couple of TLBs
+     *        living in PGM, but with publicly accessible inlined access methods
+     *        could perhaps be an even better solution. */
+    return PGMPhysIemGCPhys2Ptr(IEMCPU_TO_VM(pIemCpu),
+                                GCPhysMem,
+                                RT_BOOL(fAccess & IEM_ACCESS_TYPE_WRITE),
+                                pIemCpu->fByPassHandlers,
+                                ppvMem,
+                                pLock);
 }
 
@@ -4632,4 +4663,12 @@
                                               cbSecond);
         }
+        if (rc != VINF_SUCCESS)
+        {
+            /** @todo status code handling */
+            Log(("iemMemBounceBufferCommitAndUnmap: %s GCPhysFirst=%RGp/%#x GCPhysSecond=%RGp/%#x %Rrc (!!)\n",
+                 pIemCpu->fByPassHandlers ? "PGMPhysWrite" : "PGMPhysSimpleWriteGCPhys",
+                 pIemCpu->aMemBbMappings[iMemMap].GCPhysFirst, cbFirst,
+                 pIemCpu->aMemBbMappings[iMemMap].GCPhysSecond, cbSecond, rc));
+        }
     }
     else
@@ -4716,8 +4755,16 @@
             rc = PGMPhysRead(IEMCPU_TO_VM(pIemCpu), GCPhysFirst, pbBuf, cbFirstPage);
             if (rc != VINF_SUCCESS)
+            {
+                /** @todo status code handling */
+                Log(("iemMemBounceBufferMapPhys: PGMPhysRead GCPhysFirst=%RGp rc=%Rrc (!!)\n", GCPhysFirst, rc));
                 return rc;
+            }
             rc = PGMPhysRead(IEMCPU_TO_VM(pIemCpu), GCPhysSecond, pbBuf + cbFirstPage, cbSecondPage);
             if (rc != VINF_SUCCESS)
+            {
+                /** @todo status code handling */
+                Log(("iemMemBounceBufferMapPhys: PGMPhysRead GCPhysSecond=%RGp rc=%Rrc (!!)\n", GCPhysSecond, rc));
                 return rc;
+            }
         }
         else
@@ -4725,8 +4772,16 @@
             rc = PGMPhysSimpleReadGCPhys(IEMCPU_TO_VM(pIemCpu), pbBuf, GCPhysFirst, cbFirstPage);
             if (rc != VINF_SUCCESS)
+            {
+                /** @todo status code handling */
+                Log(("iemMemBounceBufferMapPhys: PGMPhysSimpleReadGCPhys GCPhysFirst=%RGp rc=%Rrc (!!)\n", GCPhysFirst, rc));
                 return rc;
+            }
             rc = PGMPhysSimpleReadGCPhys(IEMCPU_TO_VM(pIemCpu), pbBuf + cbFirstPage, GCPhysSecond, cbSecondPage);
             if (rc != VINF_SUCCESS)
+            {
+                /** @todo status code handling */
+                Log(("iemMemBounceBufferMapPhys: PGMPhysSimpleReadGCPhys GCPhysSecond=%RGp rc=%Rrc (!!)\n", GCPhysSecond, rc));
                 return rc;
+            }
         }
 
@@ -4820,5 +4875,10 @@
                 rc = PGMPhysSimpleReadGCPhys(IEMCPU_TO_VM(pIemCpu), pbBuf, GCPhysFirst, cbMem);
             if (rc != VINF_SUCCESS)
+            {
+                /** @todo status code handling */
+                Log(("iemMemBounceBufferMapPhys: %s GCPhysFirst=%RGp rc=%Rrc (!!)\n",
+                     pIemCpu->fByPassHandlers ? "PGMPhysRead" : "PGMPhysSimpleReadGCPhys",  GCPhysFirst, rc));
                 return rc;
+            }
         }
 
@@ -7890,14 +7950,40 @@
     }
 
+    /*
+     * Return value fiddling and statistics.
+     */
     if (rcStrict != VINF_SUCCESS)
     {
-        if (rcStrict == VERR_IEM_ASPECT_NOT_IMPLEMENTED)
+        if (RT_SUCCESS(rcStrict))
+        {
+            AssertMsg(rcStrict >= VINF_EM_FIRST && rcStrict <= VINF_EM_LAST, ("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
+            int32_t const rcPassUp = pIemCpu->rcPassUp;
+            if (rcPassUp == VINF_SUCCESS)
+                pIemCpu->cRetInfStatuses++;
+            else if (   rcPassUp < VINF_EM_FIRST
+                     || rcPassUp > VINF_EM_LAST
+                     || rcPassUp < VBOXSTRICTRC_VAL(rcStrict))
+            {
+                Log(("IEM: rcPassUp=%Rrc! rcStrict=%Rrc\n", rcPassUp, VBOXSTRICTRC_VAL(rcStrict)));
+                pIemCpu->cRetPassUpStatus++;
+                rcStrict = rcPassUp;
+            }
+            else
+            {
+                Log(("IEM: rcPassUp=%Rrc  rcStrict=%Rrc!\n", rcPassUp, VBOXSTRICTRC_VAL(rcStrict)));
+                pIemCpu->cRetInfStatuses++;
+            }
+        }
+        else if (rcStrict == VERR_IEM_ASPECT_NOT_IMPLEMENTED)
             pIemCpu->cRetAspectNotImplemented++;
         else if (rcStrict == VERR_IEM_INSTR_NOT_IMPLEMENTED)
             pIemCpu->cRetInstrNotImplemented++;
-        else if (RT_SUCCESS(rcStrict))
-            pIemCpu->cRetInfStatuses++;
         else
             pIemCpu->cRetErrStatuses++;
+    }
+    else if (pIemCpu->rcPassUp != VINF_SUCCESS)
+    {
+        pIemCpu->cRetPassUpStatus++;
+        rcStrict = pIemCpu->rcPassUp;
     }
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 42452)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 42453)
@@ -2637,5 +2637,5 @@
     {
         if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-            rcStrict = CPUMSetGuestIDTR(IEMCPU_TO_VMCPU(pIemCpu), GCPtrBase, cbLimit);
+            CPUMSetGuestIDTR(IEMCPU_TO_VMCPU(pIemCpu), GCPtrBase, cbLimit);
         else
         {
@@ -2644,6 +2644,5 @@
             pCtx->idtr.pIdt  = GCPtrBase;
         }
-        if (rcStrict == VINF_SUCCESS)
-            iemRegAddToRip(pIemCpu, cbInstr);
+        iemRegAddToRip(pIemCpu, cbInstr);
     }
     return rcStrict;
@@ -3001,8 +3000,5 @@
              */
             if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-            {
-                rc = CPUMSetGuestCR0(pVCpu, uNewCrX);
-                AssertRCSuccessReturn(rc, RT_FAILURE_NP(rc) ? rc : VERR_INTERNAL_ERROR_3);
-            }
+                CPUMSetGuestCR0(pVCpu, uNewCrX);
             else
                 pCtx->cr0 = uNewCrX;
@@ -3041,5 +3037,4 @@
                 }
                 rcStrict = PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
-                /** @todo Status code management.  */
             }
             else
@@ -3107,5 +3102,4 @@
                     AssertRCReturn(rc, rc);
                     /* ignore informational status codes */
-                    /** @todo status code management */
                 }
             }
@@ -3120,5 +3114,5 @@
         case 4:
         {
-            uint64_t const uOldCrX = pCtx->cr0;
+            uint64_t const uOldCrX = pCtx->cr4;
 
             /* reserved bits */
@@ -3168,5 +3162,9 @@
                 /* SELM - VME may change things wrt to the TSS shadowing. */
                 if ((uNewCrX ^ uOldCrX) & X86_CR4_VME)
+                {
+                    Log(("iemCImpl_load_CrX: VME %d -> %d => Setting VMCPU_FF_SELM_SYNC_TSS\n",
+                         RT_BOOL(uOldCrX & X86_CR4_VME), RT_BOOL(uNewCrX & X86_CR4_VME) ));
                     VMCPU_FF_SET(pVCpu, VMCPU_FF_SELM_SYNC_TSS);
+                }
 
                 /* PGM - flushing and mode. */
@@ -3179,5 +3177,4 @@
                 }
                 rcStrict = PGMChangeMode(pVCpu, pCtx->cr0, pCtx->cr4, pCtx->msrEFER);
-                /** @todo Status code management.  */
             }
             else
@@ -3202,9 +3199,12 @@
      * Advance the RIP on success.
      */
-    /** @todo Status code management.  */
-    if (rcStrict == VINF_SUCCESS)
+    if (RT_SUCCESS(rcStrict))
+    {
+        if (rcStrict != VINF_SUCCESS)
+            rcStrict = iemSetPassUpStatus(pIemCpu, rcStrict);
         iemRegAddToRip(pIemCpu, cbInstr);
+    }
+
     return rcStrict;
-
 }
 
@@ -3450,7 +3450,10 @@
     iemRegAddToRip(pIemCpu, cbInstr);
 
-    if (   rc == VINF_SUCCESS
-        || rc == VINF_PGM_SYNC_CR3)
+    if (rc == VINF_SUCCESS)
         return VINF_SUCCESS;
+    if (rc == VINF_PGM_SYNC_CR3)
+        return iemSetPassUpStatus(pIemCpu, rc);
+
+    AssertMsg(rc == VINF_EM_RAW_EMULATE_INSTR || RT_FAILURE_NP(rc), ("%Rrc\n", rc));
     Log(("PGMInvalidatePage(%RGv) -> %Rrc\n", rc));
     return rc;
@@ -3563,6 +3566,8 @@
         iemRegAddToRip(pIemCpu, cbInstr);
         pIemCpu->cPotentialExits++;
-    }
-    /** @todo massage rcStrict. */
+        if (rcStrict != VINF_SUCCESS)
+            rcStrict = iemSetPassUpStatus(pIemCpu, rcStrict);
+    }
+
     return rcStrict;
 }
@@ -3612,16 +3617,17 @@
         default: AssertFailedReturn(VERR_INTERNAL_ERROR_3);
     }
-    VBOXSTRICTRC rc;
+    VBOXSTRICTRC rcStrict;
     if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-        rc = IOMIOPortWrite(IEMCPU_TO_VM(pIemCpu), u16Port, u32Value, cbReg);
+        rcStrict = IOMIOPortWrite(IEMCPU_TO_VM(pIemCpu), u16Port, u32Value, cbReg);
     else
-        rc = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, u32Value, cbReg);
-    if (IOM_SUCCESS(rc))
+        rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, u32Value, cbReg);
+    if (IOM_SUCCESS(rcStrict))
     {
         iemRegAddToRip(pIemCpu, cbInstr);
         pIemCpu->cPotentialExits++;
-        /** @todo massage rc. */
-    }
-    return rc;
+        if (rcStrict != VINF_SUCCESS)
+            rcStrict = iemSetPassUpStatus(pIemCpu, rcStrict);
+    }
+    return rcStrict;
 }
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 42452)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 42453)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-2012 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -1124,5 +1124,6 @@
                     if (rcStrict != VINF_SUCCESS)
                     {
-                        /** @todo massage rc */
+                        if (IOM_SUCCESS(rcStrict))
+                            rcStrict = iemSetPassUpStatus(pIemCpu, rcStrict);
                         if (uCounterReg == 0)
                             iemRegAddToRip(pIemCpu, cbInstr);
@@ -1179,5 +1180,6 @@
             if (rcStrict != VINF_SUCCESS)
             {
-                /** @todo massage IOM status codes! */
+                if (IOM_SUCCESS(rcStrict))
+                    rcStrict = iemSetPassUpStatus(pIemCpu, rcStrict);
                 if (uCounterReg == 0)
                     iemRegAddToRip(pIemCpu, cbInstr);
@@ -1228,5 +1230,6 @@
                 pCtx->ADDR_rSI -= OP_SIZE / 8;
             iemRegAddToRip(pIemCpu, cbInstr);
-            /** @todo massage IOM status codes. */
+            if (rcStrict != VINF_SUCCESS)
+                rcStrict = iemSetPassUpStatus(pIemCpu, rcStrict);
         }
     }
@@ -1324,5 +1327,6 @@
                     if (rcStrict != VINF_SUCCESS)
                     {
-                        /** @todo massage IOM rc */
+                        if (IOM_SUCCESS(rcStrict))
+                            rcStrict = iemSetPassUpStatus(pIemCpu, rcStrict);
                         if (uCounterReg == 0)
                             iemRegAddToRip(pIemCpu, cbInstr);
@@ -1373,5 +1377,6 @@
             if (rcStrict != VINF_SUCCESS)
             {
-                /** @todo massage IOM status codes! */
+                if (IOM_SUCCESS(rcStrict))
+                    rcStrict = iemSetPassUpStatus(pIemCpu, rcStrict);
                 if (uCounterReg == 0)
                     iemRegAddToRip(pIemCpu, cbInstr);
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp	(revision 42452)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllPhys.cpp	(revision 42453)
@@ -4002,2 +4002,122 @@
 }
 
+
+
+
+/**
+ * Converts a GC physical address to a HC ring-3 pointer, with some
+ * additional checks.
+ *
+ * @returns VBox status code.
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VINF_PGM_PHYS_TLB_CATCH_WRITE and *ppv set if the page has a write
+ *          access handler of some kind.
+ * @retval  VERR_PGM_PHYS_TLB_CATCH_ALL if the page has a handler catching all
+ *          accesses or is odd in any way.
+ * @retval  VERR_PGM_PHYS_TLB_UNASSIGNED if the page doesn't exist.
+ *
+ * @param   pVM         Pointer to the VM.
+ * @param   GCPhys      The GC physical address to convert.  Since this is only
+ *                      used for filling the REM TLB, the A20 mask must be
+ *                      applied before calling this API.
+ * @param   fWritable   Whether write access is required.
+ * @param   ppv         Where to store the pointer corresponding to GCPhys on
+ *                      success.
+ * @param   pLock
+ *
+ * @remarks This is more or a less a copy of PGMR3PhysTlbGCPhys2Ptr.
+ */
+VMM_INT_DECL(int) PGMPhysIemGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, bool fByPassHandlers,
+                                       void **ppv, PPGMPAGEMAPLOCK pLock)
+{
+    pgmLock(pVM);
+    PGM_A20_ASSERT_MASKED(VMMGetCpu(pVM), GCPhys);
+
+    PPGMRAMRANGE pRam;
+    PPGMPAGE pPage;
+    int rc = pgmPhysGetPageAndRangeEx(pVM, GCPhys, &pPage, &pRam);
+    if (RT_SUCCESS(rc))
+    {
+        if (PGM_PAGE_IS_BALLOONED(pPage))
+            rc = VINF_PGM_PHYS_TLB_CATCH_WRITE;
+        else if (   !PGM_PAGE_HAS_ANY_HANDLERS(pPage)
+                 || (fByPassHandlers && !PGM_PAGE_IS_MMIO(pPage)) )
+            rc = VINF_SUCCESS;
+        else
+        {
+            if (PGM_PAGE_HAS_ACTIVE_ALL_HANDLERS(pPage)) /* catches MMIO */
+            {
+                Assert(!fByPassHandlers || PGM_PAGE_IS_MMIO(pPage));
+                rc = VERR_PGM_PHYS_TLB_CATCH_ALL;
+            }
+            else if (PGM_PAGE_HAS_ACTIVE_HANDLERS(pPage) && fWritable)
+            {
+                Assert(!fByPassHandlers);
+                rc = VINF_PGM_PHYS_TLB_CATCH_WRITE;
+            }
+        }
+        if (RT_SUCCESS(rc))
+        {
+            int rc2;
+
+            /* Make sure what we return is writable. */
+            if (fWritable)
+                switch (PGM_PAGE_GET_STATE(pPage))
+                {
+                    case PGM_PAGE_STATE_ALLOCATED:
+                        break;
+                    case PGM_PAGE_STATE_BALLOONED:
+                        AssertFailed();
+                        break;
+                    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);
+                        AssertLogRelRCReturn(rc2, rc2);
+                        break;
+                }
+
+#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+            PVMCPU pVCpu = VMMGetCpu(pVM);
+            void *pv;
+            rc = pgmRZDynMapHCPageInlined(pVCpu,
+                                          PGM_PAGE_GET_HCPHYS(pPage),
+                                          &pv
+                                          RTLOG_COMMA_SRC_POS);
+            if (RT_FAILURE(rc))
+                return rc;
+            *ppv = (void *)((uintptr_t)pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
+            pLock->pvPage = pv;
+            pLock->pVCpu  = pVCpu;
+
+#else
+            /* Get a ring-3 mapping of the address. */
+            PPGMPAGER3MAPTLBE pTlbe;
+            rc2 = pgmPhysPageQueryTlbeWithPage(pVM, pPage, GCPhys, &pTlbe);
+            AssertLogRelRCReturn(rc2, rc2);
+
+            /* Lock it and calculate the address. */
+            if (fWritable)
+                pgmPhysPageMapLockForWriting(pVM, pPage, pTlbe, pLock);
+            else
+                pgmPhysPageMapLockForReading(pVM, pPage, pTlbe, pLock);
+            *ppv = (void *)((uintptr_t)pTlbe->pv | (uintptr_t)(GCPhys & PAGE_OFFSET_MASK));
+#endif
+
+
+            Log6(("PGMPhysIemGCPhys2Ptr: GCPhys=%RGp rc=%Rrc pPage=%R[pgmpage] *ppv=%p\n", GCPhys, rc, pPage, *ppv));
+        }
+        else
+            Log6(("PGMPhysIemGCPhys2Ptr: GCPhys=%RGp rc=%Rrc pPage=%R[pgmpage]\n", GCPhys, rc, pPage));
+
+        /* else: handler catching all access, no pointer returned. */
+    }
+    else
+        rc = VERR_PGM_PHYS_TLB_UNASSIGNED;
+
+    pgmUnlock(pVM);
+    return rc;
+}
+
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 42452)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 42453)
@@ -221,4 +221,10 @@
     /** The current CPU execution mode (CS). */
     IEMMODE                 enmCpuMode;
+    /** Info status code that needs to be propagated to the IEM caller.
+     * This cannot be passed internally, as it would complicate all success
+     * checks within the interpreter making the code larger and almost impossible
+     * to get right.  Instead, we'll store status codes to pass on here.  Each
+     * source of these codes will perform appropriate sanity checks. */
+    int32_t                 rcPassUp;
 
     /** @name Statistics
@@ -239,4 +245,6 @@
     /** Counts other error statuses returned. */
     uint32_t                cRetErrStatuses;
+    /** Number of times rcPassUp has been used. */
+    uint32_t                cRetPassUpStatus;
 #ifdef IEM_VERIFICATION_MODE
     /** The Number of I/O port reads that has been performed. */
