Index: /trunk/include/VBox/vmm/iom.h
===================================================================
--- /trunk/include/VBox/vmm/iom.h	(revision 45304)
+++ /trunk/include/VBox/vmm/iom.h	(revision 45305)
@@ -271,17 +271,17 @@
 typedef FNIOMMMIOFILL *PFNIOMMMIOFILL;
 
-VMMDECL(VBOXSTRICTRC)   IOMIOPortRead(PVM pVM, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue);
-VMMDECL(VBOXSTRICTRC)   IOMIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
-VMMDECL(VBOXSTRICTRC)   IOMInterpretOUT(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
-VMMDECL(VBOXSTRICTRC)   IOMInterpretIN(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
-VMMDECL(VBOXSTRICTRC)   IOMIOPortReadString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb);
-VMMDECL(VBOXSTRICTRC)   IOMIOPortWriteString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb);
-VMMDECL(VBOXSTRICTRC)   IOMInterpretINS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
-VMMDECL(VBOXSTRICTRC)   IOMInterpretINSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
-VMMDECL(VBOXSTRICTRC)   IOMInterpretOUTS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
-VMMDECL(VBOXSTRICTRC)   IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
-VMMDECL(VBOXSTRICTRC)   IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue);
-VMMDECL(VBOXSTRICTRC)   IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue);
-VMMDECL(VBOXSTRICTRC)   IOMMMIOPhysHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault);
+VMMDECL(VBOXSTRICTRC)   IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC)   IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC)   IOMInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMDECL(VBOXSTRICTRC)   IOMInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMDECL(VBOXSTRICTRC)   IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb);
+VMMDECL(VBOXSTRICTRC)   IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb);
+VMMDECL(VBOXSTRICTRC)   IOMInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMDECL(VBOXSTRICTRC)   IOMInterpretINSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
+VMMDECL(VBOXSTRICTRC)   IOMInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMDECL(VBOXSTRICTRC)   IOMInterpretOUTSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
+VMMDECL(VBOXSTRICTRC)   IOMMMIORead(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC)   IOMMMIOWrite(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC)   IOMMMIOPhysHandler(PVM pVM, PVMCPU pVCpu, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault);
 VMMDECL(VBOXSTRICTRC)   IOMInterpretCheckPortIOAccess(PVM pVM, PCPUMCTXCORE pCtxCore, RTIOPORT Port, unsigned cb);
 VMMDECL(int)            IOMMMIOMapMMIO2Page(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysRemapped, uint64_t fPageFlags);
@@ -295,5 +295,5 @@
  * @{
  */
-VMMRCDECL(VBOXSTRICTRC) IOMRCIOPortHandler(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMRCDECL(VBOXSTRICTRC) IOMRCIOPortHandler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
 /** @} */
 #endif /* IN_RC */
Index: /trunk/src/VBox/Devices/Bus/DevPCI.cpp
===================================================================
--- /trunk/src/VBox/Devices/Bus/DevPCI.cpp	(revision 45304)
+++ /trunk/src/VBox/Devices/Bus/DevPCI.cpp	(revision 45305)
@@ -1840,8 +1840,8 @@
 {
     unsigned    i;
-    uint8_t     elcr[2] = {0, 0};
+    uint8_t     elcr[2]  = {0, 0};
     PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS);
-    PVM         pVM = PDMDevHlpGetVM(pDevIns);
-    Assert(pVM);
+    PVM         pVM      = PDMDevHlpGetVM(pDevIns); Assert(pVM);
+    PVMCPU      pVCpu    = PDMDevHlpGetVMCPU(pDevIns); Assert(pVM);
 
     /*
@@ -1865,7 +1865,7 @@
 
     /* Tell to the PIC. */
-    VBOXSTRICTRC rcStrict = IOMIOPortWrite(pVM, 0x4d0, elcr[0], sizeof(uint8_t));
+    VBOXSTRICTRC rcStrict = IOMIOPortWrite(pVM, pVCpu, 0x4d0, elcr[0], sizeof(uint8_t));
     if (rcStrict == VINF_SUCCESS)
-        rcStrict = IOMIOPortWrite(pVM, 0x4d1, elcr[1], sizeof(uint8_t));
+        rcStrict = IOMIOPortWrite(pVM, pVCpu, 0x4d1, elcr[1], sizeof(uint8_t));
     if (rcStrict != VINF_SUCCESS)
     {
Index: /trunk/src/VBox/Devices/Graphics/DevVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 45304)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 45305)
@@ -1215,5 +1215,6 @@
             /** @todo only allow read access (doesn't work now) */
             STAM_COUNTER_INC(&pThis->StatMapPage);
-            IOMMMIOMapMMIO2Page(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), GCPhys, pThis->GCPhysVRAM + addr, X86_PTE_RW|X86_PTE_P);
+            IOMMMIOMapMMIO2Page(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), GCPhys,
+                                pThis->GCPhysVRAM + addr, X86_PTE_RW | X86_PTE_P);
             /* Set as dirty as write accesses won't be noticed now. */
             vga_set_dirty(pThis, addr);
@@ -1297,5 +1298,6 @@
             {
                 STAM_COUNTER_INC(&pThis->StatMapPage);
-                IOMMMIOMapMMIO2Page(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), GCPhys, pThis->GCPhysVRAM + addr, X86_PTE_RW | X86_PTE_P);
+                IOMMMIOMapMMIO2Page(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), GCPhys,
+                                    pThis->GCPhysVRAM + addr, X86_PTE_RW | X86_PTE_P);
                 pThis->fRemappedVGA = true;
             }
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 45305)
@@ -3838,5 +3838,5 @@
     uint32_t u32Value;
     if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-        rcStrict = IOMIOPortRead(IEMCPU_TO_VM(pIemCpu), u16Port, &u32Value, cbReg);
+        rcStrict = IOMIOPortRead(IEMCPU_TO_VM(pIemCpu), IEMCPU_TO_VMCPU(pIemCpu), u16Port, &u32Value, cbReg);
     else
         rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, cbReg);
@@ -3900,5 +3900,5 @@
     }
     if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-        rcStrict = IOMIOPortWrite(IEMCPU_TO_VM(pIemCpu), u16Port, u32Value, cbReg);
+        rcStrict = IOMIOPortWrite(IEMCPU_TO_VM(pIemCpu), IEMCPU_TO_VMCPU(pIemCpu), u16Port, u32Value, cbReg);
     else
         rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, u32Value, cbReg);
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 45305)
@@ -1061,5 +1061,5 @@
     uint32_t        u32Value;
     if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-        rcStrict = IOMIOPortRead(pVM, pCtx->dx, &u32Value, OP_SIZE / 8);
+        rcStrict = IOMIOPortRead(pVM, IEMCPU_TO_VMCPU(pIemCpu), pCtx->dx, &u32Value, OP_SIZE / 8);
     else
         rcStrict = iemVerifyFakeIOPortRead(pIemCpu, pCtx->dx, &u32Value, OP_SIZE / 8);
@@ -1091,6 +1091,7 @@
 IEM_CIMPL_DEF_0(RT_CONCAT4(iemCImpl_rep_ins_op,OP_SIZE,_addr,ADDR_SIZE))
 {
-    PVM         pVM  = IEMCPU_TO_VM(pIemCpu);
-    PCPUMCTX    pCtx = pIemCpu->CTX_SUFF(pCtx);
+    PVM         pVM   = IEMCPU_TO_VM(pIemCpu);
+    PVMCPU      pVCpu = IEMCPU_TO_VMCPU(pIemCpu);
+    PCPUMCTX    pCtx  = pIemCpu->CTX_SUFF(pCtx);
 
     /*
@@ -1173,5 +1174,5 @@
                     uint32_t u32Value;
                     if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-                        rcStrict = IOMIOPortRead(pVM, u16Port, &u32Value, OP_SIZE / 8);
+                        rcStrict = IOMIOPortRead(pVM, pVCpu, u16Port, &u32Value, OP_SIZE / 8);
                     else
                         rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, OP_SIZE / 8);
@@ -1224,5 +1225,5 @@
             uint32_t u32Value;
             if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-                rcStrict = IOMIOPortRead(pVM, u16Port, &u32Value, OP_SIZE / 8);
+                rcStrict = IOMIOPortRead(pVM, pVCpu, u16Port, &u32Value, OP_SIZE / 8);
             else
                 rcStrict = iemVerifyFakeIOPortRead(pIemCpu, u16Port, &u32Value, OP_SIZE / 8);
@@ -1280,5 +1281,5 @@
     {
         if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-            rcStrict = IOMIOPortWrite(pVM, pCtx->dx, uValue, OP_SIZE / 8);
+            rcStrict = IOMIOPortWrite(pVM, IEMCPU_TO_VMCPU(pIemCpu), pCtx->dx, uValue, OP_SIZE / 8);
         else
             rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, pCtx->dx, uValue, OP_SIZE / 8);
@@ -1303,6 +1304,7 @@
 IEM_CIMPL_DEF_1(RT_CONCAT4(iemCImpl_rep_outs_op,OP_SIZE,_addr,ADDR_SIZE), uint8_t, iEffSeg)
 {
-    PVM         pVM  = IEMCPU_TO_VM(pIemCpu);
-    PCPUMCTX    pCtx = pIemCpu->CTX_SUFF(pCtx);
+    PVM         pVM   = IEMCPU_TO_VM(pIemCpu);
+    PVMCPU      pVCpu = IEMCPU_TO_VMCPU(pIemCpu);
+    PCPUMCTX    pCtx  = pIemCpu->CTX_SUFF(pCtx);
 
     /*
@@ -1377,5 +1379,5 @@
                     uint32_t u32Value = *puMem++;
                     if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-                        rcStrict = IOMIOPortWrite(pVM, u16Port, u32Value, OP_SIZE / 8);
+                        rcStrict = IOMIOPortWrite(pVM, pVCpu, u16Port, u32Value, OP_SIZE / 8);
                     else
                         rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, u32Value, OP_SIZE / 8);
@@ -1426,5 +1428,5 @@
 
             if (!IEM_VERIFICATION_ENABLED(pIemCpu))
-                rcStrict = IOMIOPortWrite(pVM, u16Port, uValue, OP_SIZE / 8);
+                rcStrict = IOMIOPortWrite(pVM, pVCpu, u16Port, uValue, OP_SIZE / 8);
             else
                 rcStrict = iemVerifyFakeIOPortWrite(pIemCpu, u16Port, uValue, OP_SIZE / 8);
Index: /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMAll/IOMAll.cpp	(revision 45305)
@@ -220,9 +220,10 @@
  *
  * @param   pVM         Pointer to the VM.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   Port        The port to read.
  * @param   pu32Value   Where to store the value read.
  * @param   cbValue     The size of the register to read in bytes. 1, 2 or 4 bytes.
  */
-VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue)
+VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue)
 {
 /** @todo should initialize *pu32Value here because it can happen that some
@@ -243,10 +244,10 @@
      * Get the statistics record.
      */
-    PIOMIOPORTSTATS  pStats = pVM->iom.s.CTX_SUFF(pStatsLastRead);
+    PIOMIOPORTSTATS  pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastRead);
     if (!pStats || pStats->Core.Key != Port)
     {
         pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);
         if (pStats)
-            pVM->iom.s.CTX_SUFF(pStatsLastRead) = pStats;
+            pVCpu->iom.s.CTX_SUFF(pStatsLastRead) = pStats;
     }
 #endif
@@ -255,5 +256,5 @@
      * Get handler for current context.
      */
-    CTX_SUFF(PIOMIOPORTRANGE) pRange = pVM->iom.s.CTX_SUFF(pRangeLastRead);
+    CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastRead);
     if (    !pRange
         ||   (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)
@@ -261,5 +262,5 @@
         pRange = iomIOPortGetRange(pVM, Port);
         if (pRange)
-            pVM->iom.s.CTX_SUFF(pRangeLastRead) = pRange;
+            pVCpu->iom.s.CTX_SUFF(pRangeLastRead) = pRange;
     }
     MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);
@@ -393,4 +394,5 @@
  *
  * @param   pVM         Pointer to the VM.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   Port        The port to read.
  * @param   pGCPtrDst   Pointer to the destination buffer (GC, incremented appropriately).
@@ -398,5 +400,6 @@
  * @param   cb          Size of the transfer unit (1, 2 or 4 bytes).
  */
-VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb)
+VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port,
+                                          PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb)
 {
     /* Take the IOM lock before performing any device I/O. */
@@ -418,10 +421,10 @@
      * Get the statistics record.
      */
-    PIOMIOPORTSTATS pStats = pVM->iom.s.CTX_SUFF(pStatsLastRead);
+    PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastRead);
     if (!pStats || pStats->Core.Key != Port)
     {
         pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);
         if (pStats)
-            pVM->iom.s.CTX_SUFF(pStatsLastRead) = pStats;
+            pVCpu->iom.s.CTX_SUFF(pStatsLastRead) = pStats;
     }
 #endif
@@ -430,5 +433,5 @@
      * Get handler for current context.
      */
-    CTX_SUFF(PIOMIOPORTRANGE) pRange = pVM->iom.s.CTX_SUFF(pRangeLastRead);
+    CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastRead);
     if (    !pRange
         ||   (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)
@@ -436,5 +439,5 @@
         pRange = iomIOPortGetRange(pVM, Port);
         if (pRange)
-            pVM->iom.s.CTX_SUFF(pRangeLastRead) = pRange;
+            pVCpu->iom.s.CTX_SUFF(pRangeLastRead) = pRange;
     }
     MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);
@@ -545,9 +548,10 @@
  *
  * @param   pVM         Pointer to the VM.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   Port        The port to write to.
  * @param   u32Value    The value to write.
  * @param   cbValue     The size of the register to read in bytes. 1, 2 or 4 bytes.
  */
-VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue)
+VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue)
 {
     /* Take the IOM lock before performing any device I/O. */
@@ -568,10 +572,10 @@
      * Find the statistics record.
      */
-    PIOMIOPORTSTATS pStats = pVM->iom.s.CTX_SUFF(pStatsLastWrite);
+    PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastWrite);
     if (!pStats || pStats->Core.Key != Port)
     {
         pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);
         if (pStats)
-            pVM->iom.s.CTX_SUFF(pStatsLastWrite) = pStats;
+            pVCpu->iom.s.CTX_SUFF(pStatsLastWrite) = pStats;
     }
 #endif
@@ -580,5 +584,5 @@
      * Get handler for current context.
      */
-    CTX_SUFF(PIOMIOPORTRANGE) pRange = pVM->iom.s.CTX_SUFF(pRangeLastWrite);
+    CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastWrite);
     if (    !pRange
         ||   (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)
@@ -586,5 +590,5 @@
         pRange = iomIOPortGetRange(pVM, Port);
         if (pRange)
-            pVM->iom.s.CTX_SUFF(pRangeLastWrite) = pRange;
+            pVCpu->iom.s.CTX_SUFF(pRangeLastWrite) = pRange;
     }
     MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);
@@ -693,10 +697,12 @@
  *
  * @param   pVM         Pointer to the VM.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   Port        The port to write.
  * @param   pGCPtrSrc   Pointer to the source buffer (GC, incremented appropriately).
  * @param   pcTransfers Pointer to the number of transfer units to write, on return remaining transfer units.
  * @param   cb          Size of the transfer unit (1, 2 or 4 bytes).
- *   */
-VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb)
+ */
+VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port,
+                                           PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb)
 {
     /* Take the IOM lock before performing any device I/O. */
@@ -718,10 +724,10 @@
      * Get the statistics record.
      */
-    PIOMIOPORTSTATS     pStats = pVM->iom.s.CTX_SUFF(pStatsLastWrite);
+    PIOMIOPORTSTATS     pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastWrite);
     if (!pStats || pStats->Core.Key != Port)
     {
         pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port);
         if (pStats)
-            pVM->iom.s.CTX_SUFF(pStatsLastWrite) = pStats;
+            pVCpu->iom.s.CTX_SUFF(pStatsLastWrite) = pStats;
     }
 #endif
@@ -730,5 +736,5 @@
      * Get handler for current context.
      */
-    CTX_SUFF(PIOMIOPORTRANGE) pRange = pVM->iom.s.CTX_SUFF(pRangeLastWrite);
+    CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastWrite);
     if (    !pRange
         ||   (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts)
@@ -736,5 +742,5 @@
         pRange = iomIOPortGetRange(pVM, Port);
         if (pRange)
-            pVM->iom.s.CTX_SUFF(pRangeLastWrite) = pRange;
+            pVCpu->iom.s.CTX_SUFF(pRangeLastWrite) = pRange;
     }
     MMHYPER_RC_ASSERT_RCPTR(pVM, pRange);
@@ -947,8 +953,9 @@
  *
  * @param   pVM         The virtual machine (GC pointer of course).
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
  * @param   pCpu        Disassembler CPU state.
  */
-VMMDECL(VBOXSTRICTRC) IOMInterpretIN(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
+VMMDECL(VBOXSTRICTRC) IOMInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
 {
 #ifdef IN_RC
@@ -974,5 +981,5 @@
          */
         uint32_t u32Data = UINT32_C(0xffffffff);
-        rcStrict = IOMIOPortRead(pVM, uPort, &u32Data, cbSize);
+        rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &u32Data, cbSize);
         if (IOM_SUCCESS(rcStrict))
         {
@@ -1007,8 +1014,9 @@
  *
  * @param   pVM         The virtual machine (GC pointer of course).
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
  * @param   pCpu        Disassembler CPU state.
  */
-VMMDECL(VBOXSTRICTRC) IOMInterpretOUT(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
+VMMDECL(VBOXSTRICTRC) IOMInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
 {
 #ifdef IN_RC
@@ -1035,5 +1043,5 @@
          * Attempt to write to the port.
          */
-        rcStrict = IOMIOPortWrite(pVM, uPort, u64Data, cbSize);
+        rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, u64Data, cbSize);
         AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_IOM_R3_IOPORT_WRITE || (rcStrict >= VINF_EM_FIRST && rcStrict <= VINF_EM_LAST) || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     }
Index: /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp	(revision 45305)
@@ -274,8 +274,8 @@
  * @warning RT_SUCCESS(rc=VINF_IOM_R3_MMIO_WRITE) is TRUE!
  */
-static int iomMMIODoWrite(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
+static int iomMMIODoWrite(PVM pVM, PVMCPU pVCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault, const void *pvData, unsigned cb)
 {
 #ifdef VBOX_WITH_STATISTICS
-    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhysFault, pRange);
+    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, pVCpu, GCPhysFault, pRange);
     Assert(pStats);
 #endif
@@ -481,8 +481,8 @@
  * Wrapper which does the read and updates range statistics when such are enabled.
  */
-DECLINLINE(int) iomMMIODoRead(PVM pVM, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, void *pvValue, unsigned cbValue)
+DECLINLINE(int) iomMMIODoRead(PVM pVM, PVMCPU pVCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhys, void *pvValue, unsigned cbValue)
 {
 #ifdef VBOX_WITH_STATISTICS
-    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhys, pRange);
+    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, pVCpu, GCPhys, pRange);
     Assert(pStats);
     STAM_PROFILE_START(&pStats->CTX_SUFF_Z(ProfRead), a);
@@ -557,4 +557,5 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
  * @param   pCpu        Disassembler CPU state.
@@ -562,5 +563,6 @@
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
  */
-static int iomInterpretMOVxXRead(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
+static int iomInterpretMOVxXRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu,
+                                 PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
 {
     Assert(pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
@@ -574,5 +576,5 @@
 
     uint64_t u64Data = 0;
-    int rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &u64Data, cb);
+    int rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &u64Data, cb);
     if (rc == VINF_SUCCESS)
     {
@@ -616,4 +618,5 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
  * @param   pCpu        Disassembler CPU state.
@@ -621,5 +624,6 @@
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
  */
-static int iomInterpretMOVxXWrite(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
+static int iomInterpretMOVxXWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu,
+                                  PIOMMMIORANGE pRange, RTGCPHYS GCPhysFault)
 {
     Assert(pRange->CTX_SUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3);
@@ -634,5 +638,5 @@
     AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);
 
-    int rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, &u64Data, cb);
+    int rc = iomMMIODoWrite(pVM, pVCpu, pRange, GCPhysFault, &u64Data, cb);
     if (rc == VINF_SUCCESS)
         iomMMIOStatLength(pVM, cb);
@@ -950,4 +954,5 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Trap register frame.
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
@@ -955,5 +960,6 @@
  * @param   pRange      Pointer MMIO range.
  */
-static int iomInterpretSTOS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
+static int iomInterpretSTOS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault,
+                            PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
 {
     /*
@@ -1046,5 +1052,5 @@
         do
         {
-            rc = iomMMIODoWrite(pVM, pRange, Phys, &u64Data, cb);
+            rc = iomMMIODoWrite(pVM, pVCpu, pRange, Phys, &u64Data, cb);
             if (rc != VINF_SUCCESS)
                 break;
@@ -1082,4 +1088,5 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Trap register frame.
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
@@ -1087,5 +1094,6 @@
  * @param   pRange      Pointer MMIO range.
  */
-static int iomInterpretLODS(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
+static int iomInterpretLODS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu,
+                            PIOMMMIORANGE pRange)
 {
     Assert(pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
@@ -1107,5 +1115,5 @@
      * Perform read.
      */
-    int rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &pRegFrame->rax, cb);
+    int rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &pRegFrame->rax, cb);
     if (rc == VINF_SUCCESS)
     {
@@ -1139,5 +1147,6 @@
  * @param   pRange      Pointer MMIO range.
  */
-static int iomInterpretCMP(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
+static int iomInterpretCMP(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu,
+                           PIOMMMIORANGE pRange)
 {
     Assert(pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
@@ -1152,8 +1161,8 @@
     if (iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &uData1, &cb))
         /* cmp reg, [MMIO]. */
-        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb);
+        rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData2, cb);
     else if (iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &uData2, &cb))
         /* cmp [MMIO], reg|imm. */
-        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb);
+        rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData1, cb);
     else
     {
@@ -1192,4 +1201,5 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Trap register frame.
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
@@ -1198,5 +1208,6 @@
  * @param   pfnEmulate  Instruction emulation function.
  */
-static int iomInterpretOrXorAnd(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange, PFNEMULATEPARAM3 pfnEmulate)
+static int iomInterpretOrXorAnd(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu,
+                                PIOMMMIORANGE pRange, PFNEMULATEPARAM3 pfnEmulate)
 {
     unsigned    cb     = 0;
@@ -1229,5 +1240,5 @@
         Assert(pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
         fAndWrite = false;
-        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb);
+        rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData2, cb);
     }
     else if (iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &uData2, &cb))
@@ -1242,5 +1253,5 @@
         if (    (pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3)
             &&  (pRange->CTX_SUFF(pfnWriteCallback) || !pRange->pfnWriteCallbackR3))
-            rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb);
+            rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData1, cb);
         else
             rc = VINF_IOM_R3_MMIO_READ_WRITE;
@@ -1261,5 +1272,5 @@
         if (fAndWrite)
             /* Store result to MMIO. */
-            rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, &uData1, cb);
+            rc = iomMMIODoWrite(pVM, pVCpu, pRange, GCPhysFault, &uData1, cb);
         else
         {
@@ -1291,4 +1302,5 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Trap register frame.
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
@@ -1296,5 +1308,6 @@
  * @param   pRange      Pointer MMIO range.
  */
-static int iomInterpretTEST(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
+static int iomInterpretTEST(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu,
+                            PIOMMMIORANGE pRange)
 {
     Assert(pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
@@ -1308,10 +1321,10 @@
     {
         /* and test, [MMIO]. */
-        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb);
+        rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData2, cb);
     }
     else if (iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &uData2, &cb))
     {
         /* test [MMIO], reg|imm. */
-        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb);
+        rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData1, cb);
     }
     else
@@ -1349,4 +1362,5 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Trap register frame.
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
@@ -1354,5 +1368,6 @@
  * @param   pRange      Pointer MMIO range.
  */
-static int iomInterpretBT(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
+static int iomInterpretBT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu,
+                          PIOMMMIORANGE pRange)
 {
     Assert(pRange->CTX_SUFF(pfnReadCallback) || !pRange->pfnReadCallbackR3);
@@ -1371,5 +1386,5 @@
 
     /* bt [MMIO], reg|imm. */
-    int rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData, cbData);
+    int rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData, cbData);
     if (rc == VINF_SUCCESS)
     {
@@ -1392,4 +1407,5 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Trap register frame.
  * @param   GCPhysFault The GC physical address corresponding to pvFault.
@@ -1397,5 +1413,6 @@
  * @param   pRange      Pointer MMIO range.
  */
-static int iomInterpretXCHG(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu, PIOMMMIORANGE pRange)
+static int iomInterpretXCHG(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, PDISCPUSTATE pCpu,
+                            PIOMMMIORANGE pRange)
 {
     /* Check for read & write handlers since IOMMMIOHandler doesn't cover this. */
@@ -1411,9 +1428,9 @@
     {
         /* xchg reg, [MMIO]. */
-        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData2, cb);
+        rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData2, cb);
         if (rc == VINF_SUCCESS)
         {
             /* Store result to MMIO. */
-            rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, &uData1, cb);
+            rc = iomMMIODoWrite(pVM, pVCpu, pRange, GCPhysFault, &uData1, cb);
 
             if (rc == VINF_SUCCESS)
@@ -1432,9 +1449,9 @@
     {
         /* xchg [MMIO], reg. */
-        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, &uData1, cb);
+        rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, &uData1, cb);
         if (rc == VINF_SUCCESS)
         {
             /* Store result to MMIO. */
-            rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, &uData2, cb);
+            rc = iomMMIODoWrite(pVM, pVCpu, pRange, GCPhysFault, &uData2, cb);
             if (rc == VINF_SUCCESS)
             {
@@ -1463,4 +1480,5 @@
  * @returns VBox status code (appropriate for GC return).
  * @param   pVM         Pointer to the VM.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   uErrorCode  CPU Error code.  This is UINT32_MAX when we don't have
  *                      any error code (the EPT misconfig hack).
@@ -1469,7 +1487,6 @@
  * @param   pvUser      Pointer to the MMIO ring-3 range entry.
  */
-static int iomMMIOHandler(PVM pVM, uint32_t uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault, void *pvUser)
-{
-    /* Take the IOM lock before performing any MMIO. */
+static int iomMMIOHandler(PVM pVM, PVMCPU pVCpu, uint32_t uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault, void *pvUser)
+{
     int rc = IOM_LOCK(pVM);
 #ifndef IN_RING3
@@ -1480,10 +1497,9 @@
 
     STAM_PROFILE_START(&pVM->iom.s.StatRZMMIOHandler, a);
-    Log(("iomMMIOHandler: GCPhys=%RGp uErr=%#x rip=%RGv\n",
-         GCPhysFault, uErrorCode, (RTGCPTR)pCtxCore->rip));
+    Log(("iomMMIOHandler: GCPhys=%RGp uErr=%#x rip=%RGv\n", GCPhysFault, uErrorCode, (RTGCPTR)pCtxCore->rip));
 
     PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser;
     Assert(pRange);
-    Assert(pRange == iomMmioGetRange(pVM, GCPhysFault));
+    Assert(pRange == iomMmioGetRange(pVM, pVCpu, GCPhysFault));
 
 #ifdef VBOX_WITH_STATISTICS
@@ -1491,5 +1507,5 @@
      * Locate the statistics, if > PAGE_SIZE we'll use the first byte for everything.
      */
-    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhysFault, pRange);
+    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, pVCpu, GCPhysFault, pRange);
     if (!pStats)
     {
@@ -1550,5 +1566,4 @@
      * Disassemble the instruction and interpret it.
      */
-    PVMCPU          pVCpu = VMMGetCpu(pVM);
     PDISCPUSTATE    pDis  = &pVCpu->iom.s.DisState;
     unsigned        cbOp;
@@ -1571,7 +1586,7 @@
                 ? uErrorCode & X86_TRAP_PF_RW
                 : DISUSE_IS_EFFECTIVE_ADDR(pDis->Param1.fUse))
-                rc = iomInterpretMOVxXWrite(pVM, pCtxCore, pDis, pRange, GCPhysFault);
+                rc = iomInterpretMOVxXWrite(pVM, pVCpu, pCtxCore, pDis, pRange, GCPhysFault);
             else
-                rc = iomInterpretMOVxXRead(pVM, pCtxCore, pDis, pRange, GCPhysFault);
+                rc = iomInterpretMOVxXRead(pVM, pVCpu, pCtxCore, pDis, pRange, GCPhysFault);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstMov, b);
             break;
@@ -1600,5 +1615,5 @@
             Assert(uErrorCode & X86_TRAP_PF_RW);
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstStos, d);
-            rc = iomInterpretSTOS(pVM, pCtxCore, GCPhysFault, pDis, pRange);
+            rc = iomInterpretSTOS(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstStos, d);
             break;
@@ -1608,5 +1623,5 @@
             Assert(!(uErrorCode & X86_TRAP_PF_RW) || uErrorCode == UINT32_MAX);
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstLods, e);
-            rc = iomInterpretLODS(pVM, pCtxCore, GCPhysFault, pDis, pRange);
+            rc = iomInterpretLODS(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstLods, e);
             break;
@@ -1615,5 +1630,5 @@
             Assert(!(uErrorCode & X86_TRAP_PF_RW) || uErrorCode == UINT32_MAX);
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstCmp, f);
-            rc = iomInterpretCMP(pVM, pCtxCore, GCPhysFault, pDis, pRange);
+            rc = iomInterpretCMP(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstCmp, f);
             break;
@@ -1621,5 +1636,5 @@
         case OP_AND:
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstAnd, g);
-            rc = iomInterpretOrXorAnd(pVM, pCtxCore, GCPhysFault, pDis, pRange, EMEmulateAnd);
+            rc = iomInterpretOrXorAnd(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange, EMEmulateAnd);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstAnd, g);
             break;
@@ -1627,5 +1642,5 @@
         case OP_OR:
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstOr, k);
-            rc = iomInterpretOrXorAnd(pVM, pCtxCore, GCPhysFault, pDis, pRange, EMEmulateOr);
+            rc = iomInterpretOrXorAnd(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange, EMEmulateOr);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstOr, k);
             break;
@@ -1633,5 +1648,5 @@
         case OP_XOR:
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstXor, m);
-            rc = iomInterpretOrXorAnd(pVM, pCtxCore, GCPhysFault, pDis, pRange, EMEmulateXor);
+            rc = iomInterpretOrXorAnd(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange, EMEmulateXor);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstXor, m);
             break;
@@ -1640,5 +1655,5 @@
             Assert(!(uErrorCode & X86_TRAP_PF_RW) || uErrorCode == UINT32_MAX);
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstTest, h);
-            rc = iomInterpretTEST(pVM, pCtxCore, GCPhysFault, pDis, pRange);
+            rc = iomInterpretTEST(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstTest, h);
             break;
@@ -1647,5 +1662,5 @@
             Assert(!(uErrorCode & X86_TRAP_PF_RW) || uErrorCode == UINT32_MAX);
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstBt, l);
-            rc = iomInterpretBT(pVM, pCtxCore, GCPhysFault, pDis, pRange);
+            rc = iomInterpretBT(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstBt, l);
             break;
@@ -1653,5 +1668,5 @@
         case OP_XCHG:
             STAM_PROFILE_START(&pVM->iom.s.StatRZInstXchg, i);
-            rc = iomInterpretXCHG(pVM, pCtxCore, GCPhysFault, pDis, pRange);
+            rc = iomInterpretXCHG(pVM, pVCpu, pCtxCore, GCPhysFault, pDis, pRange);
             STAM_PROFILE_STOP(&pVM->iom.s.StatRZInstXchg, i);
             break;
@@ -1710,5 +1725,5 @@
     LogFlow(("IOMMMIOHandler: GCPhys=%RGp uErr=%#x pvFault=%RGv rip=%RGv\n",
              GCPhysFault, (uint32_t)uErrorCode, pvFault, (RTGCPTR)pCtxCore->rip));
-    VBOXSTRICTRC rcStrict = iomMMIOHandler(pVM, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, pvUser);
+    VBOXSTRICTRC rcStrict = iomMMIOHandler(pVM, VMMGetCpu(pVM), (uint32_t)uErrorCode, pCtxCore, GCPhysFault, pvUser);
     return VBOXSTRICTRC_VAL(rcStrict);
 }
@@ -1719,9 +1734,10 @@
  * @returns VBox status code (appropriate for GC return).
  * @param   pVM         Pointer to the VM.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   uErrorCode  CPU Error code.
  * @param   pCtxCore    Trap register frame.
  * @param   GCPhysFault The GC physical address.
  */
-VMMDECL(VBOXSTRICTRC) IOMMMIOPhysHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault)
+VMMDECL(VBOXSTRICTRC) IOMMMIOPhysHandler(PVM pVM, PVMCPU pVCpu, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault)
 {
     int rc2 = IOM_LOCK(pVM); NOREF(rc2);
@@ -1730,5 +1746,6 @@
         return VINF_IOM_R3_MMIO_READ_WRITE;
 #endif
-    VBOXSTRICTRC rcStrict = iomMMIOHandler(pVM, (uint32_t)uErrorCode, pCtxCore, GCPhysFault, iomMmioGetRange(pVM, GCPhysFault));
+    VBOXSTRICTRC rcStrict = iomMMIOHandler(pVM, pVCpu, (uint32_t)uErrorCode, pCtxCore, GCPhysFault,
+                                           iomMmioGetRange(pVM, pVCpu, GCPhysFault));
     IOM_UNLOCK(pVM);
     return VBOXSTRICTRC_VAL(rcStrict);
@@ -1753,4 +1770,5 @@
                                    PGMACCESSTYPE enmAccessType, void *pvUser)
 {
+    PVMCPU        pVCpu = VMMGetCpu(pVM);
     PIOMMMIORANGE pRange = (PIOMMMIORANGE)pvUser;
     STAM_COUNTER_INC(&pVM->iom.s.StatR3MMIOHandler);
@@ -1765,5 +1783,5 @@
     int rc = IOM_LOCK(pVM);
     AssertRC(rc);
-    Assert(pRange == iomMmioGetRange(pVM, GCPhysFault));
+    Assert(pRange == iomMmioGetRange(pVM, pVCpu, GCPhysFault));
 
     /*
@@ -1784,7 +1802,7 @@
      */
     if (enmAccessType == PGMACCESSTYPE_READ)
-        rc = iomMMIODoRead(pVM, pRange, GCPhysFault, pvBuf, (unsigned)cbBuf);
+        rc = iomMMIODoRead(pVM, pVCpu, pRange, GCPhysFault, pvBuf, (unsigned)cbBuf);
     else
-        rc = iomMMIODoWrite(pVM, pRange, GCPhysFault, pvBuf, (unsigned)cbBuf);
+        rc = iomMMIODoWrite(pVM, pVCpu, pRange, GCPhysFault, pvBuf, (unsigned)cbBuf);
 
     AssertRC(rc);
@@ -1802,9 +1820,10 @@
  *
  * @param   pVM         Pointer to the VM.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   GCPhys      The physical address to read.
  * @param   pu32Value   Where to store the value read.
  * @param   cbValue     The size of the register to read in bytes. 1, 2 or 4 bytes.
  */
-VMMDECL(VBOXSTRICTRC) IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue)
+VMMDECL(VBOXSTRICTRC) IOMMMIORead(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue)
 {
     /* Take the IOM lock before performing any MMIO. */
@@ -1822,5 +1841,5 @@
      * Lookup the current context range node and statistics.
      */
-    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhys);
+    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhys);
     if (!pRange)
     {
@@ -1830,5 +1849,5 @@
     }
 #ifdef VBOX_WITH_STATISTICS
-    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhys, pRange);
+    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, pVCpu, GCPhys, pRange);
     if (!pStats)
     {
@@ -1931,9 +1950,10 @@
  *
  * @param   pVM         Pointer to the VM.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   GCPhys      The physical address to write to.
  * @param   u32Value    The value to write.
  * @param   cbValue     The size of the register to read in bytes. 1, 2 or 4 bytes.
  */
-VMMDECL(VBOXSTRICTRC) IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue)
+VMMDECL(VBOXSTRICTRC) IOMMMIOWrite(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue)
 {
     /* Take the IOM lock before performing any MMIO. */
@@ -1951,5 +1971,5 @@
      * Lookup the current context range node.
      */
-    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhys);
+    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhys);
     if (!pRange)
     {
@@ -1959,5 +1979,5 @@
     }
 #ifdef VBOX_WITH_STATISTICS
-    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, GCPhys, pRange);
+    PIOMMMIOSTATS pStats = iomMmioGetStats(pVM, pVCpu, GCPhys, pRange);
     if (!pStats)
     {
@@ -2047,4 +2067,5 @@
  *
  * @param   pVM             The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame       Pointer to CPUMCTXCORE guest registers structure.
  * @param   uPort           IO Port
@@ -2053,5 +2074,5 @@
  * @param   cbTransfer      Size of transfer unit
  */
-VMMDECL(VBOXSTRICTRC) IOMInterpretINSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix,
+VMMDECL(VBOXSTRICTRC) IOMInterpretINSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix,
                                         DISCPUMODE enmAddrMode, uint32_t cbTransfer)
 {
@@ -2065,6 +2086,4 @@
         || pRegFrame->eflags.Bits.u1DF)
         return VINF_EM_RAW_EMULATE_INSTR;
-
-    PVMCPU pVCpu = VMMGetCpu(pVM);
 
     /*
@@ -2113,5 +2132,5 @@
          * much as it wants. The rest is done with single-word transfers. */
         const RTGCUINTREG cTransfersOrg = cTransfers;
-        rcStrict = IOMIOPortReadString(pVM, uPort, &GCPtrDst, &cTransfers, cbTransfer);
+        rcStrict = IOMIOPortReadString(pVM, pVCpu, uPort, &GCPtrDst, &cTransfers, cbTransfer);
         AssertRC(VBOXSTRICTRC_VAL(rcStrict)); Assert(cTransfers <= cTransfersOrg);
         pRegFrame->rdi  = ((pRegFrame->rdi + (cTransfersOrg - cTransfers) * cbTransfer) & fAddrMask)
@@ -2125,5 +2144,5 @@
     {
         uint32_t u32Value;
-        rcStrict = IOMIOPortRead(pVM, uPort, &u32Value, cbTransfer);
+        rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &u32Value, cbTransfer);
         if (!IOM_SUCCESS(rcStrict))
             break;
@@ -2165,8 +2184,9 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
  * @param   pCpu        Disassembler CPU state.
  */
-VMMDECL(VBOXSTRICTRC) IOMInterpretINS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
+VMMDECL(VBOXSTRICTRC) IOMInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
 {
     /*
@@ -2188,5 +2208,5 @@
     }
 
-    return IOMInterpretINSEx(pVM, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);
+    return IOMInterpretINSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);
 }
 
@@ -2209,4 +2229,5 @@
  *
  * @param   pVM             The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame       Pointer to CPUMCTXCORE guest registers structure.
  * @param   uPort           IO Port
@@ -2215,5 +2236,5 @@
  * @param   cbTransfer      Size of transfer unit
  */
-VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix,
+VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix,
                                          DISCPUMODE enmAddrMode, uint32_t cbTransfer)
 {
@@ -2227,6 +2248,4 @@
         || pRegFrame->eflags.Bits.u1DF)
         return VINF_EM_RAW_EMULATE_INSTR;
-
-    PVMCPU pVCpu = VMMGetCpu(pVM);
 
     /*
@@ -2277,5 +2296,5 @@
          */
         const RTGCUINTREG cTransfersOrg = cTransfers;
-        rcStrict = IOMIOPortWriteString(pVM, uPort, &GCPtrSrc, &cTransfers, cbTransfer);
+        rcStrict = IOMIOPortWriteString(pVM, pVCpu, uPort, &GCPtrSrc, &cTransfers, cbTransfer);
         AssertRC(VBOXSTRICTRC_VAL(rcStrict)); Assert(cTransfers <= cTransfersOrg);
         pRegFrame->rsi  = ((pRegFrame->rsi + (cTransfersOrg - cTransfers) * cbTransfer) & fAddrMask)
@@ -2293,5 +2312,5 @@
         if (rcStrict != VINF_SUCCESS)
             break;
-        rcStrict = IOMIOPortWrite(pVM, uPort, u32Value, cbTransfer);
+        rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, u32Value, cbTransfer);
         if (!IOM_SUCCESS(rcStrict))
             break;
@@ -2332,8 +2351,9 @@
  *
  * @param   pVM         The virtual machine.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
  * @param   pCpu        Disassembler CPU state.
  */
-VMMDECL(VBOXSTRICTRC) IOMInterpretOUTS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
+VMMDECL(VBOXSTRICTRC) IOMInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
 {
     /*
@@ -2357,5 +2377,5 @@
     }
 
-    return IOMInterpretOUTSEx(pVM, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);
+    return IOMInterpretOUTSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);
 }
 
@@ -2396,5 +2416,5 @@
      * Lookup the context range node the page belongs to.
      */
-    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhys);
+    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhys);
     AssertMsgReturn(pRange,
                     ("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND);
@@ -2461,5 +2481,5 @@
 #ifdef VBOX_STRICT
     /* Can't lock IOM here due to potential deadlocks in the VGA device; not safe to access. */
-    PIOMMMIORANGE pRange = iomMMIOGetRangeUnsafe(pVM, GCPhys);
+    PIOMMMIORANGE pRange = iomMMIOGetRangeUnsafe(pVM, pVCpu, GCPhys);
     AssertMsgReturn(pRange,
             ("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND);
@@ -2514,5 +2534,5 @@
 #ifdef VBOX_STRICT
     /* Can't lock IOM here due to potential deadlocks in the VGA device; not safe to access. */
-    PIOMMMIORANGE pRange = iomMMIOGetRangeUnsafe(pVM, GCPhys);
+    PIOMMMIORANGE pRange = iomMMIOGetRangeUnsafe(pVM, pVCpu, GCPhys);
     AssertMsgReturn(pRange,
             ("Handlers and page tables are out of sync or something! GCPhys=%RGp\n", GCPhys), VERR_IOM_MMIO_RANGE_NOT_FOUND);
Index: /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 45305)
@@ -2475,5 +2475,5 @@
                     Log2(("IOMInterpretOUTSEx %RGv %x size=%d\n", (RTGCPTR)pCtx->rip, IoExitInfo.n.u16Port, uIOSize));
                     STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOStringWrite);
-                    rc = IOMInterpretOUTSEx(pVM, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix,
+                    rc = IOMInterpretOUTSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix,
                                             (DISCPUMODE)pDis->uAddrMode, uIOSize);
                 }
@@ -2482,5 +2482,5 @@
                     Log2(("IOMInterpretINSEx  %RGv %x size=%d\n", (RTGCPTR)pCtx->rip, IoExitInfo.n.u16Port, uIOSize));
                     STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOStringRead);
-                    rc = IOMInterpretINSEx(pVM, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix,
+                    rc = IOMInterpretINSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix,
                                            (DISCPUMODE)pDis->uAddrMode, uIOSize);
                 }
@@ -2499,5 +2499,5 @@
                       uIOSize));
                 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
-                rc = IOMIOPortWrite(pVM, IoExitInfo.n.u16Port, pCtx->eax & uAndVal, uIOSize);
+                rc = IOMIOPortWrite(pVM, pVCpu, IoExitInfo.n.u16Port, pCtx->eax & uAndVal, uIOSize);
                 if (rc == VINF_IOM_R3_IOPORT_WRITE)
                 {
@@ -2511,5 +2511,5 @@
 
                 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
-                rc = IOMIOPortRead(pVM, IoExitInfo.n.u16Port, &u32Val, uIOSize);
+                rc = IOMIOPortRead(pVM, pVCpu, IoExitInfo.n.u16Port, &u32Val, uIOSize);
                 if (IOM_SUCCESS(rc))
                 {
Index: /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 45305)
@@ -4609,5 +4609,6 @@
                     Log2(("IOMInterpretOUTSEx %RGv %x size=%d\n", (RTGCPTR)pCtx->rip, uPort, cbSize));
                     STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOStringWrite);
-                    rc = IOMInterpretOUTSEx(pVM, CPUMCTX2CORE(pCtx), uPort, pDis->fPrefix, (DISCPUMODE)pDis->uAddrMode, cbSize);
+                    rc = IOMInterpretOUTSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), uPort, pDis->fPrefix,
+                                            (DISCPUMODE)pDis->uAddrMode, cbSize);
                 }
                 else
@@ -4615,5 +4616,6 @@
                     Log2(("IOMInterpretINSEx  %RGv %x size=%d\n", (RTGCPTR)pCtx->rip, uPort, cbSize));
                     STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOStringRead);
-                    rc = IOMInterpretINSEx(pVM, CPUMCTX2CORE(pCtx), uPort, pDis->fPrefix, (DISCPUMODE)pDis->uAddrMode, cbSize);
+                    rc = IOMInterpretINSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), uPort, pDis->fPrefix,
+                                           (DISCPUMODE)pDis->uAddrMode, cbSize);
                 }
             }
@@ -4631,5 +4633,5 @@
             {
                 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
-                rc = IOMIOPortWrite(pVM, uPort, pCtx->eax & uAndVal, cbSize);
+                rc = IOMIOPortWrite(pVM, pVCpu, uPort, pCtx->eax & uAndVal, cbSize);
                 if (rc == VINF_IOM_R3_IOPORT_WRITE)
                     HMR0SavePendingIOPortWrite(pVCpu, pCtx->rip, pCtx->rip + cbInstr, uPort, uAndVal, cbSize);
@@ -4640,5 +4642,5 @@
 
                 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
-                rc = IOMIOPortRead(pVM, uPort, &u32Val, cbSize);
+                rc = IOMIOPortRead(pVM, pVCpu, uPort, &u32Val, cbSize);
                 if (IOM_SUCCESS(rc))
                 {
@@ -4763,5 +4765,5 @@
 
                 LogFlow(("Apic access at %RGp\n", GCPhys));
-                rc = IOMMMIOPhysHandler(pVM, (uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ) ? 0 : X86_TRAP_PF_RW,
+                rc = IOMMMIOPhysHandler(pVM, pVCpu, (uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ) ? 0 : X86_TRAP_PF_RW,
                                         CPUMCTX2CORE(pCtx), GCPhys);
                 if (rc == VINF_SUCCESS)
Index: /trunk/src/VBox/VMM/VMMR3/EMHM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/EMHM.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMR3/EMHM.cpp	(revision 45305)
@@ -313,5 +313,5 @@
                 {
                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIn);
-                    rcStrict = IOMInterpretIN(pVM, CPUMCTX2CORE(pCtx), &Cpu);
+                    rcStrict = IOMInterpretIN(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu);
                     break;
                 }
@@ -320,5 +320,5 @@
                 {
                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatOut);
-                    rcStrict = IOMInterpretOUT(pVM, CPUMCTX2CORE(pCtx), &Cpu);
+                    rcStrict = IOMInterpretOUT(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu);
                     break;
                 }
@@ -333,5 +333,5 @@
                 {
                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIn);
-                    rcStrict = IOMInterpretINS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
+                    rcStrict = IOMInterpretINS(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu);
                     break;
                 }
@@ -341,5 +341,5 @@
                 {
                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatOut);
-                    rcStrict = IOMInterpretOUTS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
+                    rcStrict = IOMInterpretOUTS(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu);
                     break;
                 }
Index: /trunk/src/VBox/VMM/VMMR3/EMRaw.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/EMRaw.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMR3/EMRaw.cpp	(revision 45305)
@@ -435,5 +435,5 @@
                 {
                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIn);
-                    rcStrict = IOMInterpretIN(pVM, CPUMCTX2CORE(pCtx), &Cpu);
+                    rcStrict = IOMInterpretIN(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu);
                     break;
                 }
@@ -442,5 +442,5 @@
                 {
                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatOut);
-                    rcStrict = IOMInterpretOUT(pVM, CPUMCTX2CORE(pCtx), &Cpu);
+                    rcStrict = IOMInterpretOUT(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu);
                     break;
                 }
@@ -455,5 +455,5 @@
                 {
                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatIn);
-                    rcStrict = IOMInterpretINS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
+                    rcStrict = IOMInterpretINS(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu);
                     break;
                 }
@@ -463,5 +463,5 @@
                 {
                     STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->StatOut);
-                    rcStrict = IOMInterpretOUTS(pVM, CPUMCTX2CORE(pCtx), &Cpu);
+                    rcStrict = IOMInterpretOUTS(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu);
                     break;
                 }
Index: /trunk/src/VBox/VMM/VMMR3/HM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 45305)
@@ -2552,5 +2552,5 @@
             uint32_t u32Val  = 0;
 
-            rcStrict = IOMIOPortRead(pVM, pVCpu->hm.s.PendingIO.s.Port.uPort,
+            rcStrict = IOMIOPortRead(pVM, pVCpu, pVCpu->hm.s.PendingIO.s.Port.uPort,
                                      &u32Val,
                                      pVCpu->hm.s.PendingIO.s.Port.cbSize);
@@ -2565,5 +2565,5 @@
 
         case HMPENDINGIO_PORT_WRITE:
-            rcStrict = IOMIOPortWrite(pVM, pVCpu->hm.s.PendingIO.s.Port.uPort,
+            rcStrict = IOMIOPortWrite(pVM, pVCpu, pVCpu->hm.s.PendingIO.s.Port.uPort,
                                       pCtx->eax & pVCpu->hm.s.PendingIO.s.Port.uAndVal,
                                       pVCpu->hm.s.PendingIO.s.Port.cbSize);
Index: /trunk/src/VBox/VMM/VMMR3/IOM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/IOM.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMR3/IOM.cpp	(revision 45305)
@@ -238,29 +238,37 @@
 static void iomR3FlushCache(PVM pVM)
 {
+    /*
+     * Since all relevant (1) cache use requires at least read access to the
+     * critical section, we can exclude all other EMTs by grabbing exclusive
+     * access to the critical section and then safely update the caches of
+     * other EMTs.
+     * (1) The irrelvant access not holding the lock is in assertion code.
+     */
     IOM_LOCK(pVM);
-
-    /*
-     * Caching of port and statistics (saves some time in rep outs/ins instruction emulation)
-     */
-    pVM->iom.s.pRangeLastReadR0  = NIL_RTR0PTR;
-    pVM->iom.s.pRangeLastWriteR0 = NIL_RTR0PTR;
-    pVM->iom.s.pStatsLastReadR0  = NIL_RTR0PTR;
-    pVM->iom.s.pStatsLastWriteR0 = NIL_RTR0PTR;
-    pVM->iom.s.pMMIORangeLastR0  = NIL_RTR0PTR;
-    pVM->iom.s.pMMIOStatsLastR0  = NIL_RTR0PTR;
-
-    pVM->iom.s.pRangeLastReadR3  = NULL;
-    pVM->iom.s.pRangeLastWriteR3 = NULL;
-    pVM->iom.s.pStatsLastReadR3  = NULL;
-    pVM->iom.s.pStatsLastWriteR3 = NULL;
-    pVM->iom.s.pMMIORangeLastR3  = NULL;
-    pVM->iom.s.pMMIOStatsLastR3  = NULL;
-
-    pVM->iom.s.pRangeLastReadRC  = NIL_RTRCPTR;
-    pVM->iom.s.pRangeLastWriteRC = NIL_RTRCPTR;
-    pVM->iom.s.pStatsLastReadRC  = NIL_RTRCPTR;
-    pVM->iom.s.pStatsLastWriteRC = NIL_RTRCPTR;
-    pVM->iom.s.pMMIORangeLastRC  = NIL_RTRCPTR;
-    pVM->iom.s.pMMIOStatsLastRC  = NIL_RTRCPTR;
+    VMCPUID iCpu = pVM->cCpus;
+    while (iCpu-- > 0)
+    {
+        PVMCPU pVCpu = &pVM->aCpus[iCpu];
+        pVCpu->iom.s.pRangeLastReadR0  = NIL_RTR0PTR;
+        pVCpu->iom.s.pRangeLastWriteR0 = NIL_RTR0PTR;
+        pVCpu->iom.s.pStatsLastReadR0  = NIL_RTR0PTR;
+        pVCpu->iom.s.pStatsLastWriteR0 = NIL_RTR0PTR;
+        pVCpu->iom.s.pMMIORangeLastR0  = NIL_RTR0PTR;
+        pVCpu->iom.s.pMMIOStatsLastR0  = NIL_RTR0PTR;
+
+        pVCpu->iom.s.pRangeLastReadR3  = NULL;
+        pVCpu->iom.s.pRangeLastWriteR3 = NULL;
+        pVCpu->iom.s.pStatsLastReadR3  = NULL;
+        pVCpu->iom.s.pStatsLastWriteR3 = NULL;
+        pVCpu->iom.s.pMMIORangeLastR3  = NULL;
+        pVCpu->iom.s.pMMIOStatsLastR3  = NULL;
+
+        pVCpu->iom.s.pRangeLastReadRC  = NIL_RTRCPTR;
+        pVCpu->iom.s.pRangeLastWriteRC = NIL_RTRCPTR;
+        pVCpu->iom.s.pStatsLastReadRC  = NIL_RTRCPTR;
+        pVCpu->iom.s.pStatsLastWriteRC = NIL_RTRCPTR;
+        pVCpu->iom.s.pMMIORangeLastRC  = NIL_RTRCPTR;
+        pVCpu->iom.s.pMMIOStatsLastRC  = NIL_RTRCPTR;
+    }
 
     IOM_UNLOCK(pVM);
@@ -304,18 +312,17 @@
 
     /*
-     * Apply relocations to the cached GC handlers
-     */
-    if (pVM->iom.s.pRangeLastReadRC)
-        pVM->iom.s.pRangeLastReadRC  += offDelta;
-    if (pVM->iom.s.pRangeLastWriteRC)
-        pVM->iom.s.pRangeLastWriteRC += offDelta;
-    if (pVM->iom.s.pStatsLastReadRC)
-        pVM->iom.s.pStatsLastReadRC  += offDelta;
-    if (pVM->iom.s.pStatsLastWriteRC)
-        pVM->iom.s.pStatsLastWriteRC += offDelta;
-    if (pVM->iom.s.pMMIORangeLastRC)
-        pVM->iom.s.pMMIORangeLastRC  += offDelta;
-    if (pVM->iom.s.pMMIOStatsLastRC)
-        pVM->iom.s.pMMIOStatsLastRC  += offDelta;
+     * Reset the raw-mode cache (don't bother relocating it).
+     */
+    VMCPUID iCpu = pVM->cCpus;
+    while (iCpu-- > 0)
+    {
+        PVMCPU pVCpu = &pVM->aCpus[iCpu];
+        pVCpu->iom.s.pRangeLastReadRC  = NIL_RTRCPTR;
+        pVCpu->iom.s.pRangeLastWriteRC = NIL_RTRCPTR;
+        pVCpu->iom.s.pStatsLastReadRC  = NIL_RTRCPTR;
+        pVCpu->iom.s.pStatsLastWriteRC = NIL_RTRCPTR;
+        pVCpu->iom.s.pMMIORangeLastRC  = NIL_RTRCPTR;
+        pVCpu->iom.s.pMMIOStatsLastRC  = NIL_RTRCPTR;
+    }
 }
 
@@ -1317,82 +1324,4 @@
                     sizeof(RTRCPTR) * 2,      "pvUser          ");
     RTAvlroIOPortDoWithAll(&pVM->iom.s.pTreesR3->IOPortTreeRC, true, iomR3IOPortInfoOneRC, (void *)pHlp);
-
-    if (pVM->iom.s.pRangeLastReadRC)
-    {
-        PIOMIOPORTRANGERC pRange = (PIOMIOPORTRANGERC)MMHyperRCToCC(pVM, pVM->iom.s.pRangeLastReadRC);
-        pHlp->pfnPrintf(pHlp, "RC Read  Ports: %#04x-%#04x %RRv %s\n",
-                        pRange->Port, pRange->Port + pRange->cPorts, pVM->iom.s.pRangeLastReadRC, pRange->pszDesc);
-    }
-    if (pVM->iom.s.pStatsLastReadRC)
-    {
-        PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperRCToCC(pVM, pVM->iom.s.pStatsLastReadRC);
-        pHlp->pfnPrintf(pHlp, "RC Read  Stats: %#04x %RRv\n",
-                        pRange->Core.Key, pVM->iom.s.pStatsLastReadRC);
-    }
-
-    if (pVM->iom.s.pRangeLastWriteRC)
-    {
-        PIOMIOPORTRANGERC pRange = (PIOMIOPORTRANGERC)MMHyperRCToCC(pVM, pVM->iom.s.pRangeLastWriteRC);
-        pHlp->pfnPrintf(pHlp, "RC Write Ports: %#04x-%#04x %RRv %s\n",
-                        pRange->Port, pRange->Port + pRange->cPorts, pVM->iom.s.pRangeLastWriteRC, pRange->pszDesc);
-    }
-    if (pVM->iom.s.pStatsLastWriteRC)
-    {
-        PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperRCToCC(pVM, pVM->iom.s.pStatsLastWriteRC);
-        pHlp->pfnPrintf(pHlp, "RC Write Stats: %#04x %RRv\n",
-                        pRange->Core.Key, pVM->iom.s.pStatsLastWriteRC);
-    }
-
-    if (pVM->iom.s.pRangeLastReadR3)
-    {
-        PIOMIOPORTRANGER3 pRange = pVM->iom.s.pRangeLastReadR3;
-        pHlp->pfnPrintf(pHlp, "R3 Read  Ports: %#04x-%#04x %p %s\n",
-                        pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc);
-    }
-    if (pVM->iom.s.pStatsLastReadR3)
-    {
-        PIOMIOPORTSTATS pRange = pVM->iom.s.pStatsLastReadR3;
-        pHlp->pfnPrintf(pHlp, "R3 Read  Stats: %#04x %p\n",
-                        pRange->Core.Key, pRange);
-    }
-
-    if (pVM->iom.s.pRangeLastWriteR3)
-    {
-        PIOMIOPORTRANGER3 pRange = pVM->iom.s.pRangeLastWriteR3;
-        pHlp->pfnPrintf(pHlp, "R3 Write Ports: %#04x-%#04x %p %s\n",
-                        pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc);
-    }
-    if (pVM->iom.s.pStatsLastWriteR3)
-    {
-        PIOMIOPORTSTATS pRange = pVM->iom.s.pStatsLastWriteR3;
-        pHlp->pfnPrintf(pHlp, "R3 Write Stats: %#04x %p\n",
-                        pRange->Core.Key, pRange);
-    }
-
-    if (pVM->iom.s.pRangeLastReadR0)
-    {
-        PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)MMHyperR0ToCC(pVM, pVM->iom.s.pRangeLastReadR0);
-        pHlp->pfnPrintf(pHlp, "R0 Read  Ports: %#04x-%#04x %p %s\n",
-                        pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc);
-    }
-    if (pVM->iom.s.pStatsLastReadR0)
-    {
-        PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperR0ToCC(pVM, pVM->iom.s.pStatsLastReadR0);
-        pHlp->pfnPrintf(pHlp, "R0 Read  Stats: %#04x %p\n",
-                        pRange->Core.Key, pRange);
-    }
-
-    if (pVM->iom.s.pRangeLastWriteR0)
-    {
-        PIOMIOPORTRANGER0 pRange = (PIOMIOPORTRANGER0)MMHyperR0ToCC(pVM, pVM->iom.s.pRangeLastWriteR0);
-        pHlp->pfnPrintf(pHlp, "R0 Write Ports: %#04x-%#04x %p %s\n",
-                        pRange->Port, pRange->Port + pRange->cPorts, pRange, pRange->pszDesc);
-    }
-    if (pVM->iom.s.pStatsLastWriteR0)
-    {
-        PIOMIOPORTSTATS pRange = (PIOMIOPORTSTATS)MMHyperR0ToCC(pVM, pVM->iom.s.pStatsLastWriteR0);
-        pHlp->pfnPrintf(pHlp, "R0 Write Stats: %#04x %p\n",
-                        pRange->Core.Key, pRange);
-    }
 }
 
@@ -1532,4 +1461,5 @@
  * @param   pfnReadCallback     Pointer to function which is gonna handle Read operations.
  * @param   pfnFillCallback     Pointer to function which is gonna handle Fill/memset operations.
+ * @thread  EMT
  */
 VMMR3_INT_DECL(int)
@@ -1549,4 +1479,5 @@
         return VERR_INVALID_PARAMETER;
     }
+    PVMCPU pVCpu = VMMGetCpu(pVM); Assert(pVCpu);
 
     /*
@@ -1554,5 +1485,5 @@
      */
     IOM_LOCK(pVM);
-    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhysStart);
+    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhysStart);
     AssertReturnStmt(pRange, IOM_UNLOCK(pVM), VERR_IOM_MMIO_RANGE_NOT_FOUND);
     AssertReturnStmt(pRange->pDevInsR3 == pDevIns, IOM_UNLOCK(pVM), VERR_IOM_NOT_MMIO_RANGE_OWNER);
@@ -1588,4 +1519,5 @@
  * @param   pfnReadCallback     Pointer to function which is gonna handle Read operations.
  * @param   pfnFillCallback     Pointer to function which is gonna handle Fill/memset operations.
+ * @thread  EMT
  */
 VMMR3_INT_DECL(int)
@@ -1606,4 +1538,5 @@
         return VERR_INVALID_PARAMETER;
     }
+    PVMCPU pVCpu = VMMGetCpu(pVM); Assert(pVCpu);
 
     /*
@@ -1611,5 +1544,5 @@
      */
     IOM_LOCK(pVM);
-    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhysStart);
+    PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhysStart);
     AssertReturnStmt(pRange, IOM_UNLOCK(pVM), VERR_IOM_MMIO_RANGE_NOT_FOUND);
     AssertReturnStmt(pRange->pDevInsR3 == pDevIns, IOM_UNLOCK(pVM), VERR_IOM_NOT_MMIO_RANGE_OWNER);
@@ -1656,4 +1589,5 @@
         return VERR_IOM_INVALID_MMIO_RANGE;
     }
+    PVMCPU pVCpu = VMMGetCpu(pVM); Assert(pVCpu);
 
     IOM_LOCK(pVM);
@@ -1665,5 +1599,5 @@
     while (GCPhys <= GCPhysLast && GCPhys >= GCPhysStart)
     {
-        PIOMMMIORANGE pRange = iomMmioGetRange(pVM, GCPhys);
+        PIOMMMIORANGE pRange = iomMmioGetRange(pVM, pVCpu, GCPhys);
         if (!pRange)
         {
Index: /trunk/src/VBox/VMM/VMMRC/IOMRC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/IOMRC.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMRC/IOMRC.cpp	(revision 45305)
@@ -62,24 +62,25 @@
  *
  * @param   pVM         The virtual machine handle.
+ * @param   pVCpu       Pointer to the virtual CPU structure of the caller.
  * @param   pRegFrame   Pointer to CPUMCTXCORE guest registers structure.
  * @param   pCpu        Disassembler CPU state.
  */
-VMMRCDECL(VBOXSTRICTRC) IOMRCIOPortHandler(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
+VMMRCDECL(VBOXSTRICTRC) IOMRCIOPortHandler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
 {
     switch (pCpu->pCurInstr->uOpcode)
     {
         case OP_IN:
-            return IOMInterpretIN(pVM, pRegFrame, pCpu);
+            return IOMInterpretIN(pVM, pVCpu, pRegFrame, pCpu);
 
         case OP_OUT:
-            return IOMInterpretOUT(pVM, pRegFrame, pCpu);
+            return IOMInterpretOUT(pVM, pVCpu, pRegFrame, pCpu);
 
         case OP_INSB:
         case OP_INSWD:
-            return IOMInterpretINS(pVM, pRegFrame, pCpu);
+            return IOMInterpretINS(pVM, pVCpu, pRegFrame, pCpu);
 
         case OP_OUTSB:
         case OP_OUTSWD:
-            return IOMInterpretOUTS(pVM, pRegFrame, pCpu);
+            return IOMInterpretOUTS(pVM, pVCpu, pRegFrame, pCpu);
 
         /*
Index: /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 45304)
+++ /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 45305)
@@ -1072,5 +1072,5 @@
         &&  (Cpu.pCurInstr->fOpType & DISOPTYPE_PORTIO))
     {
-        VBOXSTRICTRC rcStrict = IOMRCIOPortHandler(pVM, pRegFrame, &Cpu);
+        VBOXSTRICTRC rcStrict = IOMRCIOPortHandler(pVM, pVCpu, pRegFrame, &Cpu);
         if (IOM_SUCCESS(rcStrict))
             pRegFrame->rip += cbOp;
Index: /trunk/src/VBox/VMM/include/IOMInline.h
===================================================================
--- /trunk/src/VBox/VMM/include/IOMInline.h	(revision 45304)
+++ /trunk/src/VBox/VMM/include/IOMInline.h	(revision 45305)
@@ -63,13 +63,14 @@
  *
  * @param   pVM     Pointer to the VM.
- * @param   GCPhys  Physical address to lookup.
- */
-DECLINLINE(PIOMMMIORANGE) iomMmioGetRange(PVM pVM, RTGCPHYS GCPhys)
+ * @param   pVCpu   Pointer to the virtual CPU structure of the caller.
+ * @param   GCPhys  Physical address to lookup.
+ */
+DECLINLINE(PIOMMMIORANGE) iomMmioGetRange(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)
 {
     Assert(IOM_IS_SHARED_LOCK_OWNER(pVM));
-    PIOMMMIORANGE pRange = pVM->iom.s.CTX_SUFF(pMMIORangeLast);
+    PIOMMMIORANGE pRange = pVCpu->iom.s.CTX_SUFF(pMMIORangeLast);
     if (    !pRange
         ||  GCPhys - pRange->GCPhys >= pRange->cb)
-        pVM->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
+        pVCpu->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
             = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
     return pRange;
@@ -98,15 +99,16 @@
  *
  * @param   pVM     Pointer to the VM.
- * @param   GCPhys  Physical address to lookup.
- */
-DECLINLINE(PIOMMMIORANGE) iomMmioGetRangeWithRef(PVM pVM, RTGCPHYS GCPhys)
+ * @param   pVCpu   Pointer to the virtual CPU structure of the caller.
+ * @param   GCPhys  Physical address to lookup.
+ */
+DECLINLINE(PIOMMMIORANGE) iomMmioGetRangeWithRef(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)
 {
     int rc = IOM_LOCK_SHARED_EX(pVM, VINF_SUCCESS);
     AssertRCReturn(rc, NULL);
 
-    PIOMMMIORANGE pRange = pVM->iom.s.CTX_SUFF(pMMIORangeLast);
+    PIOMMMIORANGE pRange = pVCpu->iom.s.CTX_SUFF(pMMIORangeLast);
     if (   !pRange
         || GCPhys - pRange->GCPhys >= pRange->cb)
-        pVM->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
+        pVCpu->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
             = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
     if (pRange)
@@ -140,12 +142,13 @@
  *
  * @param   pVM     Pointer to the VM.
- * @param   GCPhys  Physical address to lookup.
- */
-DECLINLINE(PIOMMMIORANGE) iomMMIOGetRangeUnsafe(PVM pVM, RTGCPHYS GCPhys)
-{
-    PIOMMMIORANGE pRange = pVM->iom.s.CTX_SUFF(pMMIORangeLast);
+ * @param   pVCpu   Pointer to the virtual CPU structure of the caller.
+ * @param   GCPhys  Physical address to lookup.
+ */
+DECLINLINE(PIOMMMIORANGE) iomMMIOGetRangeUnsafe(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys)
+{
+    PIOMMMIORANGE pRange = pVCpu->iom.s.CTX_SUFF(pMMIORangeLast);
     if (    !pRange
         ||  GCPhys - pRange->GCPhys >= pRange->cb)
-        pVM->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
+        pVCpu->iom.s.CTX_SUFF(pMMIORangeLast) = pRange
             = (PIOMMMIORANGE)RTAvlroGCPhysRangeGet(&pVM->iom.s.CTX_SUFF(pTrees)->MMIOTree, GCPhys);
     return pRange;
@@ -164,9 +167,10 @@
  * @returns NULL if not found (R0/GC), or out of memory (R3).
  *
- * @param   pVM         Pointer to the VM.
- * @param   GCPhys      Physical address to lookup.
- * @param   pRange      The MMIO range.
- */
-DECLINLINE(PIOMMMIOSTATS) iomMmioGetStats(PVM pVM, RTGCPHYS GCPhys, PIOMMMIORANGE pRange)
+ * @param   pVM     Pointer to the VM.
+ * @param   pVCpu   Pointer to the virtual CPU structure of the caller.
+ * @param   GCPhys  Physical address to lookup.
+ * @param   pRange  The MMIO range.
+ */
+DECLINLINE(PIOMMMIOSTATS) iomMmioGetStats(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, PIOMMMIORANGE pRange)
 {
     IOM_LOCK_SHARED_EX(pVM, VINF_SUCCESS);
@@ -176,5 +180,5 @@
         GCPhys = pRange->GCPhys;
 
-    PIOMMMIOSTATS pStats = pVM->iom.s.CTX_SUFF(pMMIOStatsLast);
+    PIOMMMIOSTATS pStats = pVCpu->iom.s.CTX_SUFF(pMMIOStatsLast);
     if (    !pStats
         ||  pStats->Core.Key != GCPhys)
Index: /trunk/src/VBox/VMM/include/IOMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IOMInternal.h	(revision 45304)
+++ /trunk/src/VBox/VMM/include/IOMInternal.h	(revision 45305)
@@ -335,29 +335,4 @@
 #endif
 
-    /** @name Caching of I/O Port and MMIO ranges and statistics.
-     * (Saves quite some time in rep outs/ins instruction emulation.)
-     * @{ */
-    R3PTRTYPE(PIOMIOPORTRANGER3)    pRangeLastReadR3;
-    R3PTRTYPE(PIOMIOPORTRANGER3)    pRangeLastWriteR3;
-    R3PTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadR3;
-    R3PTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteR3;
-    R3PTRTYPE(PIOMMMIORANGE)        pMMIORangeLastR3;
-    R3PTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastR3;
-
-    R0PTRTYPE(PIOMIOPORTRANGER0)    pRangeLastReadR0;
-    R0PTRTYPE(PIOMIOPORTRANGER0)    pRangeLastWriteR0;
-    R0PTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadR0;
-    R0PTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteR0;
-    R0PTRTYPE(PIOMMMIORANGE)        pMMIORangeLastR0;
-    R0PTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastR0;
-
-    RCPTRTYPE(PIOMIOPORTRANGERC)    pRangeLastReadRC;
-    RCPTRTYPE(PIOMIOPORTRANGERC)    pRangeLastWriteRC;
-    RCPTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadRC;
-    RCPTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteRC;
-    RCPTRTYPE(PIOMMMIORANGE)        pMMIORangeLastRC;
-    RCPTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastRC;
-    /** @} */
-
     /** @name I/O Port statistics.
      * @{ */
@@ -414,4 +389,29 @@
      * on the stack. */
     DISCPUSTATE                     DisState;
+
+    /** @name Caching of I/O Port and MMIO ranges and statistics.
+     * (Saves quite some time in rep outs/ins instruction emulation.)
+     * @{ */
+    R3PTRTYPE(PIOMIOPORTRANGER3)    pRangeLastReadR3;
+    R3PTRTYPE(PIOMIOPORTRANGER3)    pRangeLastWriteR3;
+    R3PTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadR3;
+    R3PTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteR3;
+    R3PTRTYPE(PIOMMMIORANGE)        pMMIORangeLastR3;
+    R3PTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastR3;
+
+    R0PTRTYPE(PIOMIOPORTRANGER0)    pRangeLastReadR0;
+    R0PTRTYPE(PIOMIOPORTRANGER0)    pRangeLastWriteR0;
+    R0PTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadR0;
+    R0PTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteR0;
+    R0PTRTYPE(PIOMMMIORANGE)        pMMIORangeLastR0;
+    R0PTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastR0;
+
+    RCPTRTYPE(PIOMIOPORTRANGERC)    pRangeLastReadRC;
+    RCPTRTYPE(PIOMIOPORTRANGERC)    pRangeLastWriteRC;
+    RCPTRTYPE(PIOMIOPORTSTATS)      pStatsLastReadRC;
+    RCPTRTYPE(PIOMIOPORTSTATS)      pStatsLastWriteRC;
+    RCPTRTYPE(PIOMMMIORANGE)        pMMIORangeLastRC;
+    RCPTRTYPE(PIOMMMIOSTATS)        pMMIOStatsLastRC;
+    /** @} */
 } IOMCPU;
 /** Pointer to IOM per virtual CPU instance data. */
Index: /trunk/src/VBox/VMM/testcase/tstVMStruct.h
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstVMStruct.h	(revision 45304)
+++ /trunk/src/VBox/VMM/testcase/tstVMStruct.h	(revision 45305)
@@ -276,15 +276,15 @@
     GEN_CHECK_OFF(IOM, pTreesR3);
     GEN_CHECK_OFF(IOM, pTreesR0);
-    GEN_CHECK_OFF(IOM, pMMIORangeLastR3);
-    GEN_CHECK_OFF(IOM, pMMIOStatsLastR3);
-    GEN_CHECK_OFF(IOM, pMMIORangeLastR0);
-    GEN_CHECK_OFF(IOM, pMMIOStatsLastR0);
-    GEN_CHECK_OFF(IOM, pMMIORangeLastRC);
-    GEN_CHECK_OFF(IOM, pMMIOStatsLastRC);
-    GEN_CHECK_OFF(IOM, pRangeLastReadR0);
-    GEN_CHECK_OFF(IOM, pRangeLastReadRC);
 
     GEN_CHECK_SIZE(IOMCPU);
     GEN_CHECK_OFF(IOMCPU, DisState);
+    GEN_CHECK_OFF(IOMCPU, pMMIORangeLastR3);
+    GEN_CHECK_OFF(IOMCPU, pMMIOStatsLastR3);
+    GEN_CHECK_OFF(IOMCPU, pMMIORangeLastR0);
+    GEN_CHECK_OFF(IOMCPU, pMMIOStatsLastR0);
+    GEN_CHECK_OFF(IOMCPU, pMMIORangeLastRC);
+    GEN_CHECK_OFF(IOMCPU, pMMIOStatsLastRC);
+    GEN_CHECK_OFF(IOMCPU, pRangeLastReadR0);
+    GEN_CHECK_OFF(IOMCPU, pRangeLastReadRC);
 
     GEN_CHECK_SIZE(IOMMMIORANGE);
Index: /trunk/src/recompiler/VBoxREMWrapper.cpp
===================================================================
--- /trunk/src/recompiler/VBoxREMWrapper.cpp	(revision 45304)
+++ /trunk/src/recompiler/VBoxREMWrapper.cpp	(revision 45305)
@@ -680,4 +680,5 @@
 {
     { REMPARMDESC_FLAGS_INT,        sizeof(PVM),                NULL },
+    { REMPARMDESC_FLAGS_INT,        sizeof(PVMCPU),             NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(RTIOPORT),           NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t *),         NULL },
@@ -687,4 +688,5 @@
 {
     { REMPARMDESC_FLAGS_INT,        sizeof(PVM),                NULL },
+    { REMPARMDESC_FLAGS_INT,        sizeof(PVMCPU),             NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(RTIOPORT),           NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t),           NULL },
@@ -694,4 +696,5 @@
 {
     { REMPARMDESC_FLAGS_INT,        sizeof(PVM),                NULL },
+    { REMPARMDESC_FLAGS_INT,        sizeof(PVMCPU),             NULL },
     { REMPARMDESC_FLAGS_GCPHYS,     sizeof(RTGCPHYS),           NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t *),         NULL },
@@ -701,4 +704,5 @@
 {
     { REMPARMDESC_FLAGS_INT,        sizeof(PVM),                NULL },
+    { REMPARMDESC_FLAGS_INT,        sizeof(PVMCPU),             NULL },
     { REMPARMDESC_FLAGS_GCPHYS,     sizeof(RTGCPHYS),           NULL },
     { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t),           NULL },
@@ -1234,5 +1238,5 @@
     { "EMGetInhibitInterruptsPC",               VMM_FN(EMGetInhibitInterruptsPC),       &g_aArgsVMCPU[0],                           RT_ELEMENTS(g_aArgsVMCPU),                             REMFNDESC_FLAGS_RET_INT,    sizeof(RTGCPTR),    NULL },
     { "EMSetInhibitInterruptsPC",               VMM_FN(EMSetInhibitInterruptsPC),       &g_aArgsEMSetInhibitInterruptsPC[0],        RT_ELEMENTS(g_aArgsEMSetInhibitInterruptsPC),          REMFNDESC_FLAGS_RET_INT,    sizeof(int),        NULL },
-    { "HMR3CanExecuteGuest",                VMM_FN(HMR3CanExecuteGuest),        &g_aArgsHMR3CanExecuteGuest[0],         RT_ELEMENTS(g_aArgsHMR3CanExecuteGuest),           REMFNDESC_FLAGS_RET_INT,    sizeof(int),        NULL },
+    { "HMR3CanExecuteGuest",                    VMM_FN(HMR3CanExecuteGuest),            &g_aArgsHMR3CanExecuteGuest[0],             RT_ELEMENTS(g_aArgsHMR3CanExecuteGuest),               REMFNDESC_FLAGS_RET_INT,    sizeof(int),        NULL },
     { "IOMIOPortRead",                          VMM_FN(IOMIOPortRead),                  &g_aArgsIOMIOPortRead[0],                   RT_ELEMENTS(g_aArgsIOMIOPortRead),                     REMFNDESC_FLAGS_RET_INT,    sizeof(int),        NULL },
     { "IOMIOPortWrite",                         VMM_FN(IOMIOPortWrite),                 &g_aArgsIOMIOPortWrite[0],                  RT_ELEMENTS(g_aArgsIOMIOPortWrite),                    REMFNDESC_FLAGS_RET_INT,    sizeof(int),        NULL },
Index: /trunk/src/recompiler/VBoxRecompiler.c
===================================================================
--- /trunk/src/recompiler/VBoxRecompiler.c	(revision 45304)
+++ /trunk/src/recompiler/VBoxRecompiler.c	(revision 45305)
@@ -93,10 +93,10 @@
 static int      remR3InitPhysRamSizeAndDirtyMap(PVM pVM, bool fGuarded);
 
-static uint32_t remR3MMIOReadU8(void *pvVM, target_phys_addr_t GCPhys);
-static uint32_t remR3MMIOReadU16(void *pvVM, target_phys_addr_t GCPhys);
-static uint32_t remR3MMIOReadU32(void *pvVM, target_phys_addr_t GCPhys);
-static void     remR3MMIOWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
-static void     remR3MMIOWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
-static void     remR3MMIOWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32);
+static uint32_t remR3MMIOReadU8(void *pvEnv, target_phys_addr_t GCPhys);
+static uint32_t remR3MMIOReadU16(void *pvEnv, target_phys_addr_t GCPhys);
+static uint32_t remR3MMIOReadU32(void *pvEnv, target_phys_addr_t GCPhys);
+static void     remR3MMIOWriteU8(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32);
+static void     remR3MMIOWriteU16(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32);
+static void     remR3MMIOWriteU32(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32);
 
 static uint32_t remR3HandlerReadU8(void *pvVM, target_phys_addr_t GCPhys);
@@ -334,5 +334,5 @@
      * Register ram types.
      */
-    pVM->rem.s.iMMIOMemType    = cpu_register_io_memory(g_apfnMMIORead, g_apfnMMIOWrite, pVM);
+    pVM->rem.s.iMMIOMemType    = cpu_register_io_memory(g_apfnMMIORead, g_apfnMMIOWrite, &pVM->rem.s.Env);
     AssertReleaseMsg(pVM->rem.s.iMMIOMemType >= 0, ("pVM->rem.s.iMMIOMemType=%d\n", pVM->rem.s.iMMIOMemType));
     pVM->rem.s.iHandlerMemType = cpu_register_io_memory(g_apfnHandlerRead, g_apfnHandlerWrite, pVM);
@@ -3785,8 +3785,9 @@
 
 /** Read MMIO memory. */
-static uint32_t remR3MMIOReadU8(void *pvVM, target_phys_addr_t GCPhys)
-{
-    uint32_t u32 = 0;
-    int rc = IOMMMIORead((PVM)pvVM, GCPhys, &u32, 1);
+static uint32_t remR3MMIOReadU8(void *pvEnv, target_phys_addr_t GCPhys)
+{
+    CPUX86State *env = (CPUX86State *)pvEnv;
+    uint32_t     u32 = 0;
+    int rc = IOMMMIORead(env->pVM, env->pVCpu, GCPhys, &u32, 1);
     AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
     Log2(("remR3MMIOReadU8: GCPhys=%RGp -> %02x\n", (RTGCPHYS)GCPhys, u32));
@@ -3795,8 +3796,9 @@
 
 /** Read MMIO memory. */
-static uint32_t remR3MMIOReadU16(void *pvVM, target_phys_addr_t GCPhys)
-{
-    uint32_t u32 = 0;
-    int rc = IOMMMIORead((PVM)pvVM, GCPhys, &u32, 2);
+static uint32_t remR3MMIOReadU16(void *pvEnv, target_phys_addr_t GCPhys)
+{
+    CPUX86State *env = (CPUX86State *)pvEnv;
+    uint32_t     u32 = 0;
+    int rc = IOMMMIORead(env->pVM, env->pVCpu, GCPhys, &u32, 2);
     AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
     Log2(("remR3MMIOReadU16: GCPhys=%RGp -> %04x\n", (RTGCPHYS)GCPhys, u32));
@@ -3805,8 +3807,9 @@
 
 /** Read MMIO memory. */
-static uint32_t remR3MMIOReadU32(void *pvVM, target_phys_addr_t GCPhys)
-{
-    uint32_t u32 = 0;
-    int rc = IOMMMIORead((PVM)pvVM, GCPhys, &u32, 4);
+static uint32_t remR3MMIOReadU32(void *pvEnv, target_phys_addr_t GCPhys)
+{
+    CPUX86State *env = (CPUX86State *)pvEnv;
+    uint32_t     u32 = 0;
+    int rc = IOMMMIORead(env->pVM, env->pVCpu, GCPhys, &u32, 4);
     AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
     Log2(("remR3MMIOReadU32: GCPhys=%RGp -> %08x\n", (RTGCPHYS)GCPhys, u32));
@@ -3815,27 +3818,30 @@
 
 /** Write to MMIO memory. */
-static void     remR3MMIOWriteU8(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
-{
-    int rc;
+static void     remR3MMIOWriteU8(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32)
+{
+    CPUX86State *env = (CPUX86State *)pvEnv;
+    int          rc;
     Log2(("remR3MMIOWriteU8: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
-    rc = IOMMMIOWrite((PVM)pvVM, GCPhys, u32, 1);
+    rc = IOMMMIOWrite(env->pVM, env->pVCpu, GCPhys, u32, 1);
     AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
 }
 
 /** Write to MMIO memory. */
-static void     remR3MMIOWriteU16(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
-{
-    int rc;
+static void     remR3MMIOWriteU16(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32)
+{
+    CPUX86State *env = (CPUX86State *)pvEnv;
+    int          rc;
     Log2(("remR3MMIOWriteU16: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
-    rc = IOMMMIOWrite((PVM)pvVM, GCPhys, u32, 2);
+    rc = IOMMMIOWrite(env->pVM, env->pVCpu, GCPhys, u32, 2);
     AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
 }
 
 /** Write to MMIO memory. */
-static void     remR3MMIOWriteU32(void *pvVM, target_phys_addr_t GCPhys, uint32_t u32)
-{
-    int rc;
+static void     remR3MMIOWriteU32(void *pvEnv, target_phys_addr_t GCPhys, uint32_t u32)
+{
+    CPUX86State *env = (CPUX86State *)pvEnv;
+    int          rc;
     Log2(("remR3MMIOWriteU32: GCPhys=%RGp u32=%#x\n", (RTGCPHYS)GCPhys, u32));
-    rc = IOMMMIOWrite((PVM)pvVM, GCPhys, u32, 4);
+    rc = IOMMMIOWrite(env->pVM, env->pVCpu, GCPhys, u32, 4);
     AssertMsg(rc == VINF_SUCCESS, ("rc=%Rrc\n", rc)); NOREF(rc);
 }
@@ -4557,5 +4563,5 @@
         Log2(("cpu_outb: addr=%#06x val=%#x\n", addr, val));
 
-    rc = IOMIOPortWrite(env->pVM, (RTIOPORT)addr, val, 1);
+    rc = IOMIOPortWrite(env->pVM, env->pVCpu, (RTIOPORT)addr, val, 1);
     if (RT_LIKELY(rc == VINF_SUCCESS))
         return;
@@ -4572,5 +4578,5 @@
 {
     //Log2(("cpu_outw: addr=%#06x val=%#x\n", addr, val));
-    int rc = IOMIOPortWrite(env->pVM, (RTIOPORT)addr, val, 2);
+    int rc = IOMIOPortWrite(env->pVM, env->pVCpu, (RTIOPORT)addr, val, 2);
     if (RT_LIKELY(rc == VINF_SUCCESS))
         return;
@@ -4588,5 +4594,5 @@
     int rc;
     Log2(("cpu_outl: addr=%#06x val=%#x\n", addr, val));
-    rc = IOMIOPortWrite(env->pVM, (RTIOPORT)addr, val, 4);
+    rc = IOMIOPortWrite(env->pVM, env->pVCpu, (RTIOPORT)addr, val, 4);
     if (RT_LIKELY(rc == VINF_SUCCESS))
         return;
@@ -4603,5 +4609,5 @@
 {
     uint32_t u32 = 0;
-    int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 1);
+    int rc = IOMIOPortRead(env->pVM, env->pVCpu, (RTIOPORT)addr, &u32, 1);
     if (RT_LIKELY(rc == VINF_SUCCESS))
     {
@@ -4623,5 +4629,5 @@
 {
     uint32_t u32 = 0;
-    int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 2);
+    int rc = IOMIOPortRead(env->pVM, env->pVCpu, (RTIOPORT)addr, &u32, 2);
     if (RT_LIKELY(rc == VINF_SUCCESS))
     {
@@ -4642,5 +4648,5 @@
 {
     uint32_t u32 = 0;
-    int rc = IOMIOPortRead(env->pVM, (RTIOPORT)addr, &u32, 4);
+    int rc = IOMIOPortRead(env->pVM, env->pVCpu, (RTIOPORT)addr, &u32, 4);
     if (RT_LIKELY(rc == VINF_SUCCESS))
     {
