Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-bootsector.asm
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-bootsector.asm	(revision 59951)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-bootsector.asm	(revision 59952)
@@ -146,5 +146,5 @@
         mov     eax, cr4
         mov     [BS3_ADDR_REG_SAVE + BS3REGS.cr4], eax
-        mov     byte [BS3_ADDR_REG_SAVE + BS3REGS.cBits], 16
+        mov     byte [BS3_ADDR_REG_SAVE + BS3REGS.bMode], BS3_MODE_RM
         xor     eax, eax
         mov     [cs:BS3_ADDR_REG_SAVE + BS3REGS.cs], ax
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSystemCallHandler.asm
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSystemCallHandler.asm	(revision 59951)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-mode-TrapSystemCallHandler.asm	(revision 59952)
@@ -28,9 +28,7 @@
 
 
-%ifdef TMPL_CMN_R86
-; Make sure BS3DATA16 is defined so we can refere to it below.
-BS3_BEGIN_DATA16
-BS3_BEGIN_TEXT16
-%endif
+BS3_EXTERN_DATA16 g_bBs3CurrentMode
+BS3_EXTERN_DATA16 g_uBs3CpuDetected
+TMPL_BEGIN_TEXT
 
 
@@ -49,4 +47,5 @@
         mov     xBP, xSP
 %ifndef TMPL_64BIT
+ %define VAR_CALLER_DS      [xBP - xCB]
         push    ds
  %ifdef TMPL_CMN_R86
@@ -56,4 +55,18 @@
  %endif
         pop     ds
+ %define VAR_CALLER_BP      [xBP]
+ %define VAR_CALLER_DS      [xBP -       - xCB]
+ %define VAR_CALLER_BX      [xBP - xCB*1 - xCB]
+ %define VAR_CALLER_AX      [xBP - xCB*2 - xCB]
+ %define VAR_CALLER_CX      [xBP - xCB*3 - xCB]
+ %define VAR_CALLER_DX      [xBP - xCB*4 - xCB]
+ %define VAR_CALLER_MODE    [xBP - xCB*5 - xCB]
+%else
+ %define VAR_CALLER_BP      [xBP]
+ %define VAR_CALLER_BX      [xBP - xCB*1]
+ %define VAR_CALLER_AX      [xBP - xCB*2]
+ %define VAR_CALLER_CX      [xBP - xCB*3]
+ %define VAR_CALLER_DX      [xBP - xCB*4]
+ %define VAR_CALLER_MODE    [xBP - xCB*5]
 %endif
         push    xBX
@@ -61,4 +74,9 @@
         push    xCX
         push    xDX
+
+        ; VAR_CALLER_MODE: Save the current mode (important for v8086 with 16-bit kernel).
+        xor     xBX, xBX
+        mov     bl, [g_bBs3CurrentMode]
+        push    xBX
 
         ;
@@ -139,5 +157,6 @@
 
         ;
-        ; Print CX chars from string pointed to by DS:[E]DI
+        ; Print CX chars from string pointed to by DX:SI in 16-bit and v8086 mode,
+        ; and ESI/RSI in 64-bit and 32-bit mode (flat).
         ;
         ; We use the vga bios teletype interrupt to do the writing, so we must
@@ -146,4 +165,13 @@
         ;
 .print_str:
+        push    xSI                     ; we setup ds:xSI to point to the thing.
+%if TMPL_BITS != 64
+        mov     bl, byte VAR_CALLER_MODE
+        and     bl, BS3_MODE_CODE_MASK
+        cmp     bl, BS3_MODE_CODE_V86
+        jne     .print_str_not_v8086
+        ;; @todo this gets complicated _fast_. Later.
+.print_str_not_v8086:
+%endif
         int3
         jmp     .return
@@ -154,8 +182,12 @@
         ;
 .to_ring0:
-        int3
-
-        jmp     .return
-
+        sub     xSP, BS3REGS_size
+        mov     xBX, xSP                ; xBP = BS3REGS pointer.
+        call    .save_context
+
+
+        jmp     .return
+
+;; @todo the remainder could be implemented in client code using SwitchToRing0
 .to_ring1:
         int3
@@ -170,8 +202,15 @@
         jmp     .return
 
+
         ;
         ; Return.
         ;
 .return:
+        pop     xBX                     ; saved mode
+%if TMPL_BITS == 16
+        and     bl, BS3_MODE_CODE_MASK
+        cmp     bl, BS3_MODE_CODE_V86
+        je      .return_to_v8086_from_16bit_krnl
+%endif
         pop     xDX
         pop     xCX
@@ -187,4 +226,186 @@
         iret
 %endif
+
+%if TMPL_BITS == 16
+.return_to_v8086_from_16bit_krnl:
+        int3
+        jmp     .return_to_v8086_from_16bit_krnl
+%endif
+
+
+
+        ;
+        ; Internal function. ss:xBX = Pointer to register frame (BS3REGS).
+        ; @uses xAX
+        ;
+.save_context:
+%if TMPL_BITS == 16
+        cmp     byte [g_uBs3CpuDetected], BS3CPU_80386
+        jae     .save_context_full
+
+        ;
+        ; 80286 or earlier.
+        ;
+
+        ; Clear the state area first.
+        push    di
+        xor     di, di
+.save_context_16_clear_loop:
+        mov     word [ss:bx + di], 0
+        mov     word [ss:bx + di + 2], 0
+        mov     word [ss:bx + di + 4], 0
+        mov     word [ss:bx + di + 6], 0
+        add     di, 8
+        cmp     di, BS3REGS_size
+        jb      .save_context_16_clear_loop
+        pop     di
+
+        ; Do the 8086/80186/80286 state saving.
+        mov     ax, VAR_CALLER_AX
+        mov     [ss:bx + BS3REGS.rax], ax
+        mov     cx, VAR_CALLER_CX
+        mov     [ss:bx + BS3REGS.rcx], ax
+        mov     ax, VAR_CALLER_DX
+        mov     [ss:bx + BS3REGS.rdx], ax
+        mov     ax, VAR_CALLER_BX
+        mov     [ss:bx + BS3REGS.rbx], ax
+        mov     [ss:bx + BS3REGS.rsi], si
+        mov     [ss:bx + BS3REGS.rdi], di
+        mov     ax, VAR_CALLER_BP
+        mov     [ss:bx + BS3REGS.rbp], ax
+        mov     [ss:bx + BS3REGS.es], es
+        mov     ax, [xBP + xCB]
+        mov     [ss:bx + BS3REGS.rip], ax
+        mov     ax, [xBP + xCB*2]
+        mov     [ss:bx + BS3REGS.cs], ax
+        and     al, X86_SEL_RPL
+        mov     [ss:bx + BS3REGS.bCpl], al
+        cmp     al, 0
+        je      .save_context_16_same
+        mov     ax, [xBP + xCB*4]
+        mov     [ss:bx + BS3REGS.rsp], ax
+        mov     ax, [xBP + xCB*5]
+        mov     [ss:bx + BS3REGS.ss], ax
+        jmp     .save_context_16_done_stack
+.save_context_16_same:
+        mov     ax, bp
+        add     ax, xCB * (1 + 3)
+        mov     [ss:bx + BS3REGS.rsp], ax
+        mov     ax, ss
+        mov     [ss:bx + BS3REGS.ss], ax
+.save_context_16_done_stack:
+        mov     ax, [xBP + xCB*3]
+        mov     [ss:bx + BS3REGS.rflags], ax
+        mov     al, VAR_CALLER_MODE
+        mov     [ss:bx + BS3REGS.bMode], al
+        cmp     byte [g_uBs3CpuDetected], BS3CPU_80286
+        jne     .save_context_16_return
+        smsw    [ss:bx + BS3REGS.cr0]
+        str     [ss:bx + BS3REGS.tr]
+        sldt    [ss:bx + BS3REGS.ldtr]
+.save_context_16_return:
+        ret
+%endif ; TMPL_BITS == 16
+
+        ;
+        ; 80386 or later.
+        ;
+.save_context_full:
+
+        ; Clear the state area first unless 64-bit mode.
+%if TMPL_BITS != 64
+        push    xDI
+        xor     xDI, xDI
+.save_context_32_clear_loop:
+        mov     dword [ss:xBX + xDI], 0
+        mov     dword [ss:xBX + xDI + 4], 0
+        add     xDI, 8
+        cmp     xDI, BS3REGS_size
+        jb      .save_context_32_clear_loop
+        pop     xDI
+%endif
+
+        ; Do the 386+ state saving.
+%if TMPL_BITS == 16                     ; save the high word of registered pushed on the stack.
+        mov     [ss:bx + BS3REGS.rax], eax
+        mov     [ss:bx + BS3REGS.rcx], ecx
+        mov     [ss:bx + BS3REGS.rdx], edx
+        mov     [ss:bx + BS3REGS.rbx], ebx
+        mov     [ss:bx + BS3REGS.rbp], ebp
+        mov     [ss:bx + BS3REGS.rsp], esp
+%endif
+        mov     xAX, VAR_CALLER_AX
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rax], xAX
+        mov     xCX, VAR_CALLER_CX
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rcx], xCX
+        mov     xAX, VAR_CALLER_DX
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rdx], xAX
+        mov     xAX, VAR_CALLER_BX
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rbx], xAX
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rsi], sSI
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rdi], sDI
+        mov     xAX, VAR_CALLER_BP
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rbp], xAX
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.es], es
+        mov     xAX, [xBP + xCB]
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rip], xAX
+        mov     ax, [xBP + xCB*2]
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.cs], ax
+%if TMPL_MODE != BS3_MODE_RM
+        and     al, X86_SEL_RPL
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.bCpl], al
+        cmp     al, 0
+        je      .save_context_full_same
+        mov     xAX, [xBP + xCB*4]
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rsp], xAX
+        mov     ax, [xBP + xCB*5]
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.ss], ax
+        jmp     .save_context_full_done_stack
+%else
+        mov     byte [BS3_NOT_64BIT(ss:) xBX + BS3REGS.bCpl], 0
+%endif
+.save_context_full_same:
+        mov     xAX, xBP
+        add     xAX, xCB * (1 + 3)
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rsp], xAX
+        mov     ax, ss
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.ss], ax
+.save_context_full_done_stack:
+        mov     xAX, [xBP + xCB*3]
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.rflags], xAX
+        mov     al, VAR_CALLER_MODE
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.bMode], al
+%if TMPL_BITS == 64
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.r8], r8
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.r9], r9
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.r10], r10
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.r11], r11
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.r12], r12
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.r13], r13
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.r14], r14
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.r15], r15
+%endif
+        ; Save state according to detected CPU.
+        str     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.tr]
+        sldt    [BS3_NOT_64BIT(ss:) xBX + BS3REGS.ldtr]
+        cmp     byte [g_uBs3CpuDetected], BS3CPU_80286
+        ja      .save_context_full_return
+        smsw    [BS3_NOT_64BIT(ss:) xBX + BS3REGS.cr0]
+        jmp     .save_context_full_return
+
+.save_context_full_386_plus:
+        mov     sAX, cr0
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.cr0], sAX
+        mov     sAX, cr2
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.cr2], sAX
+        mov     sAX, cr3
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.cr3], sAX
+        mov     sAX, cr4
+        mov     [BS3_NOT_64BIT(ss:) xBX + BS3REGS.cr4], sAX
+
+.save_context_full_return:
+        ret
+
+
 BS3_PROC_END_MODE   Bs3TrapSystemCallHandler
 
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.h
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.h	(revision 59951)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.h	(revision 59952)
@@ -1948,6 +1948,7 @@
     uint16_t    tr;
     uint16_t    ldtr;
-    uint8_t     cBits;
-    uint8_t     abPadding[7];
+    uint8_t     bMode;                  /**< BS3_MODE_XXX. */
+    uint8_t     bCpl;                   /**< 0-3, 0 is used for real mode. */
+    uint8_t     abPadding[6];
     BS3REG      cr0;
     BS3REG      cr2;
Index: /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.mac
===================================================================
--- /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.mac	(revision 59951)
+++ /trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.mac	(revision 59952)
@@ -178,4 +178,11 @@
  %endif
 
+ %undef   BS3_NOT_64BIT
+ %if %1 == 64
+  %define BS3_NOT_64BIT(a_Expr)
+ %else
+  %define BS3_NOT_64BIT(a_Expr)     a_Expr
+ %endif
+
  %undef   BS3_IF_16_32_64BIT
  %if %1 == 16
@@ -274,4 +281,11 @@
 %else
  %define BS3_ONLY_64BIT(a_Expr)
+%endif
+
+;; For segment overrides and stuff. Follows BS3_SET_BITS.
+%if ARCH_BITS == 64
+ %define BS3_NOT_64BIT(a_Expr)
+%else
+ %define BS3_NOT_64BIT(a_Expr)     a_Expr
 %endif
 
@@ -1112,35 +1126,38 @@
 ;
 struc BS3REGS
-        .rax    resq 1
-        .rbx    resq 1
-        .rcx    resq 1
-        .rdx    resq 1
-        .rdi    resq 1
-        .rsi    resq 1
-        .rbp    resq 1
-        .rsp    resq 1
-        .rip    resq 1
-        .r8     resq 1
-        .r9     resq 1
-        .r10    resq 1
-        .r11    resq 1
-        .r12    resq 1
-        .r13    resq 1
-        .r14    resq 1
-        .r15    resq 1
-        .rflags resq 1
-        .cs     resw 1
-        .ds     resw 1
-        .es     resw 1
-        .fs     resw 1
-        .gs     resw 1
-        .ss     resw 1
-        .cBits  resb 1
-        .pad    resb 3
-        .cr0    resq 1
-        .cr2    resq 1
-        .cr3    resq 1
-        .cr4    resq 1
-        .cr8    resq 1
+        .rax        resq 1
+        .rcx        resq 1
+        .rdx        resq 1
+        .rbx        resq 1
+        .rsp        resq 1
+        .rbp        resq 1
+        .rsi        resq 1
+        .rdi        resq 1
+        .r8         resq 1
+        .r9         resq 1
+        .r10        resq 1
+        .r11        resq 1
+        .r12        resq 1
+        .r13        resq 1
+        .r14        resq 1
+        .r15        resq 1
+        .rflags     resq 1
+        .rip        resq 1
+        .cs         resw 1
+        .ds         resw 1
+        .es         resw 1
+        .fs         resw 1
+        .gs         resw 1
+        .ss         resw 1
+        .tr         resw 1
+        .ldtr       resw 1
+        .bMode      resb 1
+        .bCpl       resb 1
+        .abPadding  resb 6
+        .cr0        resq 1
+        .cr2        resq 1
+        .cr3        resq 1
+        .cr4        resq 1
+
         ;; @todo Add floating point registers when they are active.
 endstruc
