Index: /trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncsBltIn.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncsBltIn.cpp	(revision 100800)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllThrdFuncsBltIn.cpp	(revision 100801)
@@ -315,4 +315,25 @@
     } while(0)
 
+/**
+ * Macro that considers whether we need CS.LIM checking after a branch or
+ * crossing over to a new page.
+ *
+ * This may long jump if we're raising a \#PF, \#GP or similar trouble.
+ */
+#define BODY_CONSIDER_CS_LIM_CHECKING(a_pTb, a_cbInstr) do { \
+        int64_t const offFromLim = (int64_t)pVCpu->cpum.GstCtx.cs.u32Limit - (int64_t)pVCpu->cpum.GstCtx.eip; \
+        if (offFromLim >= GUEST_PAGE_SIZE + 16 - (int32_t)(pVCpu->cpum.GstCtx.cs.u64Base & GUEST_PAGE_OFFSET_MASK)) \
+        { /* likely */ } \
+        else \
+        { \
+            Log7(("TB need CS.LIM: %p at %04x:%08RX64 LB %u; #%u offFromLim=%#RX64 CS.LIM=%#RX32 CS.BASE=%#RX64\n", \
+                  (a_pTb), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, (a_cbInstr), offFromLim, \
+                  pVCpu->cpum.GstCtx.cs.u32Limit, pVCpu->cpum.GstCtx.cs.u64Base, __LINE__)); \
+            RT_NOREF(a_pTb, a_cbInstr); \
+            return iemThreadeFuncWorkerObsoleteTb(pVCpu); \
+        } \
+    } while(0)
+
+
 
 /**
@@ -360,4 +381,20 @@
 
 
+/**
+ * Built-in function for re-checking opcodes and considering the need for CS.LIM
+ * checking after an instruction that may have modified them.
+ */
+IEM_DECL_IEMTHREADEDFUNC_DEF(iemThreadedFunc_BltIn_CheckOpcodesConsiderCsLim)
+{
+    PCIEMTB const  pTb      = pVCpu->iem.s.pCurTbR3;
+    uint32_t const cbInstr  = (uint32_t)uParam0;
+    uint32_t const idxRange = (uint32_t)uParam1;
+    uint32_t const offRange = (uint32_t)uParam2;
+    BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
+    BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
+    return VINF_SUCCESS;
+}
+
+
 /*
  * Post-branching checkers.
@@ -406,4 +443,26 @@
 
 /**
+ * Built-in function for checking the PC and checking opcodes and considering
+ * the need for CS.LIM checking after conditional branching within the same
+ * page.
+ *
+ * @see iemThreadedFunc_BltIn_CheckCsLimAndPcAndOpcodes
+ */
+IEM_DECL_IEMTHREADEDFUNC_DEF(iemThreadedFunc_BltIn_CheckPcAndOpcodesConsiderCsLim)
+{
+    PCIEMTB const  pTb      = pVCpu->iem.s.pCurTbR3;
+    uint32_t const cbInstr  = (uint32_t)uParam0;
+    uint32_t const idxRange = (uint32_t)uParam1;
+    uint32_t const offRange = (uint32_t)uParam2;
+    //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
+    BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
+    BODY_CHECK_PC_AFTER_BRANCH(pTb, idxRange, cbInstr);
+    BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
+    //LogFunc(("okay\n"));
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Built-in function for checking CS.LIM, loading TLB and checking opcodes when
  * transitioning to a different code page.
@@ -445,4 +504,28 @@
     uint32_t const offRange = (uint32_t)uParam2;
     //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
+    BODY_LOAD_TLB_AFTER_BRANCH(pTb, idxRange, cbInstr);
+    BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
+    //LogFunc(("okay\n"));
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Built-in function for loading TLB and checking opcodes and considering the
+ * need for CS.LIM checking when transitioning to a different code page.
+ *
+ * The code page transition can either be natural over onto the next page (with
+ * the instruction starting at page offset zero) or by means of branching.
+ *
+ * @see iemThreadedFunc_BltIn_CheckCsLimAndOpcodesLoadingTlb
+ */
+IEM_DECL_IEMTHREADEDFUNC_DEF(iemThreadedFunc_BltIn_CheckOpcodesLoadingTlbConsiderCsLim)
+{
+    PCIEMTB const  pTb      = pVCpu->iem.s.pCurTbR3;
+    uint32_t const cbInstr  = (uint32_t)uParam0;
+    uint32_t const idxRange = (uint32_t)uParam1;
+    uint32_t const offRange = (uint32_t)uParam2;
+    //LogFunc(("idxRange=%u @ %#x LB %#x: offPhysPage=%#x LB %#x\n", idxRange, offRange, cbInstr, pTb->aRanges[idxRange].offPhysPage, pTb->aRanges[idxRange].cbOpcodes));
+    BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
     BODY_LOAD_TLB_AFTER_BRANCH(pTb, idxRange, cbInstr);
     BODY_CHECK_OPCODES(pTb, idxRange, offRange, cbInstr);
@@ -509,4 +592,31 @@
 
 /**
+ * Built-in function for loading TLB and checking opcodes on both pages and
+ * considering the need for CS.LIM checking when transitioning to a different
+ * code page.
+ *
+ * This is used when the previous instruction requires revalidation of opcodes
+ * bytes and the current instruction stries a page boundrary with opcode bytes
+ * in both the old and new page.
+ *
+ * @see iemThreadedFunc_BltIn_CheckCsLimAndOpcodesAcrossPageLoadingTlb
+ */
+IEM_DECL_IEMTHREADEDFUNC_DEF(iemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlbConsiderCsLim)
+{
+    PCIEMTB const  pTb         = pVCpu->iem.s.pCurTbR3;
+    uint32_t const cbInstr     = (uint32_t)uParam0;
+    uint32_t const cbStartPage = (uint32_t)(uParam0 >> 32);
+    uint32_t const idxRange1   = (uint32_t)uParam1;
+    uint32_t const offRange1   = (uint32_t)uParam2;
+    uint32_t const idxRange2   = idxRange1 + 1;
+    BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
+    BODY_CHECK_OPCODES(pTb, idxRange1, offRange1, cbInstr);
+    BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr);
+    BODY_CHECK_OPCODES(pTb, idxRange2, 0, cbInstr);
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Built-in function for checking CS.LIM, loading TLB and checking opcodes when
  * advancing naturally to a different code page.
@@ -556,4 +666,28 @@
 
 /**
+ * Built-in function for loading TLB and checking opcodes and considering the
+ * need for CS.LIM checking when advancing naturally to a different code page.
+ *
+ * Only opcodes on the new page is checked.
+ *
+ * @see iemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNextPageLoadingTlb
+ */
+IEM_DECL_IEMTHREADEDFUNC_DEF(iemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlbConsiderCsLim)
+{
+    PCIEMTB const  pTb         = pVCpu->iem.s.pCurTbR3;
+    uint32_t const cbInstr     = (uint32_t)uParam0;
+    uint32_t const cbStartPage = (uint32_t)(uParam0 >> 32);
+    uint32_t const idxRange1   = (uint32_t)uParam1;
+    //uint32_t const offRange1   = (uint32_t)uParam2;
+    uint32_t const idxRange2   = idxRange1 + 1;
+    BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
+    BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, cbStartPage, idxRange2, cbInstr);
+    BODY_CHECK_OPCODES(pTb, idxRange2, 0, cbInstr);
+    RT_NOREF(uParam2);
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Built-in function for checking CS.LIM, loading TLB and checking opcodes when
  * advancing naturally to a different code page with first instr at byte 0.
@@ -593,2 +727,23 @@
 }
 
+
+/**
+ * Built-in function for loading TLB and checking opcodes and considering the
+ * need for CS.LIM checking when advancing naturally to a different code page
+ * with first instr at byte 0.
+ *
+ * @see iemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNewPageLoadingTlb
+ */
+IEM_DECL_IEMTHREADEDFUNC_DEF(iemThreadedFunc_BltIn_CheckOpcodesOnNewPageLoadingTlbConsiderCsLim)
+{
+    PCIEMTB const  pTb         = pVCpu->iem.s.pCurTbR3;
+    uint32_t const cbInstr     = (uint32_t)uParam0;
+    uint32_t const idxRange    = (uint32_t)uParam1;
+    Assert(uParam2 == 0 /*offRange*/); RT_NOREF(uParam2);
+    BODY_CONSIDER_CS_LIM_CHECKING(pTb, cbInstr);
+    BODY_LOAD_TLB_FOR_NEW_PAGE(pTb, 0, idxRange, cbInstr);
+    Assert(pVCpu->iem.s.offCurInstrStart == 0);
+    BODY_CHECK_OPCODES(pTb, idxRange, 0, cbInstr);
+    return VINF_SUCCESS;
+}
+
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py	(revision 100800)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllThrdPython.py	(revision 100801)
@@ -1384,16 +1384,28 @@
         'CheckMode',
         'CheckCsLim',
+
         'CheckCsLimAndOpcodes',
         'CheckOpcodes',
+        'CheckOpcodesConsiderCsLim',
+
         'CheckCsLimAndPcAndOpcodes',
         'CheckPcAndOpcodes',
+        'CheckPcAndOpcodesConsiderCsLim',
+
         'CheckCsLimAndOpcodesAcrossPageLoadingTlb',
         'CheckOpcodesAcrossPageLoadingTlb',
+        'CheckOpcodesAcrossPageLoadingTlbConsiderCsLim',
+
         'CheckCsLimAndOpcodesLoadingTlb',
         'CheckOpcodesLoadingTlb',
+        'CheckOpcodesLoadingTlbConsiderCsLim',
+
         'CheckCsLimAndOpcodesOnNextPageLoadingTlb',
         'CheckOpcodesOnNextPageLoadingTlb',
+        'CheckOpcodesOnNextPageLoadingTlbConsiderCsLim',
+
         'CheckCsLimAndOpcodesOnNewPageLoadingTlb',
         'CheckOpcodesOnNewPageLoadingTlb',
+        'CheckOpcodesOnNewPageLoadingTlbConsiderCsLim',
     );
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp	(revision 100800)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllThrdRecompiler.cpp	(revision 100801)
@@ -865,5 +865,5 @@
  *
  * @returns true if everything went well, false if we're out of space in the TB
- *          (e.g. opcode ranges).
+ *          (e.g. opcode ranges) or needs to start doing CS.LIM checks.
  * @param   pVCpu       The cross context virtual CPU structure of the calling
  *                      thread.
@@ -877,4 +877,27 @@
         RTLogChangeFlags(NULL, 0, RTLOGFLAGS_DISABLED);
 #endif
+
+    /*
+     * If we're not in 64-bit mode and not already checking CS.LIM we need to
+     * see if it's needed to start checking.
+     */
+    bool           fConsiderCsLimChecking;
+    uint32_t const fMode = pVCpu->iem.s.fExec & IEM_F_MODE_MASK;
+    if (   fMode == IEM_F_MODE_X86_64BIT
+        || (pTb->fFlags & IEMTB_F_CS_LIM_CHECKS)
+        || fMode == IEM_F_MODE_X86_32BIT_PROT_FLAT
+        || fMode == IEM_F_MODE_X86_32BIT_FLAT)
+        fConsiderCsLimChecking = false; /* already enabled or not needed */
+    else
+    {
+        int64_t const offFromLim = (int64_t)pVCpu->cpum.GstCtx.cs.u32Limit - (int64_t)pVCpu->cpum.GstCtx.eip;
+        if (offFromLim >= GUEST_PAGE_SIZE + 16 - (int32_t)(pVCpu->cpum.GstCtx.cs.u64Base & GUEST_PAGE_OFFSET_MASK))
+            fConsiderCsLimChecking = true; /* likely */
+        else
+        {
+            Log8(("%04x:%08RX64: Needs CS.LIM checks (%#RX64)\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, offFromLim));
+            return false;
+        }
+    }
 
     /*
@@ -1000,9 +1023,13 @@
                 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS
                                    ? kIemThreadedFunc_BltIn_CheckCsLimAndOpcodesLoadingTlb
-                                   : kIemThreadedFunc_BltIn_CheckOpcodesLoadingTlb;
+                                   : !fConsiderCsLimChecking
+                                   ? kIemThreadedFunc_BltIn_CheckOpcodesLoadingTlb
+                                   : kIemThreadedFunc_BltIn_CheckOpcodesLoadingTlbConsiderCsLim;
             else if (pVCpu->iem.s.fTbBranched & (IEMBRANCHED_F_CONDITIONAL | /* paranoia: */ IEMBRANCHED_F_DIRECT))
                 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS
                                    ? kIemThreadedFunc_BltIn_CheckCsLimAndPcAndOpcodes
-                                   : kIemThreadedFunc_BltIn_CheckPcAndOpcodes;
+                                   : !fConsiderCsLimChecking
+                                   ? kIemThreadedFunc_BltIn_CheckPcAndOpcodes
+                                   : kIemThreadedFunc_BltIn_CheckPcAndOpcodesConsiderCsLim;
             else
             {
@@ -1010,5 +1037,7 @@
                 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS
                                    ? kIemThreadedFunc_BltIn_CheckCsLimAndOpcodes
-                                   : kIemThreadedFunc_BltIn_CheckOpcodes;
+                                   : !fConsiderCsLimChecking
+                                   ? kIemThreadedFunc_BltIn_CheckOpcodes
+                                   : kIemThreadedFunc_BltIn_CheckOpcodesConsiderCsLim;
             }
         }
@@ -1112,5 +1141,7 @@
             pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS
                                ? kIemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNewPageLoadingTlb
-                               : kIemThreadedFunc_BltIn_CheckOpcodesOnNewPageLoadingTlb;
+                               : !fConsiderCsLimChecking
+                               ? kIemThreadedFunc_BltIn_CheckOpcodesOnNewPageLoadingTlb
+                               : kIemThreadedFunc_BltIn_CheckOpcodesOnNewPageLoadingTlbConsiderCsLim;
         }
         else
@@ -1134,9 +1165,13 @@
                 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS
                                    ? kIemThreadedFunc_BltIn_CheckCsLimAndOpcodesAcrossPageLoadingTlb
-                                   : kIemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlb;
+                                   : !fConsiderCsLimChecking
+                                   ? kIemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlb
+                                   : kIemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlbConsiderCsLim;
             else
                 pCall->enmFunction = pTb->fFlags & IEMTB_F_CS_LIM_CHECKS
                                    ? kIemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNextPageLoadingTlb
-                                   : kIemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlb;
+                                   : !fConsiderCsLimChecking
+                                   ? kIemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlb
+                                   : kIemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlbConsiderCsLim;
         }
     }
@@ -1569,11 +1604,10 @@
      */
     if (IEM_IS_64BIT_CODE(pVCpu))
-    { /* done */ }
-    else if (RT_LIKELY(   pVCpu->cpum.GstCtx.eip < pVCpu->cpum.GstCtx.cs.u32Limit
-                       && pVCpu->cpum.GstCtx.cs.u32Limit - pVCpu->cpum.GstCtx.eip >= X86_PAGE_SIZE))
-    { /* done */ }
-    else
-        fRet |= IEMTB_F_CS_LIM_CHECKS;
-    return fRet;
+        return fRet;
+
+    int64_t const offFromLim = (int64_t)pVCpu->cpum.GstCtx.cs.u32Limit - (int64_t)pVCpu->cpum.GstCtx.eip;
+    if (offFromLim >= X86_PAGE_SIZE + 16 - (int32_t)(pVCpu->cpum.GstCtx.cs.u64Base & GUEST_PAGE_OFFSET_MASK))
+        return fRet;
+    return fRet | IEMTB_F_CS_LIM_CHECKS;
 }
 
Index: /trunk/src/VBox/VMM/include/IEMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 100800)
+++ /trunk/src/VBox/VMM/include/IEMInternal.h	(revision 100801)
@@ -5014,21 +5014,27 @@
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckCsLimAndOpcodes);
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodes);
+IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesConsiderCsLim);
 
 /* Branching: */
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckCsLimAndPcAndOpcodes);
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckPcAndOpcodes);
+IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckPcAndOpcodesConsiderCsLim);
 
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckCsLimAndOpcodesLoadingTlb);
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesLoadingTlb);
+IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesLoadingTlbConsiderCsLim);
 
 /* Natural page crossing: */
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckCsLimAndOpcodesAcrossPageLoadingTlb);
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlb);
+IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesAcrossPageLoadingTlbConsiderCsLim);
 
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNextPageLoadingTlb);
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlb);
+IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesOnNextPageLoadingTlbConsiderCsLim);
 
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckCsLimAndOpcodesOnNewPageLoadingTlb);
 IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesOnNewPageLoadingTlb);
+IEM_DECL_IEMTHREADEDFUNC_PROTO(iemThreadedFunc_BltIn_CheckOpcodesOnNewPageLoadingTlbConsiderCsLim);
 
 bool iemThreadedCompileEmitIrqCheckBefore(PVMCPUCC pVCpu, PIEMTB pTb);
