Index: /trunk/include/VBox/cpum.h
===================================================================
--- /trunk/include/VBox/cpum.h	(revision 30262)
+++ /trunk/include/VBox/cpum.h	(revision 30263)
@@ -878,6 +878,6 @@
 VMMDECL(PCCPUMCTXCORE)  CPUMGetGuestCtxCore(PVMCPU pVCpu);
 VMMDECL(void)           CPUMSetGuestCtxCore(PVMCPU pVCpu, PCCPUMCTXCORE pCtxCore);
-VMMDECL(int)            CPUMRawEnter(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore);
-VMMDECL(int)            CPUMRawLeave(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, int rc);
+VMMR3DECL(int)          CPUMR3RawEnter(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore);
+VMMR3DECL(int)          CPUMR3RawLeave(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, int rc);
 VMMDECL(uint32_t)       CPUMRawGetEFlags(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore);
 VMMDECL(void)           CPUMRawSetEFlags(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint32_t eflags);
@@ -890,21 +890,29 @@
  * @{
  */
-#define CPUM_CHANGED_FPU_REM            RT_BIT(0)
-#define CPUM_CHANGED_CR0                RT_BIT(1)
-#define CPUM_CHANGED_CR4                RT_BIT(2)
-#define CPUM_CHANGED_GLOBAL_TLB_FLUSH   RT_BIT(3)
-#define CPUM_CHANGED_CR3                RT_BIT(4)
-#define CPUM_CHANGED_GDTR               RT_BIT(5)
-#define CPUM_CHANGED_IDTR               RT_BIT(6)
-#define CPUM_CHANGED_LDTR               RT_BIT(7)
-#define CPUM_CHANGED_TR                 RT_BIT(8)
-#define CPUM_CHANGED_SYSENTER_MSR       RT_BIT(9)
-#define CPUM_CHANGED_HIDDEN_SEL_REGS    RT_BIT(10)
-#define CPUM_CHANGED_CPUID              RT_BIT(11)
-#define CPUM_CHANGED_ALL                (CPUM_CHANGED_FPU_REM|CPUM_CHANGED_CR0|CPUM_CHANGED_CR3|CPUM_CHANGED_CR4|CPUM_CHANGED_GDTR|CPUM_CHANGED_IDTR|CPUM_CHANGED_LDTR|CPUM_CHANGED_TR|CPUM_CHANGED_SYSENTER_MSR|CPUM_CHANGED_HIDDEN_SEL_REGS|CPUM_CHANGED_CPUID)
+#define CPUM_CHANGED_FPU_REM                    RT_BIT(0)
+#define CPUM_CHANGED_CR0                        RT_BIT(1)
+#define CPUM_CHANGED_CR4                        RT_BIT(2)
+#define CPUM_CHANGED_GLOBAL_TLB_FLUSH           RT_BIT(3)
+#define CPUM_CHANGED_CR3                        RT_BIT(4)
+#define CPUM_CHANGED_GDTR                       RT_BIT(5)
+#define CPUM_CHANGED_IDTR                       RT_BIT(6)
+#define CPUM_CHANGED_LDTR                       RT_BIT(7)
+#define CPUM_CHANGED_TR                         RT_BIT(8)
+#define CPUM_CHANGED_SYSENTER_MSR               RT_BIT(9)
+#define CPUM_CHANGED_HIDDEN_SEL_REGS            RT_BIT(10)
+#define CPUM_CHANGED_CPUID                      RT_BIT(11)
+#define CPUM_CHANGED_ALL                        \
+    ( CPUM_CHANGED_FPU_REM | CPUM_CHANGED_CR0 | CPUM_CHANGED_CR3 | CPUM_CHANGED_CR4 | CPUM_CHANGED_GDTR | CPUM_CHANGED_IDTR \
+     | CPUM_CHANGED_LDTR | CPUM_CHANGED_TR | CPUM_CHANGED_SYSENTER_MSR | CPUM_CHANGED_HIDDEN_SEL_REGS | CPUM_CHANGED_CPUID )
+/** This one is used by raw-mode to indicate that the hidden register
+ * information is not longer reliable and have to be re-determined.
+ *
+ * @remarks This must not be part of CPUM_CHANGED_ALL! */
+#define CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID    RT_BIT(12)
 /** @} */
 
-VMMDECL(unsigned)       CPUMGetAndClearChangedFlagsREM(PVMCPU pVCpu);
 VMMDECL(void)           CPUMSetChangedFlags(PVMCPU pVCpu, uint32_t fChangedFlags);
+VMMR3DECL(uint32_t)     CPUMR3RemEnter(PVMCPU pVCpu, uint32_t *puCpl);
+VMMR3DECL(void)         CPUMR3RemLeave(PVMCPU pVCpu, bool fNoOutOfSyncSels);
 VMMDECL(bool)           CPUMSupportsFXSR(PVM pVM);
 VMMDECL(bool)           CPUMIsHostUsingSysEnter(PVM pVM);
@@ -917,5 +925,5 @@
 VMMDECL(void)           CPUMDeactivateHyperDebugState(PVMCPU pVCpu);
 VMMDECL(uint32_t)       CPUMGetGuestCPL(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore);
-VMMDECL(bool)           CPUMAreHiddenSelRegsValid(PVM pVM);
+VMMDECL(bool)           CPUMAreHiddenSelRegsValid(PVMCPU pVCpu);
 VMMDECL(CPUMMODE)       CPUMGetGuestMode(PVMCPU pVCpu);
 
Index: /trunk/include/VBox/selm.h
===================================================================
--- /trunk/include/VBox/selm.h	(revision 30262)
+++ /trunk/include/VBox/selm.h	(revision 30263)
@@ -76,8 +76,11 @@
 
 VMMDECL(int)        SELMToFlatEx(PVM pVM, DIS_SELREG SelReg, PCCPUMCTXCORE pCtxCore, RTGCPTR Addr, unsigned fFlags, PRTGCPTR ppvGC);
-VMMDECL(int)        SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, PCPUMSELREGHID pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb);
-VMMDECL(int)        SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, PCPUMSELREGHID pHiddenCSSel, RTGCPTR Addr, PRTGCPTR ppvFlat);
-VMMDECL(int)        SELMValidateAndConvertCSAddrGCTrap(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat, uint32_t *pcBits);
-VMMDECL(DISCPUMODE) SELMGetCpuModeFromSelector(PVM pVM, X86EFLAGS eflags, RTSEL Sel, PCPUMSELREGHID pHiddenSel);
+VMMDECL(int)        SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, PCCPUMSELREGHID pHiddenSel,
+                                      unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb);
+VMMDECL(int)        SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS,
+                                                 PCCPUMSELREGHID pHiddenCSSel, RTGCPTR Addr, PRTGCPTR ppvFlat);
+VMMDECL(int)        SELMValidateAndConvertCSAddrGCTrap(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr,
+                                                       PRTGCPTR ppvFlat, uint32_t *pcBits);
+VMMDECL(DISCPUMODE) SELMGetCpuModeFromSelector(PVM pVM, X86EFLAGS eflags, RTSEL Sel, PCCPUMSELREGHID pHiddenSel);
 VMMDECL(int)        SELMGetLDTFromSel(PVM pVM, RTSEL SelLdt, PRTGCPTR ppvLdt, unsigned *pcbLimit);
 
Index: /trunk/src/VBox/VMM/CPUM.cpp
===================================================================
--- /trunk/src/VBox/VMM/CPUM.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/CPUM.cpp	(revision 30263)
@@ -63,5 +63,8 @@
 *******************************************************************************/
 /** The current saved state version. */
-#define CPUM_SAVED_STATE_VERSION                11
+#define CPUM_SAVED_STATE_VERSION                12
+/** The saved state version of 3.2, 3.1 and 3.3 trunk before the hidden
+ * selector register change (CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID). */
+#define CPUM_SAVED_STATE_VERSION_VER3_2         11
 /** The saved state version of 3.0 and 3.1 trunk before the teleportation
  * changes. */
@@ -2065,4 +2068,5 @@
      */
     if (    uVersion != CPUM_SAVED_STATE_VERSION
+        &&  uVersion != CPUM_SAVED_STATE_VERSION_VER3_2
         &&  uVersion != CPUM_SAVED_STATE_VERSION_VER3_0
         &&  uVersion != CPUM_SAVED_STATE_VERSION_VER2_1_NOMSR
@@ -2134,4 +2138,11 @@
             }
         }
+
+        /* Older states does not set CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID for
+           raw-mode guest, so we have to do it ourselves. */
+        if (   uVersion <= CPUM_SAVED_STATE_VERSION_VER3_2
+            && !HWACCMIsEnabled(pVM))
+            for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
+                pVM->aCpus[iCpu].cpum.s.fChanged |= CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID;
     }
 
@@ -2272,5 +2283,4 @@
         return VERR_INTERNAL_ERROR_2;
     }
-
     return VINF_SUCCESS;
 }
@@ -3574,5 +3584,5 @@
         &&   pCtx->eflags.Bits.u1VM == 0)
     {
-        if (CPUMAreHiddenSelRegsValid(pVM))
+        if (CPUMAreHiddenSelRegsValid(pVCpu))
         {
             State.f64Bits         = enmMode >= PGMMODE_AMD64 && pCtx->csHid.Attr.n.u1Long;
@@ -3768,2 +3778,212 @@
     return (RCPTRTYPE(PCCPUMCPUID))VM_RC_ADDR(pVM, &pVM->cpum.s.GuestCpuIdDef);
 }
+
+
+/**
+ * Transforms the guest CPU state to raw-ring mode.
+ *
+ * This function will change the any of the cs and ss register with DPL=0 to DPL=1.
+ *
+ * @returns VBox status. (recompiler failure)
+ * @param   pVCpu       The VMCPU handle.
+ * @param   pCtxCore    The context core (for trap usage).
+ * @see     @ref pg_raw
+ */
+VMMR3DECL(int) CPUMR3RawEnter(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore)
+{
+    PVM pVM = pVCpu->CTX_SUFF(pVM);
+
+    Assert(!pVCpu->cpum.s.fRawEntered);
+    Assert(!pVCpu->cpum.s.fRemEntered);
+    if (!pCtxCore)
+        pCtxCore = CPUMCTX2CORE(&pVCpu->cpum.s.Guest);
+
+    /*
+     * Are we in Ring-0?
+     */
+    if (    pCtxCore->ss && (pCtxCore->ss & X86_SEL_RPL) == 0
+        &&  !pCtxCore->eflags.Bits.u1VM)
+    {
+        /*
+         * Enter execution mode.
+         */
+        PATMRawEnter(pVM, pCtxCore);
+
+        /*
+         * Set CPL to Ring-1.
+         */
+        pCtxCore->ss |= 1;
+        if (pCtxCore->cs && (pCtxCore->cs & X86_SEL_RPL) == 0)
+            pCtxCore->cs |= 1;
+    }
+    else
+    {
+        AssertMsg((pCtxCore->ss & X86_SEL_RPL) >= 2 || pCtxCore->eflags.Bits.u1VM,
+                  ("ring-1 code not supported\n"));
+        /*
+         * PATM takes care of IOPL and IF flags for Ring-3 and Ring-2 code as well.
+         */
+        PATMRawEnter(pVM, pCtxCore);
+    }
+
+    /*
+     * Invalidate the hidden registers.
+     */
+    pVCpu->cpum.s.fChanged |= CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID;
+
+    /*
+     * Assert sanity.
+     */
+    AssertMsg((pCtxCore->eflags.u32 & X86_EFL_IF), ("X86_EFL_IF is clear\n"));
+    AssertReleaseMsg(   pCtxCore->eflags.Bits.u2IOPL < (unsigned)(pCtxCore->ss & X86_SEL_RPL)
+                     || pCtxCore->eflags.Bits.u1VM,
+                     ("X86_EFL_IOPL=%d CPL=%d\n", pCtxCore->eflags.Bits.u2IOPL, pCtxCore->ss & X86_SEL_RPL));
+    Assert((pVCpu->cpum.s.Guest.cr0 & (X86_CR0_PG | X86_CR0_WP | X86_CR0_PE)) == (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP));
+
+    pCtxCore->eflags.u32        |= X86_EFL_IF; /* paranoia */
+
+    pVCpu->cpum.s.fRawEntered = true;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Transforms the guest CPU state from raw-ring mode to correct values.
+ *
+ * This function will change any selector registers with DPL=1 to DPL=0.
+ *
+ * @returns Adjusted rc.
+ * @param   pVCpu       The VMCPU handle.
+ * @param   rc          Raw mode return code
+ * @param   pCtxCore    The context core (for trap usage).
+ * @see     @ref pg_raw
+ */
+VMMR3DECL(int) CPUMR3RawLeave(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, int rc)
+{
+    PVM pVM = pVCpu->CTX_SUFF(pVM);
+
+    /*
+     * Don't leave if we've already left (in GC).
+     */
+    Assert(pVCpu->cpum.s.fRawEntered);
+    Assert(!pVCpu->cpum.s.fRemEntered);
+    if (!pVCpu->cpum.s.fRawEntered)
+        return rc;
+    pVCpu->cpum.s.fRawEntered = false;
+
+    PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
+    if (!pCtxCore)
+        pCtxCore = CPUMCTX2CORE(pCtx);
+    Assert(pCtxCore->eflags.Bits.u1VM || (pCtxCore->ss & X86_SEL_RPL));
+    AssertMsg(pCtxCore->eflags.Bits.u1VM || pCtxCore->eflags.Bits.u2IOPL < (unsigned)(pCtxCore->ss & X86_SEL_RPL),
+              ("X86_EFL_IOPL=%d CPL=%d\n", pCtxCore->eflags.Bits.u2IOPL, pCtxCore->ss & X86_SEL_RPL));
+
+    /*
+     * Are we executing in raw ring-1?
+     */
+    if (    (pCtxCore->ss & X86_SEL_RPL) == 1
+        &&  !pCtxCore->eflags.Bits.u1VM)
+    {
+        /*
+         * Leave execution mode.
+         */
+        PATMRawLeave(pVM, pCtxCore, rc);
+        /* Not quite sure if this is really required, but shouldn't harm (too much anyways). */
+        /** @todo See what happens if we remove this. */
+        if ((pCtxCore->ds & X86_SEL_RPL) == 1)
+            pCtxCore->ds &= ~X86_SEL_RPL;
+        if ((pCtxCore->es & X86_SEL_RPL) == 1)
+            pCtxCore->es &= ~X86_SEL_RPL;
+        if ((pCtxCore->fs & X86_SEL_RPL) == 1)
+            pCtxCore->fs &= ~X86_SEL_RPL;
+        if ((pCtxCore->gs & X86_SEL_RPL) == 1)
+            pCtxCore->gs &= ~X86_SEL_RPL;
+
+        /*
+         * Ring-1 selector => Ring-0.
+         */
+        pCtxCore->ss &= ~X86_SEL_RPL;
+        if ((pCtxCore->cs & X86_SEL_RPL) == 1)
+            pCtxCore->cs &= ~X86_SEL_RPL;
+    }
+    else
+    {
+        /*
+         * PATM is taking care of the IOPL and IF flags for us.
+         */
+        PATMRawLeave(pVM, pCtxCore, rc);
+        if (!pCtxCore->eflags.Bits.u1VM)
+        {
+            /** @todo See what happens if we remove this. */
+            if ((pCtxCore->ds & X86_SEL_RPL) == 1)
+                pCtxCore->ds &= ~X86_SEL_RPL;
+            if ((pCtxCore->es & X86_SEL_RPL) == 1)
+                pCtxCore->es &= ~X86_SEL_RPL;
+            if ((pCtxCore->fs & X86_SEL_RPL) == 1)
+                pCtxCore->fs &= ~X86_SEL_RPL;
+            if ((pCtxCore->gs & X86_SEL_RPL) == 1)
+                pCtxCore->gs &= ~X86_SEL_RPL;
+        }
+    }
+
+    return rc;
+}
+
+
+/**
+ * Enters REM, gets and resets the changed flags (CPUM_CHANGED_*).
+ *
+ * Only REM should ever call this function!
+ *
+ * @returns The changed flags.
+ * @param   pVCpu       The VMCPU handle.
+ * @param   puCpl       Where to return the current privilege level (CPL).
+ */
+VMMR3DECL(uint32_t) CPUMR3RemEnter(PVMCPU pVCpu, uint32_t *puCpl)
+{
+    Assert(!pVCpu->cpum.s.fRawEntered);
+    Assert(!pVCpu->cpum.s.fRemEntered);
+
+    /*
+     * Get the CPL first.
+     */
+    *puCpl = CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(&pVCpu->cpum.s.Guest));
+
+    /*
+     * Get and reset the flags, leaving CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID set.
+     */
+    uint32_t fFlags = pVCpu->cpum.s.fChanged;
+    pVCpu->cpum.s.fChanged &= CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID; /* leave it set */
+
+    /** @todo change the switcher to use the fChanged flags. */
+    if (pVCpu->cpum.s.fUseFlags & CPUM_USED_FPU_SINCE_REM)
+    {
+        fFlags |= CPUM_CHANGED_FPU_REM;
+        pVCpu->cpum.s.fUseFlags &= ~CPUM_USED_FPU_SINCE_REM;
+    }
+
+    pVCpu->cpum.s.fRemEntered = true;
+    return fFlags;
+}
+
+
+/**
+ * Leaves REM and works the CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID flag.
+ *
+ * @param   pVCpu               The virtual CPU handle.
+ * @param   fNoOutOfSyncSels    This is @c false if there are out of sync
+ *                              registers.
+ */
+VMMR3DECL(void) CPUMR3RemLeave(PVMCPU pVCpu, bool fNoOutOfSyncSels)
+{
+    Assert(!pVCpu->cpum.s.fRawEntered);
+    Assert(pVCpu->cpum.s.fRemEntered);
+
+    if (fNoOutOfSyncSels)
+        pVCpu->cpum.s.fChanged &= ~CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID;
+    else
+        pVCpu->cpum.s.fChanged |= ~CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID;
+
+    pVCpu->cpum.s.fRemEntered = false;
+}
+
Index: /trunk/src/VBox/VMM/CPUMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/CPUMInternal.h	(revision 30262)
+++ /trunk/src/VBox/VMM/CPUMInternal.h	(revision 30263)
@@ -294,6 +294,4 @@
     } CR4;
 
-    /** Have we entered rawmode? */
-    bool                    fRawEntered;
     /** Synthetic CPU type? */
     bool                    fSyntheticCpu;
@@ -303,7 +301,5 @@
      * This is used to verify load order dependencies (PGM). */
     bool                    fPendingRestore;
-#if HC_ARCH_BITS == 64
-    uint8_t                 abPadding[4];
-#endif
+    uint8_t                 abPadding[HC_ARCH_BITS == 64 ? 5 : 1];
 
     /** The standard set of CpuId leafs. */
@@ -390,6 +386,11 @@
     uint32_t                u32RetCode;
 
+    /** Have we entered raw-mode? */
+    bool                    fRawEntered;
+    /** Have we entered the recompiler? */
+    bool                    fRemEntered;
+
     /** Align the structure on a 64-byte boundrary. */
-    uint8_t                 abPadding2[HC_ARCH_BITS == 32 ? 36 : 28];
+    uint8_t                 abPadding2[HC_ARCH_BITS == 32 ? 34 : 26];
 } CPUMCPU, *PCPUMCPU;
 /** Pointer to the CPUMCPU instance data residing in the shared VMCPU structure. */
Index: /trunk/src/VBox/VMM/CPUMInternal.mac
===================================================================
--- /trunk/src/VBox/VMM/CPUMInternal.mac	(revision 30262)
+++ /trunk/src/VBox/VMM/CPUMInternal.mac	(revision 30263)
@@ -67,12 +67,11 @@
     .CR4.OrMask           resd    1
     ; entered rawmode?
-    .fRawEntered          resb    1
     .fSyntheticCpu        resb    1
     .u8PortableCpuIdLevel resb    1
     .fPendingRestore      resb    1
 %if RTHCPTR_CB == 8
-    .abPadding            resb    4
+    .abPadding            resb    5
 %else
-;    .abPadding            resb    0
+    .abPadding            resb    1
 %endif
 
@@ -418,9 +417,11 @@
     .offCPUM              resd    1
     .u32RetCode           resd    1
+    .fRawEntered          resb    1
+    .fRemEntered          resb    1
 
 %if RTHCPTR_CB == 8
-    .abPadding2           resb    28
+    .abPadding2           resb    26
 %else
-    .abPadding2           resb    36
+    .abPadding2           resb    34
 %endif
 
Index: /trunk/src/VBox/VMM/DBGFDisas.cpp
===================================================================
--- /trunk/src/VBox/VMM/DBGFDisas.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/DBGFDisas.cpp	(revision 30263)
@@ -339,5 +339,5 @@
 
     if (    pHiddenSel
-        &&  CPUMAreHiddenSelRegsValid(pVM))
+        &&  CPUMAreHiddenSelRegsValid(pVCpu))
     {
         SelInfo.Sel                     = Sel;
@@ -379,5 +379,5 @@
         SelInfo.u.Raw.Gen.u4LimitHigh   = 0xf;
 
-        if (CPUMAreHiddenSelRegsValid(pVM))
+        if (CPUMAreHiddenSelRegsValid(pVCpu))
         {   /* Assume the current CS defines the execution mode. */
             pCtxCore   = CPUMGetGuestCtxCore(pVCpu);
Index: /trunk/src/VBox/VMM/EMRaw.cpp
===================================================================
--- /trunk/src/VBox/VMM/EMRaw.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/EMRaw.cpp	(revision 30263)
@@ -183,9 +183,9 @@
      * Resume execution.
      */
-    CPUMRawEnter(pVCpu, NULL);
+    CPUMR3RawEnter(pVCpu, NULL);
     CPUMSetHyperEFlags(pVCpu, CPUMGetHyperEFlags(pVCpu) | X86_EFL_RF);
     rc = VMMR3ResumeHyper(pVM, pVCpu);
     Log(("emR3RawResumeHyper: cs:eip=%RTsel:%RGr efl=%RGr - returned from GC with rc=%Rrc\n", pCtx->cs, pCtx->eip, pCtx->eflags, rc));
-    rc = CPUMRawLeave(pVCpu, NULL, rc);
+    rc = CPUMR3RawLeave(pVCpu, NULL, rc);
     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
 
@@ -244,5 +244,5 @@
      * We do not start time or anything, if anything we should just do a few nanoseconds.
      */
-    CPUMRawEnter(pVCpu, NULL);
+    CPUMR3RawEnter(pVCpu, NULL);
     do
     {
@@ -257,5 +257,5 @@
     } while (   rc == VINF_SUCCESS
              || rc == VINF_EM_RAW_INTERRUPT);
-    rc = CPUMRawLeave(pVCpu, NULL, rc);
+    rc = CPUMR3RawLeave(pVCpu, NULL, rc);
     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
 
@@ -1477,5 +1477,5 @@
          * and perhaps EIP) needs to be stored with PATM.
          */
-        rc = CPUMRawEnter(pVCpu, NULL);
+        rc = CPUMR3RawEnter(pVCpu, NULL);
         if (rc != VINF_SUCCESS)
         {
@@ -1500,5 +1500,5 @@
                 if (rc != VINF_SUCCESS)
                 {
-                    rc = CPUMRawLeave(pVCpu, NULL, rc);
+                    rc = CPUMR3RawLeave(pVCpu, NULL, rc);
                     break;
                 }
@@ -1542,5 +1542,5 @@
          * execution FFs before doing anything else.
          */
-        rc = CPUMRawLeave(pVCpu, NULL, rc);
+        rc = CPUMR3RawLeave(pVCpu, NULL, rc);
         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_RESUME_GUEST_MASK);
         if (    VM_FF_ISPENDING(pVM, VM_FF_HIGH_PRIORITY_POST_MASK)
Index: /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp	(revision 30263)
@@ -1854,149 +1854,5 @@
 
 
-
-#ifndef IN_RING0  /** @todo I don't think we need this in R0, so move it to CPUMAll.cpp? */
-
-/**
- * Transforms the guest CPU state to raw-ring mode.
- *
- * This function will change the any of the cs and ss register with DPL=0 to DPL=1.
- *
- * @returns VBox status. (recompiler failure)
- * @param   pVCpu       The VMCPU handle.
- * @param   pCtxCore    The context core (for trap usage).
- * @see     @ref pg_raw
- */
-VMMDECL(int) CPUMRawEnter(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore)
-{
-    PVM pVM = pVCpu->CTX_SUFF(pVM);
-
-    Assert(!pVM->cpum.s.fRawEntered);
-    if (!pCtxCore)
-        pCtxCore = CPUMCTX2CORE(&pVCpu->cpum.s.Guest);
-
-    /*
-     * Are we in Ring-0?
-     */
-    if (    pCtxCore->ss && (pCtxCore->ss & X86_SEL_RPL) == 0
-        &&  !pCtxCore->eflags.Bits.u1VM)
-    {
-        /*
-         * Enter execution mode.
-         */
-        PATMRawEnter(pVM, pCtxCore);
-
-        /*
-         * Set CPL to Ring-1.
-         */
-        pCtxCore->ss |= 1;
-        if (pCtxCore->cs && (pCtxCore->cs & X86_SEL_RPL) == 0)
-            pCtxCore->cs |= 1;
-    }
-    else
-    {
-        AssertMsg((pCtxCore->ss & X86_SEL_RPL) >= 2 || pCtxCore->eflags.Bits.u1VM,
-                  ("ring-1 code not supported\n"));
-        /*
-         * PATM takes care of IOPL and IF flags for Ring-3 and Ring-2 code as well.
-         */
-        PATMRawEnter(pVM, pCtxCore);
-    }
-
-    /*
-     * Assert sanity.
-     */
-    AssertMsg((pCtxCore->eflags.u32 & X86_EFL_IF), ("X86_EFL_IF is clear\n"));
-    AssertReleaseMsg(   pCtxCore->eflags.Bits.u2IOPL < (unsigned)(pCtxCore->ss & X86_SEL_RPL)
-                     || pCtxCore->eflags.Bits.u1VM,
-                     ("X86_EFL_IOPL=%d CPL=%d\n", pCtxCore->eflags.Bits.u2IOPL, pCtxCore->ss & X86_SEL_RPL));
-    Assert((pVCpu->cpum.s.Guest.cr0 & (X86_CR0_PG | X86_CR0_WP | X86_CR0_PE)) == (X86_CR0_PG | X86_CR0_PE | X86_CR0_WP));
-    pCtxCore->eflags.u32        |= X86_EFL_IF; /* paranoia */
-
-    pVM->cpum.s.fRawEntered = true;
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Transforms the guest CPU state from raw-ring mode to correct values.
- *
- * This function will change any selector registers with DPL=1 to DPL=0.
- *
- * @returns Adjusted rc.
- * @param   pVCpu       The VMCPU handle.
- * @param   rc          Raw mode return code
- * @param   pCtxCore    The context core (for trap usage).
- * @see     @ref pg_raw
- */
-VMMDECL(int) CPUMRawLeave(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, int rc)
-{
-    PVM pVM = pVCpu->CTX_SUFF(pVM);
-
-    /*
-     * Don't leave if we've already left (in GC).
-     */
-    Assert(pVM->cpum.s.fRawEntered);
-    if (!pVM->cpum.s.fRawEntered)
-        return rc;
-    pVM->cpum.s.fRawEntered = false;
-
-    PCPUMCTX pCtx = &pVCpu->cpum.s.Guest;
-    if (!pCtxCore)
-        pCtxCore = CPUMCTX2CORE(pCtx);
-    Assert(pCtxCore->eflags.Bits.u1VM || (pCtxCore->ss & X86_SEL_RPL));
-    AssertMsg(pCtxCore->eflags.Bits.u1VM || pCtxCore->eflags.Bits.u2IOPL < (unsigned)(pCtxCore->ss & X86_SEL_RPL),
-              ("X86_EFL_IOPL=%d CPL=%d\n", pCtxCore->eflags.Bits.u2IOPL, pCtxCore->ss & X86_SEL_RPL));
-
-    /*
-     * Are we executing in raw ring-1?
-     */
-    if (    (pCtxCore->ss & X86_SEL_RPL) == 1
-        &&  !pCtxCore->eflags.Bits.u1VM)
-    {
-        /*
-         * Leave execution mode.
-         */
-        PATMRawLeave(pVM, pCtxCore, rc);
-        /* Not quite sure if this is really required, but shouldn't harm (too much anyways). */
-        /** @todo See what happens if we remove this. */
-        if ((pCtxCore->ds & X86_SEL_RPL) == 1)
-            pCtxCore->ds &= ~X86_SEL_RPL;
-        if ((pCtxCore->es & X86_SEL_RPL) == 1)
-            pCtxCore->es &= ~X86_SEL_RPL;
-        if ((pCtxCore->fs & X86_SEL_RPL) == 1)
-            pCtxCore->fs &= ~X86_SEL_RPL;
-        if ((pCtxCore->gs & X86_SEL_RPL) == 1)
-            pCtxCore->gs &= ~X86_SEL_RPL;
-
-        /*
-         * Ring-1 selector => Ring-0.
-         */
-        pCtxCore->ss &= ~X86_SEL_RPL;
-        if ((pCtxCore->cs & X86_SEL_RPL) == 1)
-            pCtxCore->cs &= ~X86_SEL_RPL;
-    }
-    else
-    {
-        /*
-         * PATM is taking care of the IOPL and IF flags for us.
-         */
-        PATMRawLeave(pVM, pCtxCore, rc);
-        if (!pCtxCore->eflags.Bits.u1VM)
-        {
-            /** @todo See what happens if we remove this. */
-            if ((pCtxCore->ds & X86_SEL_RPL) == 1)
-                pCtxCore->ds &= ~X86_SEL_RPL;
-            if ((pCtxCore->es & X86_SEL_RPL) == 1)
-                pCtxCore->es &= ~X86_SEL_RPL;
-            if ((pCtxCore->fs & X86_SEL_RPL) == 1)
-                pCtxCore->fs &= ~X86_SEL_RPL;
-            if ((pCtxCore->gs & X86_SEL_RPL) == 1)
-                pCtxCore->gs &= ~X86_SEL_RPL;
-        }
-    }
-
-    return rc;
-}
-
+#ifndef IN_RING0
 /**
  * Updates the EFLAGS while we're in raw-mode.
@@ -2010,5 +1866,5 @@
     PVM pVM = pVCpu->CTX_SUFF(pVM);
 
-    if (!pVM->cpum.s.fRawEntered)
+    if (!pVCpu->cpum.s.fRawEntered)
     {
         pCtxCore->eflags.u32 = eflags;
@@ -2017,6 +1873,6 @@
     PATMRawSetEFlags(pVM, pCtxCore, eflags);
 }
-
 #endif /* !IN_RING0 */
+
 
 /**
@@ -2034,29 +1890,8 @@
     PVM pVM = pVCpu->CTX_SUFF(pVM);
 
-    if (!pVM->cpum.s.fRawEntered)
+    if (!pVCpu->cpum.s.fRawEntered)
         return pCtxCore->eflags.u32;
     return PATMRawGetEFlags(pVM, pCtxCore);
 #endif
-}
-
-
-/**
- * Gets and resets the changed flags (CPUM_CHANGED_*).
- * Only REM should call this function.
- *
- * @returns The changed flags.
- * @param   pVCpu       The VMCPU handle.
- */
-VMMDECL(unsigned) CPUMGetAndClearChangedFlagsREM(PVMCPU pVCpu)
-{
-    unsigned fFlags = pVCpu->cpum.s.fChanged;
-    pVCpu->cpum.s.fChanged = 0;
-    /** @todo change the switcher to use the fChanged flags. */
-    if (pVCpu->cpum.s.fUseFlags & CPUM_USED_FPU_SINCE_REM)
-    {
-        fFlags |= CPUM_CHANGED_FPU_REM;
-        pVCpu->cpum.s.fUseFlags &= ~CPUM_USED_FPU_SINCE_REM;
-    }
-    return fFlags;
 }
 
@@ -2169,5 +2004,5 @@
 
 /**
- * Mark the guest's debug state as inactive
+ * Mark the guest's debug state as inactive.
  *
  * @returns boolean
@@ -2181,5 +2016,5 @@
 
 /**
- * Mark the hypervisor's debug state as inactive
+ * Mark the hypervisor's debug state as inactive.
  *
  * @returns boolean
@@ -2192,12 +2027,16 @@
 
 /**
- * Checks if the hidden selector registers are valid
+ * Checks if the hidden selector registers are valid for the specified CPU.
+ *
  * @returns true if they are.
  * @returns false if not.
- * @param   pVM     The VM handle.
- */
-VMMDECL(bool) CPUMAreHiddenSelRegsValid(PVM pVM)
-{
-    return HWACCMIsEnabled(pVM);
+ * @param   pVCpu     The VM handle.
+ */
+VMMDECL(bool) CPUMAreHiddenSelRegsValid(PVMCPU pVCpu)
+{
+    bool const fRc = !(pVCpu->cpum.s.fChanged & CPUM_CHANGED_HIDDEN_SEL_REGS_INVALID);
+    Assert(fRc || !HWACCMIsEnabled(pVCpu->CTX_SUFF(pVM)));
+    Assert(!pVCpu->cpum.s.fRemEntered);
+    return fRc;
 }
 
@@ -2215,5 +2054,5 @@
     uint32_t cpl;
 
-    if (CPUMAreHiddenSelRegsValid(pVCpu->CTX_SUFF(pVM)))
+    if (CPUMAreHiddenSelRegsValid(pVCpu))
     {
         /*
Index: /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 30262)
+++ /trunk/src/VBox/VMM/VMMAll/PGMAllBth.h	(revision 30263)
@@ -773,5 +773,6 @@
                              */
                             RTGCPTR PC;
-                            rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &PC);
+                            rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs,
+                                                              &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &PC);
                             if (rc == VINF_SUCCESS)
                             {
Index: /trunk/src/VBox/VMM/VMMAll/SELMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/SELMAll.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/VMMAll/SELMAll.cpp	(revision 30263)
@@ -98,5 +98,5 @@
     {
         RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff;
-        if (CPUMAreHiddenSelRegsValid(pVM))
+        if (CPUMAreHiddenSelRegsValid(pVCpu))
             uFlat += pHiddenSel->u64Base;
         else
@@ -106,8 +106,8 @@
 
 #ifdef IN_RING0
-    Assert(CPUMAreHiddenSelRegsValid(pVM));
+    Assert(CPUMAreHiddenSelRegsValid(pVCpu));
 #else
     /** @todo when we're in 16 bits mode, we should cut off the address as well.. */
-    if (!CPUMAreHiddenSelRegsValid(pVM))
+    if (!CPUMAreHiddenSelRegsValid(pVCpu))
         return SELMToFlatBySel(pVM, Sel, Addr);
 #endif
@@ -170,5 +170,5 @@
         {
             if (    pHiddenSel
-                &&  CPUMAreHiddenSelRegsValid(pVM))
+                &&  CPUMAreHiddenSelRegsValid(pVCpu))
                 *ppvGC = (RTGCPTR)(pHiddenSel->u64Base + uFlat);
             else
@@ -186,5 +186,5 @@
 #ifndef IN_RC
     if (    pHiddenSel
-        &&  CPUMAreHiddenSelRegsValid(pVM))
+        &&  CPUMAreHiddenSelRegsValid(pVCpu))
     {
         bool fCheckLimit = true;
@@ -460,5 +460,5 @@
  * @remarks Don't use when in long mode.
  */
-VMMDECL(int) SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, CPUMSELREGHID *pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
+VMMDECL(int) SELMToFlatBySelEx(PVM pVM, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, PCCPUMSELREGHID pHiddenSel, unsigned fFlags, PRTGCPTR ppvGC, uint32_t *pcb)
 {
     PVMCPU pVCpu = VMMGetCpu(pVM);
@@ -476,5 +476,5 @@
         {
             if (    pHiddenSel
-                &&  CPUMAreHiddenSelRegsValid(pVM))
+                &&  CPUMAreHiddenSelRegsValid(pVCpu))
                 *ppvGC = (RTGCPTR)(pHiddenSel->u64Base + uFlat);
             else
@@ -493,5 +493,5 @@
     /** @todo when we're in 16 bits mode, we should cut off the address as well.. */
     if (    pHiddenSel
-        &&  CPUMAreHiddenSelRegsValid(pVM))
+        &&  CPUMAreHiddenSelRegsValid(pVCpu))
     {
         u1Present     = pHiddenSel->Attr.n.u1Present;
@@ -665,5 +665,5 @@
  *
  * @returns VINF_SUCCESS.
- * @param   pVM     VM Handle.
+ * @param   pVCpu   The Virtual CPU handle.
  * @param   SelCS   Selector part.
  * @param   pHidCS  The hidden CS register part. Optional.
@@ -671,8 +671,9 @@
  * @param   ppvFlat Where to store the flat address.
  */
-DECLINLINE(int) selmValidateAndConvertCSAddrRealMode(PVM pVM, RTSEL SelCS, PCPUMSELREGHID pHidCS, RTGCPTR Addr, PRTGCPTR ppvFlat)
+DECLINLINE(int) selmValidateAndConvertCSAddrRealMode(PVMCPU pVCpu, RTSEL SelCS, PCCPUMSELREGHID pHidCS, RTGCPTR Addr,
+                                                     PRTGCPTR ppvFlat)
 {
     RTGCUINTPTR uFlat = (RTGCUINTPTR)Addr & 0xffff;
-    if (!pHidCS || !CPUMAreHiddenSelRegsValid(pVM))
+    if (!pHidCS || !CPUMAreHiddenSelRegsValid(pVCpu))
         uFlat += ((RTGCUINTPTR)SelCS << 4);
     else
@@ -690,4 +691,5 @@
  * @returns VBox status code.
  * @param   pVM     VM Handle.
+ * @param   pVCpu   The virtual CPU handle.
  * @param   SelCPL  Current privilege level. Get this from SS - CS might be conforming!
  *                  A full selector can be passed, we'll only use the RPL part.
@@ -697,8 +699,7 @@
  * @param   pcBits  Where to store the segment bitness (16/32/64). Optional.
  */
-DECLINLINE(int) selmValidateAndConvertCSAddrStd(PVM pVM, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr, PRTGCPTR ppvFlat, uint32_t *pcBits)
-{
-    Assert(!CPUMAreHiddenSelRegsValid(pVM));
-
+DECLINLINE(int) selmValidateAndConvertCSAddrStd(PVM pVM, PVMCPU pVCpu, RTSEL SelCPL, RTSEL SelCS, RTGCPTR Addr,
+                                                PRTGCPTR ppvFlat, uint32_t *pcBits)
+{
     /** @todo validate limit! */
     X86DESC    Desc;
@@ -771,5 +772,6 @@
  * @param   ppvFlat Where to store the flat address.
  */
-DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVMCPU pVCpu, RTSEL SelCPL, RTSEL SelCS, PCPUMSELREGHID pHidCS, RTGCPTR Addr, PRTGCPTR ppvFlat)
+DECLINLINE(int) selmValidateAndConvertCSAddrHidden(PVMCPU pVCpu, RTSEL SelCPL, RTSEL SelCS, PCCPUMSELREGHID pHidCS,
+                                                   RTGCPTR Addr, PRTGCPTR ppvFlat)
 {
     /*
@@ -849,7 +851,8 @@
     {
         *pcBits = 16;
-        return selmValidateAndConvertCSAddrRealMode(pVM, SelCS, NULL, Addr, ppvFlat);
-    }
-    return selmValidateAndConvertCSAddrStd(pVM, SelCPL, SelCS, Addr, ppvFlat, pcBits);
+        return selmValidateAndConvertCSAddrRealMode(pVCpu, SelCS, NULL, Addr, ppvFlat);
+    }
+    Assert(!CPUMAreHiddenSelRegsValid(pVCpu));
+    return selmValidateAndConvertCSAddrStd(pVM, pVCpu, SelCPL, SelCS, Addr, ppvFlat, pcBits);
 }
 #endif /* IN_RC */
@@ -869,5 +872,6 @@
  * @param   ppvFlat      Where to store the flat address.
  */
-VMMDECL(int) SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, CPUMSELREGHID *pHiddenCSSel, RTGCPTR Addr, PRTGCPTR ppvFlat)
+VMMDECL(int) SELMValidateAndConvertCSAddr(PVM pVM, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS, PCCPUMSELREGHID pHiddenCSSel,
+                                          RTGCPTR Addr, PRTGCPTR ppvFlat)
 {
     PVMCPU pVCpu = VMMGetCpu(pVM);
@@ -875,12 +879,12 @@
     if (    eflags.Bits.u1VM
         ||  CPUMIsGuestInRealMode(pVCpu))
-        return selmValidateAndConvertCSAddrRealMode(pVM, SelCS, pHiddenCSSel, Addr, ppvFlat);
+        return selmValidateAndConvertCSAddrRealMode(pVCpu, SelCS, pHiddenCSSel, Addr, ppvFlat);
 
 #ifdef IN_RING0
-    Assert(CPUMAreHiddenSelRegsValid(pVM));
+    Assert(CPUMAreHiddenSelRegsValid(pVCpu));
 #else
     /** @todo when we're in 16 bits mode, we should cut off the address as well? (like in selmValidateAndConvertCSAddrRealMode) */
-    if (!CPUMAreHiddenSelRegsValid(pVM))
-        return selmValidateAndConvertCSAddrStd(pVM, SelCPL, SelCS, Addr, ppvFlat, NULL);
+    if (!CPUMAreHiddenSelRegsValid(pVCpu) || !pHiddenCSSel)
+        return selmValidateAndConvertCSAddrStd(pVM, pVCpu, SelCPL, SelCS, Addr, ppvFlat, NULL);
 #endif
     return selmValidateAndConvertCSAddrHidden(pVCpu, SelCPL, SelCS, pHiddenCSSel, Addr, ppvFlat);
@@ -894,9 +898,10 @@
  * @returns DISCPUMODE according to the selector type (16, 32 or 64 bits)
  * @param   pVM     VM Handle.
+ * @param   pVCpu   The virtual CPU handle.
  * @param   Sel     The selector.
  */
-static DISCPUMODE selmGetCpuModeFromSelector(PVM pVM, RTSEL Sel)
-{
-    Assert(!CPUMAreHiddenSelRegsValid(pVM));
+static DISCPUMODE selmGetCpuModeFromSelector(PVM pVM, PVMCPU pVCpu, RTSEL Sel)
+{
+    Assert(!CPUMAreHiddenSelRegsValid(pVCpu));
 
     /** @todo validate limit! */
@@ -924,11 +929,11 @@
  * @param   pHiddenSel The hidden selector register.
  */
-VMMDECL(DISCPUMODE) SELMGetCpuModeFromSelector(PVM pVM, X86EFLAGS eflags, RTSEL Sel, CPUMSELREGHID *pHiddenSel)
+VMMDECL(DISCPUMODE) SELMGetCpuModeFromSelector(PVM pVM, X86EFLAGS eflags, RTSEL Sel, PCCPUMSELREGHID pHiddenSel)
 {
     PVMCPU pVCpu = VMMGetCpu(pVM);
 #ifdef IN_RING0
-    Assert(CPUMAreHiddenSelRegsValid(pVM));
+    Assert(CPUMAreHiddenSelRegsValid(pVCpu));
 #else  /* !IN_RING0 */
-    if (!CPUMAreHiddenSelRegsValid(pVM))
+    if (!CPUMAreHiddenSelRegsValid(pVCpu))
     {
         /*
@@ -939,5 +944,5 @@
             return CPUMODE_16BIT;
 
-        return selmGetCpuModeFromSelector(pVM, Sel);
+        return selmGetCpuModeFromSelector(pVM, pVCpu, Sel);
     }
 #endif /* !IN_RING0 */
@@ -947,5 +952,5 @@
 
     /* Else compatibility or 32 bits mode. */
-    return (pHiddenSel->Attr.n.u1DefBig) ? CPUMODE_32BIT : CPUMODE_16BIT;
+    return pHiddenSel->Attr.n.u1DefBig ? CPUMODE_32BIT : CPUMODE_16BIT;
 }
 
Index: /trunk/src/VBox/VMM/VMMAll/TRPMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/TRPMAll.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/VMMAll/TRPMAll.cpp	(revision 30263)
@@ -358,5 +358,6 @@
  * @internal
  */
-VMMDECL(int) TRPMForwardTrap(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t iGate, uint32_t opsize, TRPMERRORCODE enmError, TRPMEVENT enmType, int32_t iOrgTrap)
+VMMDECL(int) TRPMForwardTrap(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t iGate, uint32_t opsize,
+                             TRPMERRORCODE enmError, TRPMEVENT enmType, int32_t iOrgTrap)
 {
 #ifdef TRPM_FORWARD_TRAPS_IN_GC
Index: /trunk/src/VBox/VMM/VMMGC/TRPMGC.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMGC/TRPMGC.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/VMMGC/TRPMGC.cpp	(revision 30263)
@@ -175,5 +175,6 @@
      */
     RTGCPTR PC;
-    int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &PC);
+    int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid,
+                                          (RTGCPTR)pRegFrame->eip, &PC);
     if (rc == VINF_SUCCESS)
     {
Index: /trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp	(revision 30263)
@@ -380,5 +380,6 @@
          */
         RTGCPTR PC;
-        rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &PC);
+        rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid,
+                                          (RTGCPTR)pRegFrame->eip, &PC);
         if (RT_FAILURE(rc))
         {
@@ -507,5 +508,7 @@
      */
     RTGCPTR GCPtr;
-    if (SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->eip, &GCPtr) == VINF_SUCCESS)
+    if (   SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid,
+                                        (RTGCPTR)pRegFrame->eip, &GCPtr)
+        == VINF_SUCCESS)
     {
         uint8_t *pu8Code = (uint8_t *)(uintptr_t)GCPtr;
Index: /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 30262)
+++ /trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 30263)
@@ -2742,5 +2742,6 @@
     {
         RTGCPTR pbCode;
-        int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs, &pRegFrame->csHid, (RTGCPTR)pRegFrame->rip, &pbCode);
+        int rc = SELMValidateAndConvertCSAddr(pVM, pRegFrame->eflags, pRegFrame->ss, pRegFrame->cs,
+                                              &pRegFrame->csHid, (RTGCPTR)pRegFrame->rip, &pbCode);
         if (RT_SUCCESS(rc))
         {
Index: /trunk/src/recompiler/VBoxREMWrapper.cpp
===================================================================
--- /trunk/src/recompiler/VBoxREMWrapper.cpp	(revision 30262)
+++ /trunk/src/recompiler/VBoxREMWrapper.cpp	(revision 30263)
@@ -545,4 +545,16 @@
 };
 
+static const REMPARMDESC g_aArgsCPUMR3RemEnter[] =
+{
+    { REMPARMDESC_FLAGS_INT,        sizeof(PVMCPU),             NULL },
+    { REMPARMDESC_FLAGS_INT,        sizeof(uint32_t *),         NULL }
+};
+
+static const REMPARMDESC g_aArgsCPUMR3RemLeave[] =
+{
+    { REMPARMDESC_FLAGS_INT,        sizeof(PVMCPU),             NULL },
+    { REMPARMDESC_FLAGS_INT,        sizeof(bool),               NULL }
+};
+
 static const REMPARMDESC g_aArgsCPUMSetChangedFlags[] =
 {
@@ -1170,6 +1182,7 @@
 static REMFNDESC g_aVMMImports[] =
 {
-    { "CPUMAreHiddenSelRegsValid",              VMM_FN(CPUMAreHiddenSelRegsValid),      &g_aArgsVM[0],                              RT_ELEMENTS(g_aArgsVM),                                REMFNDESC_FLAGS_RET_INT,    sizeof(bool),       NULL },
-    { "CPUMGetAndClearChangedFlagsREM",         VMM_FN(CPUMGetAndClearChangedFlagsREM), &g_aArgsVM[0],                              RT_ELEMENTS(g_aArgsVM),                                REMFNDESC_FLAGS_RET_INT,    sizeof(unsigned),   NULL },
+    { "CPUMAreHiddenSelRegsValid",              VMM_FN(CPUMAreHiddenSelRegsValid),      &g_aArgsVMCPU[0],                           RT_ELEMENTS(g_aArgsVMCPU),                             REMFNDESC_FLAGS_RET_INT,    sizeof(bool),       NULL },
+    { "CPUMR3RemEnter",                         VMM_FN(CPUMR3RemEnter),                 &g_aArgsCPUMR3RemEnter[0],                  RT_ELEMENTS(g_aArgsCPUMR3RemEnter),                    REMFNDESC_FLAGS_RET_INT,    sizeof(uint32_t),   NULL },
+    { "CPUMR3RemLeave",                         VMM_FN(CPUMR3RemLeave),                 &g_aArgsCPUMR3RemLeave[0],                  RT_ELEMENTS(g_aArgsCPUMR3RemLeave),                    REMFNDESC_FLAGS_RET_VOID,   0,                  NULL },
     { "CPUMSetChangedFlags",                    VMM_FN(CPUMSetChangedFlags),            &g_aArgsCPUMSetChangedFlags[0],             RT_ELEMENTS(g_aArgsCPUMSetChangedFlags),               REMFNDESC_FLAGS_RET_VOID,   0,                  NULL },
     { "CPUMGetGuestCPL",                        VMM_FN(CPUMGetGuestCPL),                &g_aArgsCPUMGetGuestCpl[0],                 RT_ELEMENTS(g_aArgsCPUMGetGuestCpl),                   REMFNDESC_FLAGS_RET_INT,    sizeof(unsigned),   NULL },
Index: /trunk/src/recompiler/VBoxRecompiler.c
===================================================================
--- /trunk/src/recompiler/VBoxRecompiler.c	(revision 30262)
+++ /trunk/src/recompiler/VBoxRecompiler.c	(revision 30263)
@@ -1798,4 +1798,5 @@
     TRPMEVENT               enmType;
     uint8_t                 u8TrapNo;
+    uint32_t                uCpl;
     int                     rc;
 
@@ -1805,5 +1806,5 @@
     pVM->rem.s.Env.pVCpu = pVCpu;
     pCtx = pVM->rem.s.pCtx = CPUMQueryGuestCtxPtr(pVCpu);
-    fHiddenSelRegsValid = CPUMAreHiddenSelRegsValid(pVM);
+    fHiddenSelRegsValid = CPUMAreHiddenSelRegsValid(pVCpu); /// @todo move this down and use fFlags.
 
     Assert(!pVM->rem.s.fInREM);
@@ -1927,6 +1928,6 @@
      * Registers which are rarely changed and require special handling / order when changed.
      */
-    fFlags = CPUMGetAndClearChangedFlagsREM(pVCpu);
-    LogFlow(("CPUMGetAndClearChangedFlagsREM %x\n", fFlags));
+    fFlags = CPUMR3RemEnter(pVCpu, &uCpl);
+    LogFlow(("CPUMR3RemEnter %x %x\n", fFlags, uCpl));
     if (fFlags & (  CPUM_CHANGED_CR4  | CPUM_CHANGED_CR3  | CPUM_CHANGED_CR0
                   | CPUM_CHANGED_GDTR | CPUM_CHANGED_IDTR | CPUM_CHANGED_LDTR
@@ -2041,5 +2042,5 @@
 
         /* Set current CPL */
-        cpu_x86_set_cpl(&pVM->rem.s.Env, CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(pCtx)));
+        cpu_x86_set_cpl(&pVM->rem.s.Env, uCpl);
 
         cpu_x86_load_seg_cache(&pVM->rem.s.Env, R_CS, pCtx->cs, pCtx->csHid.u64Base, pCtx->csHid.u32Limit, (pCtx->csHid.Attr.u << 8) & 0xFFFFFF);
@@ -2057,5 +2058,5 @@
             Log2(("REMR3State: SS changed from %04x to %04x!\n", pVM->rem.s.Env.segs[R_SS].selector, pCtx->ss));
 
-            cpu_x86_set_cpl(&pVM->rem.s.Env, CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(pCtx)));
+            cpu_x86_set_cpl(&pVM->rem.s.Env, uCpl);
             sync_seg(&pVM->rem.s.Env, R_SS, pCtx->ss);
 #ifdef VBOX_WITH_STATISTICS
@@ -2475,4 +2476,13 @@
      * We're not longer in REM mode.
      */
+    CPUMR3RemLeave(pVCpu,
+                      HWACCMIsEnabled(pVM)
+                   || (  pVM->rem.s.Env.segs[R_SS].newselector
+                       | pVM->rem.s.Env.segs[R_GS].newselector
+                       | pVM->rem.s.Env.segs[R_FS].newselector
+                       | pVM->rem.s.Env.segs[R_ES].newselector
+                       | pVM->rem.s.Env.segs[R_DS].newselector
+                       | pVM->rem.s.Env.segs[R_CS].newselector) == 0
+                   );
     VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED, VMCPUSTATE_STARTED_EXEC_REM);
     pVM->rem.s.fInREM    = false;
