Index: trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c
===================================================================
--- trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c	(revision 66392)
+++ trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1-template.c	(revision 66404)
@@ -395,4 +395,7 @@
     /* [BS3CG1DST_OZ_R14] = */  BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
     /* [BS3CG1DST_OZ_R15] = */  BS3CG1DSTSIZE_OPERAND_SIZE_GRP,
+
+    /* [BS3CG1DST_CR0] = */     4,
+    /* [BS3CG1DST_CR4] = */     4,
 
     /* [BS3CG1DST_FCW] = */         2,
@@ -623,4 +626,7 @@
     /* [BS3CG1DST_OZ_R15] = */      RT_OFFSETOF(BS3REGCTX, r15),
 
+    /* [BS3CG1DST_CR0] = */         RT_OFFSETOF(BS3REGCTX, cr0),
+    /* [BS3CG1DST_CR4] = */         RT_OFFSETOF(BS3REGCTX, cr4),
+
     /* [BS3CG1DST_FCW] = */         sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FCW),
     /* [BS3CG1DST_FSW] = */         sizeof(BS3REGCTX) + RT_OFFSETOF(BS3EXTCTX, Ctx.x87.FSW),
@@ -852,4 +858,7 @@
     { "OZ_R15" },
 
+    { "CR0" },
+    { "CR4" },
+
     { "FCW" },
     { "FSW" },
@@ -861,5 +870,4 @@
     { "FPUDS" },
     { "MXCSR" },
-    { "MXCSR_M" },
     { "ST0" },
     { "ST1" },
@@ -977,4 +985,5 @@
     { "VALXCPT" },
 };
+AssertCompile(RT_ELEMENTS(g_aszBs3Cg1DstFields) >= BS3CG1DST_END);
 AssertCompile(RT_ELEMENTS(g_aszBs3Cg1DstFields) == BS3CG1DST_END);
 
@@ -1556,4 +1565,18 @@
             break;
 
+        case BS3CG1ENC_MODRM_MdRO:
+            if (iEncoding == 0)
+            {
+                off = Bs3Cg1InsertOpcodes(pThis, Bs3Cg1InsertReqPrefix(pThis, 0)) - 1;
+                off = Bs3Cfg1EncodeMemMod0Disp(pThis, false, off,
+                                               (pThis->abCurInstr[off] & X86_MODRM_REG_MASK) >> X86_MODRM_REG_SHIFT,
+                                               4, 0, BS3CG1OPLOC_MEM);
+            }
+            else
+                break;
+            pThis->cbCurInstr = off;
+            iEncoding++;
+            break;
+
         case BS3CG1ENC_MODRM_MdWO:
             if (iEncoding == 0)
@@ -1836,4 +1859,10 @@
             pThis->iRmOp             = 0;
             pThis->aOperands[0].cbOp = 1;
+            pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
+            break;
+
+        case BS3CG1ENC_MODRM_MdRO:
+            pThis->iRmOp             = 0;
+            pThis->aOperands[0].cbOp = 4;
             pThis->aOperands[0].enmLocation = BS3CG1OPLOC_MEM;
             break;
@@ -2166,4 +2195,5 @@
         case BS3CG1_CTXOP_AND:      return "&=";
         case BS3CG1_CTXOP_AND_INV:  return "&~=";
+        default:                    return "?WTF?";
     }
 }
@@ -3284,5 +3314,5 @@
 #if 0
     /* (for debugging) */
-    if (!BS3_MODE_IS_RM_OR_V86(bMode))
+    if (bMode != BS3_MODE_PPV86)
         return BS3TESTDOMODE_SKIPPED;
 #endif
Index: trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h
===================================================================
--- trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h	(revision 66392)
+++ trunk/src/VBox/ValidationKit/bootsectors/bs3-cpu-generated-1.h	(revision 66404)
@@ -70,4 +70,5 @@
     BS3CG1OP_Ma,
     BS3CG1OP_MbRO,
+    BS3CG1OP_MdRO,
     BS3CG1OP_MdWO,
     BS3CG1OP_Mq,
@@ -104,4 +105,5 @@
     BS3CG1ENC_MODRM_Vdq_Wdq,
     BS3CG1ENC_MODRM_MbRO,
+    BS3CG1ENC_MODRM_MdRO,
     BS3CG1ENC_MODRM_MdWO,
 
@@ -410,4 +412,8 @@
     BS3CG1DST_OZ_R14,
     BS3CG1DST_OZ_R15,
+
+    /* Control registers.*/
+    BS3CG1DST_CR0,
+    BS3CG1DST_CR4,
 
     /* FPU registers. */
Index: trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm
===================================================================
--- trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm	(revision 66392)
+++ trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxRestore.asm	(revision 66404)
@@ -309,4 +309,6 @@
         je      .skip_control_regs
 %endif
+        test    byte [xBX + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_TR_LDTR
+        jnz     .skip_control_regs
 
         ; LDTR
Index: trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveEx.asm
===================================================================
--- trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveEx.asm	(revision 66392)
+++ trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-RegCtxSaveEx.asm	(revision 66404)
@@ -33,4 +33,7 @@
 ;*********************************************************************************************************************************
 BS3_EXTERN_DATA16   g_bBs3CurrentMode
+%if ARCH_BITS != 64
+BS3_EXTERN_DATA16   g_uBs3CpuDetected
+%endif
 
 TMPL_BEGIN_TEXT
@@ -97,4 +100,7 @@
         push    xBP
         mov     xBP, xSP
+%if ARCH_BITS == 64
+        push    rcx                     ; Save pRegCtx
+%endif
 
         ;
@@ -151,5 +157,4 @@
         BS3_CALL_CONV_EPILOG 3
         BS3_HYBRID_RET
-
 
         ;
@@ -218,5 +223,5 @@
 %endif
         BS3_SET_BITS TMPL_BITS
-        jmp     .return
+        jmp     .supplement_and_return
         TMPL_BEGIN_TEXT
 
@@ -256,5 +261,5 @@
         call    _Bs3SwitchTo%[TMPL_BITS]Bit_c16
         BS3_SET_BITS TMPL_BITS
-        jmp     .return
+        jmp     .supplement_and_return
 TMPL_BEGIN_TEXT
 %endif
@@ -292,13 +297,15 @@
         call    _Bs3SwitchTo16Bit_c32
         BS3_SET_BITS TMPL_BITS
-        jmp     .return
+        jmp     .supplement_and_return
 .code_32_back_to_v86:
         BS3_SET_BITS 32
         call    _Bs3SwitchTo16BitV86_c32
+        BS3_SET_BITS TMPL_BITS
+        jmp     .return
  %else
         call    _Bs3SwitchTo64Bit_c32
- %endif
-        BS3_SET_BITS TMPL_BITS
-        jmp     .return
+        BS3_SET_BITS TMPL_BITS
+        jmp     .supplement_and_return
+ %endif
 %endif
 
@@ -334,5 +341,110 @@
         jmp     .return
 %endif
+
+
+        ;
+        ; Supplement the state out of the current context and then return.
+        ;
+.supplement_and_return:
+%if ARCH_BITS == 16
+        CPU 8086
+        ; Skip 286 and older.  Also make 101% sure we not in real mode or v8086 mode.
+        cmp     byte [BS3_DATA16_WRT(g_uBs3CpuDetected)], BS3CPU_80386
+        jb      .return                 ; Just skip if 286 or older.
+        test    byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_CODE_V86
+        jnz     .return
+        cmp     byte [BS3_DATA16_WRT(g_bBs3CurrentMode)], BS3_MODE_RM
+        jne     .return                 ; paranoia
+        CPU 386
+%endif
+
+        ; Load the context pointer into a suitable register.
+%if ARCH_BITS == 64
+ %define pRegCtx rcx
+        mov     rcx, [xBP - xCB]
+%elif ARCH_BITS == 32
+ %define pRegCtx ecx
+        mov     ecx, [xBP + xCB + cbCurRetAddr]
+%else
+ %define pRegCtx es:bx
+        push    es
+        push    bx
+        les     bx, [xBP + xCB + cbCurRetAddr]
+%endif
+%if ARCH_BITS == 64
+        ; If we're in 64-bit mode we can capture and restore the high bits.
+        test    byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64
+        jz      .supplemented_64bit_registers
+        mov     [pRegCtx + BS3REGCTX.r8], r8
+        mov     [pRegCtx + BS3REGCTX.r9], r9
+        mov     [pRegCtx + BS3REGCTX.r10], r10
+        mov     [pRegCtx + BS3REGCTX.r11], r11
+        mov     [pRegCtx + BS3REGCTX.r12], r12
+        mov     [pRegCtx + BS3REGCTX.r13], r13
+        mov     [pRegCtx + BS3REGCTX.r14], r14
+        mov     [pRegCtx + BS3REGCTX.r15], r15
+        shr     rax, 32
+        mov     [pRegCtx + BS3REGCTX.rax + 4], eax
+        mov     rax, rbx
+        shr     rax, 32
+        mov     [pRegCtx + BS3REGCTX.rbx + 4], eax
+        mov     rax, rcx
+        shr     rax, 32
+        mov     [pRegCtx + BS3REGCTX.rcx + 4], eax
+        mov     rax, rdx
+        shr     rax, 32
+        mov     [pRegCtx + BS3REGCTX.rdx + 4], eax
+        mov     rax, rsp
+        shr     rax, 32
+        mov     [pRegCtx + BS3REGCTX.rsp + 4], eax
+        mov     rax, rbp
+        shr     rax, 32
+        mov     [pRegCtx + BS3REGCTX.rbp + 4], eax
+        mov     rax, rsi
+        shr     rax, 32
+        mov     [pRegCtx + BS3REGCTX.rsi + 4], eax
+        mov     rax, rdi
+        shr     rax, 32
+        mov     [pRegCtx + BS3REGCTX.rdi + 4], eax
+        ;and     byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_AMD64 - enable later.
+.supplemented_64bit_registers:
+%endif
+        ; The rest requires ring-0 (at least during restore).
+        mov     ax, ss
+        test    ax, 3
+        jnz     .done_supplementing
+
+        ; Do control registers.
+        test    byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR4
+        jz      .supplemented_control_registers
+        mov     sAX, cr0
+        mov     [pRegCtx + BS3REGCTX.cr0], sAX
+        mov     sAX, cr2
+        mov     [pRegCtx + BS3REGCTX.cr2], sAX
+        mov     sAX, cr3
+        mov     [pRegCtx + BS3REGCTX.cr3], sAX
+        and     byte [pRegCtx + BS3REGCTX.fbFlags], ~(BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR0_IS_MSW)
+
+%if ARCH_BITS != 64
+        test    byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8)
+        jz      .supplemented_control_registers
+%endif
+        mov     sAX, cr4
+        mov     [pRegCtx + BS3REGCTX.cr4], sAX
+        and     byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_CR4
+.supplemented_control_registers:
+
+        ; Supply tr and ldtr if necessary
+        test    byte [pRegCtx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_TR_LDTR
+        jz      .done_supplementing
+        str     [pRegCtx + BS3REGCTX.tr]
+        sldt    [pRegCtx + BS3REGCTX.ldtr]
+        and     byte [pRegCtx + BS3REGCTX.fbFlags], ~BS3REG_CTX_F_NO_TR_LDTR
+
+.done_supplementing:
+TONLY16 pop     bx
+TONLY16 pop     es
+        jmp     .return
+%undef pRegCtx
 BS3_PROC_END_CMN   Bs3RegCtxSaveEx
 
-
