Index: /trunk/include/VBox/vmm/iem.h
===================================================================
--- /trunk/include/VBox/vmm/iem.h	(revision 56627)
+++ /trunk/include/VBox/vmm/iem.h	(revision 56628)
@@ -105,4 +105,5 @@
 VMMR3DECL(int)      IEMR3Term(PVM pVM);
 VMMR3DECL(void)     IEMR3Relocate(PVM pVM);
+VMMR3_INT_DECL(VBOXSTRICTRC) IEMR3DoPendingAction(PVMCPU pVCpu, VBOXSTRICTRC rcStrict);
 /** @} */
 
Index: /trunk/include/VBox/vmm/vm.h
===================================================================
--- /trunk/include/VBox/vmm/vm.h	(revision 56627)
+++ /trunk/include/VBox/vmm/vm.h	(revision 56628)
@@ -373,4 +373,8 @@
 /** This action forces the VCPU out of the halted state. */
 #define VMCPU_FF_UNHALT                     RT_BIT_32(6)
+/** Pending IEM action (bit number). */
+#define VMCPU_FF_IEM_BIT                    7
+/** Pending IEM action (mask). */
+#define VMCPU_FF_IEM                        RT_BIT_32(VMCPU_FF_IEM_BIT)
 /** This action forces the VM to service pending requests from other
  * thread or requests which must be executed in another context. */
@@ -457,5 +461,5 @@
 /** High priority post-execution actions. */
 #define VMCPU_FF_HIGH_PRIORITY_POST_MASK        (  VMCPU_FF_PDM_CRITSECT | VM_WHEN_RAW_MODE(VMCPU_FF_CSAM_PENDING_ACTION, 0) \
-                                                 | VMCPU_FF_HM_UPDATE_CR3 | VMCPU_FF_HM_UPDATE_PAE_PDPES)
+                                                 | VMCPU_FF_HM_UPDATE_CR3 | VMCPU_FF_HM_UPDATE_PAE_PDPES | VMCPU_FF_IEM)
 
 /** Normal priority VM post-execution actions. */
@@ -478,5 +482,5 @@
                                                  | VM_FF_PDM_QUEUES | VM_FF_EMT_RENDEZVOUS)
 /** VMCPU Flags that cause the HM loops to go back to ring-3. */
-#define VMCPU_FF_HM_TO_R3_MASK                  (VMCPU_FF_TO_R3 | VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT)
+#define VMCPU_FF_HM_TO_R3_MASK                  (VMCPU_FF_TO_R3 | VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT | VMCPU_FF_IEM)
 
 /** High priority ring-0 VM pre HM-mode execution mask. */
Index: /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 56627)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 56628)
@@ -769,4 +769,7 @@
     PVMCPU   pVCpu = IEMCPU_TO_VMCPU(pIemCpu);
 
+    Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_IEM));
+    Assert(pIemCpu->PendingCommit.enmFn == IEMCOMMIT_INVALID);
+
 #if defined(VBOX_STRICT) && (defined(IEM_VERIFICATION_MODE_FULL) || !defined(VBOX_WITH_RAW_MODE_NOT_R0))
     Assert(CPUMSELREG_ARE_HIDDEN_PARTS_VALID(pVCpu, &pCtx->cs));
@@ -829,4 +832,7 @@
     PCPUMCTX pCtx  = pIemCpu->CTX_SUFF(pCtx);
     PVMCPU   pVCpu = IEMCPU_TO_VMCPU(pIemCpu);
+
+    Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_IEM));
+    Assert(pIemCpu->PendingCommit.enmFn == IEMCOMMIT_INVALID);
 
 #if defined(VBOX_STRICT) && (defined(IEM_VERIFICATION_MODE_FULL) || !defined(VBOX_WITH_RAW_MODE_NOT_R0))
@@ -10712,4 +10718,5 @@
                       || rcStrict == VINF_CPUM_R3_MSR_WRITE
                       || rcStrict == VINF_EM_RAW_EMULATE_INSTR
+                      || rcStrict == VINF_EM_RAW_TO_R3
                       /* raw-mode / virt handlers only: */
                       || rcStrict == VINF_EM_RAW_EMULATE_INSTR_GDT_FAULT
@@ -11552,2 +11559,87 @@
 }
 
+#ifdef IN_RING3
+
+/**
+ * Called by force-flag handling code when VMCPU_FF_IEM is set.
+ *
+ * @returns Merge between @a rcStrict and what the commit operation returned.
+ * @param   pVCpu           Pointer to the cross context CPU structure for the
+ *                          calling EMT.
+ * @param   rcStrict        The status code returned by ring-0 or raw-mode.
+ */
+VMMR3_INT_DECL(VBOXSTRICTRC) IEMR3DoPendingAction(PVMCPU pVCpu, VBOXSTRICTRC rcStrict)
+{
+    PIEMCPU      pIemCpu = &pVCpu->iem.s;
+
+    /*
+     * Retrieve and reset the pending commit.
+     */
+    IEMCOMMIT const enmFn = pIemCpu->PendingCommit.enmFn;
+    pIemCpu->PendingCommit.enmFn = IEMCOMMIT_INVALID;
+    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_IEM);
+
+    /*
+     * Must reset pass-up status code.
+     */
+    pIemCpu->rcPassUp = VINF_SUCCESS;
+
+    /*
+     * Call the function.  Currently using switch here instead of function
+     * pointer table as a switch won't get skewed.
+     */
+    VBOXSTRICTRC rcStrictCommit;
+    switch (enmFn)
+    {
+        case IEMCOMMIT_INS_OP8_ADDR16:          rcStrictCommit = iemR3CImpl_commit_ins_op8_addr16(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_INS_OP8_ADDR32:          rcStrictCommit = iemR3CImpl_commit_ins_op8_addr32(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_INS_OP8_ADDR64:          rcStrictCommit = iemR3CImpl_commit_ins_op8_addr64(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_INS_OP16_ADDR16:         rcStrictCommit = iemR3CImpl_commit_ins_op16_addr16(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_INS_OP16_ADDR32:         rcStrictCommit = iemR3CImpl_commit_ins_op16_addr32(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_INS_OP16_ADDR64:         rcStrictCommit = iemR3CImpl_commit_ins_op16_addr64(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_INS_OP32_ADDR16:         rcStrictCommit = iemR3CImpl_commit_ins_op32_addr16(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_INS_OP32_ADDR32:         rcStrictCommit = iemR3CImpl_commit_ins_op32_addr32(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_INS_OP32_ADDR64:         rcStrictCommit = iemR3CImpl_commit_ins_op32_addr64(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP8_ADDR16:      rcStrictCommit = iemR3CImpl_commit_rep_ins_op8_addr16(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP8_ADDR32:      rcStrictCommit = iemR3CImpl_commit_rep_ins_op8_addr32(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP8_ADDR64:      rcStrictCommit = iemR3CImpl_commit_rep_ins_op8_addr64(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP16_ADDR16:     rcStrictCommit = iemR3CImpl_commit_rep_ins_op16_addr16(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP16_ADDR32:     rcStrictCommit = iemR3CImpl_commit_rep_ins_op16_addr32(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP16_ADDR64:     rcStrictCommit = iemR3CImpl_commit_rep_ins_op16_addr64(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP32_ADDR16:     rcStrictCommit = iemR3CImpl_commit_rep_ins_op32_addr16(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP32_ADDR32:     rcStrictCommit = iemR3CImpl_commit_rep_ins_op32_addr32(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        case IEMCOMMIT_REP_INS_OP32_ADDR64:     rcStrictCommit = iemR3CImpl_commit_rep_ins_op32_addr64(pIemCpu, pIemCpu->PendingCommit.cbInstr); break;
+        default:
+            AssertLogRelMsgFailedReturn(("enmFn=%#x (%d)\n", pIemCpu->PendingCommit.enmFn, pIemCpu->PendingCommit.enmFn), VERR_IEM_IPE_2);
+    }
+
+    /*
+     * Merge status code (if any) with the incomming one.
+     */
+    rcStrictCommit = iemExecStatusCodeFiddling(pIemCpu, rcStrictCommit);
+    if (RT_LIKELY(rcStrictCommit == VINF_SUCCESS))
+        return rcStrict;
+    if (RT_LIKELY(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RAW_TO_R3))
+        return rcStrictCommit;
+
+    /* Complicated. */
+    if (RT_FAILURE(rcStrict))
+        return rcStrict;
+    if (RT_FAILURE(rcStrictCommit))
+        return rcStrictCommit;
+    if (   rcStrict >= VINF_EM_FIRST
+        && rcStrict <= VINF_EM_LAST)
+    {
+        if (   rcStrictCommit >= VINF_EM_FIRST
+            && rcStrictCommit <= VINF_EM_LAST)
+            return rcStrict < rcStrictCommit ? rcStrict : rcStrictCommit;
+
+        /* This really shouldn't happen. Check PGM + handler code! */
+        AssertLogRelMsgFailedReturn(("rcStrictCommit=%Rrc rcStrict=%Rrc enmFn=%d\n", VBOXSTRICTRC_VAL(rcStrictCommit), VBOXSTRICTRC_VAL(rcStrict), enmFn), VERR_IEM_IPE_1);
+    }
+    /* This shouldn't really happen either, see IOM_SUCCESS. */
+    AssertLogRelMsgFailedReturn(("rcStrictCommit=%Rrc rcStrict=%Rrc enmFn=%d\n", VBOXSTRICTRC_VAL(rcStrictCommit), VBOXSTRICTRC_VAL(rcStrict), enmFn), VERR_IEM_IPE_2);
+}
+
+#endif /* IN_RING */
+
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 56627)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImplStrInstr.cpp.h	(revision 56628)
@@ -1015,4 +1015,58 @@
 #if OP_SIZE != 64
 
+# if !defined(IN_RING3) && !defined(IEMCIMPL_INS_INLINES)
+#  define IEMCIMPL_INS_INLINES 1
+
+/**
+ * Check if we should postpone committing an INS instruction to ring-3, or if we
+ * should rather panic.
+ *
+ * @returns true if we should postpone it, false if it's better to panic.
+ * @param   rcStrictMem     The status code returned by the memory write.
+ */
+DECLINLINE(bool) iemCImpl_ins_shouldPostponeCommitToRing3(VBOXSTRICTRC rcStrictMem)
+{
+    /*
+     * The following requires executing the write in ring-3.
+     * See PGMPhysWrite for status code explanations.
+     */
+    if (   rcStrictMem == VINF_IOM_R3_MMIO_WRITE
+        || rcStrictMem == VINF_IOM_R3_MMIO_READ_WRITE
+        || rcStrictMem == VINF_EM_RAW_EMULATE_INSTR
+# ifdef IN_RC
+        || rcStrictMem == VINF_EM_RAW_EMULATE_INSTR_LDT_FAULT
+        || rcStrictMem == VINF_EM_RAW_EMULATE_INSTR_TSS_FAULT
+        || rcStrictMem == VINF_EM_RAW_EMULATE_INSTR_IDT_FAULT
+        || rcStrictMem == VINF_CSAM_PENDING_ACTION
+        || rcStrictMem == VINF_PATM_CHECK_PATCH_PAGE
+# endif
+       )
+        return true;
+
+    /* For the other status code, the pass-up handling should already have
+       caught them. So, anything getting down here is a real problem worth
+       meditating over. */
+    return false;
+}
+
+
+/**
+ * Merges a iemCImpl_ins_shouldPostponeCommitToRing3() status with the I/O port
+ * status.
+ *
+ * @returns status code.
+ * @param   rcStrictPort    The status returned by the I/O port read.
+ * @param   rcStrictMem     The status code returned by the memory write.
+ */
+DECLINLINE(VBOXSTRICTRC) iemCImpl_ins_mergePostponedCommitStatuses(VBOXSTRICTRC rcStrictPort, VBOXSTRICTRC rcStrictMem)
+{
+    /* Turns out we don't need a lot of merging, since we'll be redoing the
+       write anyway.  (CSAM, PATM status codes, perhaps, but that's about it.) */
+    return rcStrictPort == VINF_SUCCESS ? VINF_EM_RAW_TO_R3 : rcStrictPort;
+}
+
+# endif /* !IN_RING3 || !IEMCIMPL_INS_INLINES */
+
+
 /**
  * Implements 'INS' (no rep)
@@ -1067,13 +1121,47 @@
             iemRegAddToRipAndClearRF(pIemCpu, cbInstr);
         }
+#ifndef IN_RING3
         /* iemMemMap already checked permissions, so this may only be real errors
-           or access handlers meddling. The access handler case is going to
-           cause misbehavior if the instruction is re-interpreted or smth. So,
-           we fail with an internal error here instead. */
+           or access handlers meddling. In the access handler case, we must postpone
+           the instruction committing to ring-3. */
+        else if (iemCImpl_ins_shouldPostponeCommitToRing3(rcStrict2))
+        {
+            pIemCpu->PendingCommit.cbInstr = cbInstr;
+            pIemCpu->PendingCommit.uValue  = u32Value;
+            pIemCpu->PendingCommit.enmFn   = RT_CONCAT4(IEMCOMMIT_INS_OP,OP_SIZE,_ADDR,ADDR_SIZE);
+            pIemCpu->cPendingCommit++;
+            VMCPU_FF_SET(IEMCPU_TO_VMCPU(pIemCpu), VMCPU_FF_IEM);
+            Log(("%s: Postponing to ring-3; cbInstr=%#x u32Value=%#x rcStrict2=%Rrc rcStrict=%Rrc\n", __FUNCTION__,
+                 cbInstr, u32Value, VBOXSTRICTRC_VAL(rcStrict2),  VBOXSTRICTRC_VAL(rcStrict)));
+            rcStrict = iemCImpl_ins_mergePostponedCommitStatuses(rcStrict, rcStrict2);
+        }
+#endif
         else
-            AssertLogRelMsgFailedReturn(("rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)), VERR_IEM_IPE_1);
+            AssertLogRelMsgFailedReturn(("rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)), RT_FAILURE_NP(rcStrict2) ? rcStrict2 : VERR_IEM_IPE_1);
     }
     return rcStrict;
 }
+
+
+# ifdef IN_RING3
+/**
+ * Called in ring-3 when raw-mode or ring-0 was forced to return while
+ * committing the instruction (hit access handler).
+ */
+IEM_CIMPL_DEF_0(RT_CONCAT4(iemR3CImpl_commit_ins_op,OP_SIZE,_addr,ADDR_SIZE))
+{
+    PCPUMCTX     pCtx     = pIemCpu->CTX_SUFF(pCtx);
+    VBOXSTRICTRC rcStrict = RT_CONCAT(iemMemStoreDataU,OP_SIZE)(pIemCpu, X86_SREG_ES, pCtx->ADDR_rDI, (OP_TYPE)pIemCpu->PendingCommit.uValue);
+    if (rcStrict == VINF_SUCCESS)
+    {
+        if (!pCtx->eflags.Bits.u1DF)
+            pCtx->ADDR_rDI += OP_SIZE / 8;
+        else
+            pCtx->ADDR_rDI -= OP_SIZE / 8;
+        iemRegAddToRipAndClearRF(pIemCpu, cbInstr);
+    }
+    return rcStrict;
+}
+# endif /* IN_RING3 */
 
 
@@ -1217,6 +1305,25 @@
             *puMem = (OP_TYPE)u32Value;
             VBOXSTRICTRC rcStrict2 = iemMemCommitAndUnmap(pIemCpu, puMem, IEM_ACCESS_DATA_W);
-            AssertLogRelMsgReturn(rcStrict2 == VINF_SUCCESS, ("rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)),
-                                  VERR_IEM_IPE_1); /* See non-rep version. */
+            if (rcStrict2 == VINF_SUCCESS)
+            { /* likely */ }
+#ifndef IN_RING3
+            /* iemMemMap already checked permissions, so this may only be real errors
+               or access handlers meddling. In the access handler case, we must postpone
+               the instruction committing to ring-3. */
+            else if (iemCImpl_ins_shouldPostponeCommitToRing3(rcStrict2))
+            {
+                pIemCpu->PendingCommit.cbInstr = cbInstr;
+                pIemCpu->PendingCommit.uValue  = u32Value;
+                pIemCpu->PendingCommit.enmFn   = RT_CONCAT4(IEMCOMMIT_REP_INS_OP,OP_SIZE,_ADDR,ADDR_SIZE);
+                pIemCpu->cPendingCommit++;
+                VMCPU_FF_SET(IEMCPU_TO_VMCPU(pIemCpu), VMCPU_FF_IEM);
+                Log(("%s: Postponing to ring-3; cbInstr=%#x u32Value=%#x rcStrict2=%Rrc rcStrict=%Rrc\n", __FUNCTION__,
+                     cbInstr, u32Value, VBOXSTRICTRC_VAL(rcStrict2),  VBOXSTRICTRC_VAL(rcStrict)));
+                return iemCImpl_ins_mergePostponedCommitStatuses(rcStrict, rcStrict2);
+            }
+#endif
+            else
+                AssertLogRelMsgFailedReturn(("rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict2)),
+                                            RT_FAILURE(rcStrict2) ? rcStrict2 : VERR_IEM_IPE_1);
 
             pCtx->ADDR_rDI = uAddrReg += cbIncr;
@@ -1240,4 +1347,27 @@
     return VINF_SUCCESS;
 }
+
+# ifdef IN_RING3
+/**
+ * Called in ring-3 when raw-mode or ring-0 was forced to return while
+ * committing the instruction (hit access handler).
+ */
+IEM_CIMPL_DEF_0(RT_CONCAT4(iemR3CImpl_commit_rep_ins_op,OP_SIZE,_addr,ADDR_SIZE))
+{
+    PCPUMCTX     pCtx     = pIemCpu->CTX_SUFF(pCtx);
+    VBOXSTRICTRC rcStrict = RT_CONCAT(iemMemStoreDataU,OP_SIZE)(pIemCpu, X86_SREG_ES, pCtx->ADDR_rDI, (OP_TYPE)pIemCpu->PendingCommit.uValue);
+    if (rcStrict == VINF_SUCCESS)
+    {
+        if (!pCtx->eflags.Bits.u1DF)
+            pCtx->ADDR_rDI += OP_SIZE / 8;
+        else
+            pCtx->ADDR_rDI -= OP_SIZE / 8;
+        pCtx->ADDR_rCX -= 1;
+        if (pCtx->ADDR_rCX == 0)
+            iemRegAddToRipAndClearRF(pIemCpu, cbInstr);
+    }
+    return rcStrict;
+}
+# endif /* IN_RING3 */
 
 
Index: /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 56627)
+++ /trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 56628)
@@ -11366,4 +11366,5 @@
                   || rcStrict == VINF_EM_DBG_BREAKPOINT
                   || rcStrict == VINF_EM_RAW_GUEST_TRAP
+                  || rcStrict == VINF_EM_RAW_TO_R3
                   || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
     }
Index: /trunk/src/VBox/VMM/VMMR3/EM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 56627)
+++ /trunk/src/VBox/VMM/VMMR3/EM.cpp	(revision 56628)
@@ -1575,4 +1575,8 @@
     }
 
+    /* IEM has pending work (typically memory write after INS instruction). */
+    if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_IEM))
+        rc = VBOXSTRICTRC_TODO(IEMR3DoPendingAction(pVCpu, rc));
+
 #ifdef VBOX_WITH_RAW_MODE
     if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_CSAM_PENDING_ACTION))
Index: /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 56627)
+++ /trunk/src/VBox/VMM/VMMR3/IEMR3.cpp	(revision 56628)
@@ -65,4 +65,6 @@
         STAMR3RegisterF(pVM, &pVCpu->iem.s.cbWritten,                 STAMTYPE_U32,       STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
                         "Approx bytes written",              "/IEM/CPU%u/cbWritten", idCpu);
+        STAMR3RegisterF(pVM, &pVCpu->iem.s.cPendingCommit,            STAMTYPE_U32,       STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
+                        "Times RC/R0 had to postpone instruction committing to ring-3", "/IEM/CPU%u/cPendingCommit", idCpu);
 
         /*
Index: /trunk/src/VBox/VMM/VMMR3/VMM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 56627)
+++ /trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 56628)
@@ -2416,4 +2416,5 @@
         PRINT_FLAG(VMCPU_FF_,PDM_CRITSECT);
         PRINT_FLAG(VMCPU_FF_,UNHALT);
+        PRINT_FLAG(VMCPU_FF_,IEM);
         PRINT_FLAG(VMCPU_FF_,REQUEST);
         PRINT_FLAG(VMCPU_FF_,HM_UPDATE_CR3);
Index: /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 56627)
+++ /trunk/src/VBox/VMM/VMMRC/TRPMRCHandlers.cpp	(revision 56628)
@@ -213,4 +213,5 @@
                                           | VMCPU_FF_REQUEST | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL
                                           | VMCPU_FF_PDM_CRITSECT
+                                          | VMCPU_FF_IEM
                                           | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT
                                           | VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT
@@ -223,5 +224,5 @@
             rc = VINF_EM_NO_MEMORY;
         /* Pending Ring-3 action. */
-        else if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_TO_R3 | VMCPU_FF_PDM_CRITSECT))
+        else if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_TO_R3 | VMCPU_FF_PDM_CRITSECT | VMCPU_FF_IEM))
         {
             VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 56627)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 56628)
@@ -123,4 +123,43 @@
 /** Pointer to a const FPU result consisting of two output values and FSW. */
 typedef IEMFPURESULTTWO const *PCIEMFPURESULTTWO;
+
+
+/**
+ * IEM pending commit function index.
+ */
+typedef enum IEMCOMMIT
+{
+    /** Invalid / nothing pending. */
+    IEMCOMMIT_INVALID = 0,
+    /** @name INS
+     * @{  */
+    IEMCOMMIT_INS_OP8_ADDR16,
+    IEMCOMMIT_INS_OP8_ADDR32,
+    IEMCOMMIT_INS_OP8_ADDR64,
+    IEMCOMMIT_INS_OP16_ADDR16,
+    IEMCOMMIT_INS_OP16_ADDR32,
+    IEMCOMMIT_INS_OP16_ADDR64,
+    IEMCOMMIT_INS_OP32_ADDR16,
+    IEMCOMMIT_INS_OP32_ADDR32,
+    IEMCOMMIT_INS_OP32_ADDR64,
+    /** @} */
+    /** @name REP INS
+     * @{  */
+    IEMCOMMIT_REP_INS_OP8_ADDR16,
+    IEMCOMMIT_REP_INS_OP8_ADDR32,
+    IEMCOMMIT_REP_INS_OP8_ADDR64,
+    IEMCOMMIT_REP_INS_OP16_ADDR16,
+    IEMCOMMIT_REP_INS_OP16_ADDR32,
+    IEMCOMMIT_REP_INS_OP16_ADDR64,
+    IEMCOMMIT_REP_INS_OP32_ADDR16,
+    IEMCOMMIT_REP_INS_OP32_ADDR32,
+    IEMCOMMIT_REP_INS_OP32_ADDR64,
+    /** @} */
+    /** End of valid functions. */
+    IEMCOMMIT_END,
+    /** Make sure the type is int in call contexts. */
+    IEMCOMMIT_32BIT_HACK = 0x7fffffff
+} IEMCOMMIT;
+AssertCompile(sizeof(IEMCOMMIT) == 4);
 
 
@@ -253,4 +292,6 @@
     /** Number of times rcPassUp has been used. */
     uint32_t                cRetPassUpStatus;
+    /** Number of times RZ left with instruction commit pending for ring-3. */
+    uint32_t                cPendingCommit;
 #ifdef IEM_VERIFICATION_MODE_FULL
     /** The Number of I/O port reads that has been performed. */
@@ -322,7 +363,4 @@
     /** @}*/
 
-    /** Alignment padding for aMemMappings. */
-    uint8_t                 abAlignment2[4];
-
     /** The number of active guest memory mappings. */
     uint8_t                 cActiveMappings;
@@ -376,4 +414,17 @@
         uint8_t             ab[512];
     } aBounceBuffers[3];
+
+    /** @name Pending Instruction Commit (R0/RC postponed it to Ring-3).
+     * @{ */
+    struct
+    {
+        /** The commit function to call. */
+        IEMCOMMIT           enmFn;
+        /** The instruction size. */
+        uint8_t             cbInstr;
+        /** Generic value to commit. */
+        uint64_t            uValue;
+    } PendingCommit;
+    /** @} */
 
     /** @name Target CPU information.
