summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm')
-rw-r--r--src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm546
1 files changed, 546 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm
new file mode 100644
index 00000000..3f25a5f2
--- /dev/null
+++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm
@@ -0,0 +1,546 @@
+; $Id: bs3-c32-Trap32Generic.asm $
+;; @file
+; BS3Kit - Trap, 32-bit assembly handlers.
+;
+
+;
+; Copyright (C) 2007-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+;*********************************************************************************************************************************
+;* Header Files *
+;*********************************************************************************************************************************
+%include "bs3kit-template-header.mac"
+
+%ifndef TMPL_32BIT
+ %error "32-bit only template"
+%endif
+
+
+;*********************************************************************************************************************************
+;* External Symbols *
+;*********************************************************************************************************************************
+BS3_EXTERN_DATA16 g_bBs3CurrentMode
+BS3_EXTERN_DATA16 g_uBs3CpuDetected
+BS3_EXTERN_DATA16 g_apfnBs3TrapHandlers_c32
+BS3_EXTERN_SYSTEM16 Bs3Gdt
+TMPL_BEGIN_TEXT
+BS3_EXTERN_CMN Bs3TrapDefaultHandler
+BS3_EXTERN_CMN Bs3RegCtxRestore
+TMPL_BEGIN_TEXT
+
+
+;*********************************************************************************************************************************
+;* Global Variables *
+;*********************************************************************************************************************************
+BS3_BEGIN_DATA16
+;; Easy to access flat address of Bs3Trap32GenericEntries.
+BS3_GLOBAL_DATA g_Bs3Trap32GenericEntriesFlatAddr, 4
+ dd Bs3Trap32GenericEntries wrt FLAT
+;; Easy to access flat address of Bs3Trap32DoubleFaultHandler.
+BS3_GLOBAL_DATA g_Bs3Trap32DoubleFaultHandlerFlatAddr, 4
+ dd Bs3Trap32DoubleFaultHandler wrt FLAT
+
+
+TMPL_BEGIN_TEXT
+
+;;
+; Generic entry points for IDT handlers, 8 byte spacing.
+;
+BS3_PROC_BEGIN Bs3Trap32GenericEntries
+%macro Bs3Trap32GenericEntryNoErr 1
+ push byte 0 ; 2 byte: fake error code.
+ db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value.
+ jmp near %1 ; 5 byte
+ ALIGNCODE(2)
+%assign i i+1
+%endmacro
+
+%macro Bs3Trap32GenericEntryErrCd 1
+ db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value.
+ jmp near %1 ; 5 byte
+ db 0cch, 0cch ; 2 byte: padding.
+ ALIGNCODE(2)
+%assign i i+1
+%endmacro
+
+%assign i 0 ; start counter.
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 0
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 2
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 3
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 4
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 5
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 6
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 7
+ Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; 8
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 9
+ Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; a
+ Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; b
+ Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; c
+ Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; d
+ Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; e
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; f (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 10
+ Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; 11
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 12
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 13
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 14
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 15 (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 16 (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 17 (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 18 (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 19 (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1a (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1b (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1c (reserved)
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1d (reserved)
+ Bs3Trap32GenericEntryErrCd bs3Trap32GenericTrapOrInt ; 1e
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt ; 1f (reserved)
+%rep 224
+ Bs3Trap32GenericEntryNoErr bs3Trap32GenericTrapOrInt
+%endrep
+BS3_PROC_END Bs3Trap32GenericEntries
+AssertCompile(Bs3Trap32GenericEntries_EndProc - Bs3Trap32GenericEntries == 10*256)
+
+
+;;
+; Trap or interrupt with error code, faked if necessary.
+;
+BS3_PROC_BEGIN bs3Trap32GenericTrapOrInt
+ push ebp ; 0
+ mov ebp, esp
+ pushfd ; -04h
+ cld
+ push eax ; -08h
+ push edi ; -0ch
+ lea eax, [esp + (4+1+1)*4] ; 4 pushes above, 1 exception number push, 1 error code.
+ push eax ; -10h = handler ESP
+ add eax, 3*4 ; 3 dword iret frame
+ push eax ; -14h = caller ESP if same CPL
+ push ss ; -18h
+ push ds ; -1ch
+
+ ; Make sure we've got a flat DS. It makes everything so much simpler.
+ mov ax, ss
+ and al, 3
+ AssertCompile(BS3_SEL_RING_SHIFT == 8)
+ mov ah, al
+ add ax, BS3_SEL_R0_DS32
+ mov ds, ax
+
+ ;
+ ; We may be comming from 16-bit code with a 16-bit SS. Thunk it as
+ ; the C code may assume flat SS and we'll mess up by using EBP/ESP/EDI
+ ; instead of BP/SP/SS:DI. ASSUMES standard GDT selector.
+ ;
+ mov ax, ss
+ lar eax, ax
+ test eax, X86LAR_F_D
+ jz .stack_thunk
+ mov ax, ss
+ and al, 3
+ AssertCompile(BS3_SEL_RING_SHIFT == 8)
+ mov ah, al
+ add ax, BS3_SEL_R0_SS32
+ mov ss, ax
+ jmp .stack_flat
+.stack_thunk:
+ mov di, ss
+ and edi, X86_SEL_MASK_OFF_RPL
+ mov al, [X86DESCGENERIC_BIT_OFF_BASE_HIGH1 / 8 + edi + Bs3Gdt wrt FLAT]
+ mov ah, [X86DESCGENERIC_BIT_OFF_BASE_HIGH2 / 8 + edi + Bs3Gdt wrt FLAT]
+ shl eax, 16
+ mov ax, [X86DESCGENERIC_BIT_OFF_BASE_LOW / 8 + edi + Bs3Gdt wrt FLAT] ; eax = SS.base
+ movzx ebp, bp ; SS:BP -> flat EBP.
+ add ebp, eax
+ movzx edi, sp ; SS:SP -> flat ESP in EAX.
+ add edi, eax
+ mov ax, ss
+ and al, 3
+ AssertCompile(BS3_SEL_RING_SHIFT == 8)
+ mov ah, al
+ add ax, BS3_SEL_R0_SS32
+ mov ss, ax
+ mov esp, edi
+ sub dword [ebp - 10h], (4+1)*4 ; Recalc handler ESP in case of wraparound.
+ add word [ebp - 10h], (4+1)*4
+ sub dword [ebp - 10h], (4+1+3)*4 ; Recalc caller ESP in case of wraparound.
+ add word [ebp - 10h], (4+1+3)*4
+.stack_flat:
+
+ ; Reserve space for the register and trap frame.
+ mov eax, (BS3TRAPFRAME_size + 7) / 8
+AssertCompileSizeAlignment(BS3TRAPFRAME, 8)
+.more_zeroed_space:
+ push dword 0
+ push dword 0
+ dec eax
+ jnz .more_zeroed_space
+ mov edi, esp ; edi points to trapframe structure.
+
+ ; Copy stuff from the stack over.
+ mov eax, [ebp + 8]
+;; @todo Do voodoo checks for 'int xx' or misguided hardware interrupts.
+ mov [edi + BS3TRAPFRAME.uErrCd], eax
+ mov al, [ebp + 4]
+ mov [edi + BS3TRAPFRAME.bXcpt], al
+ mov eax, [ebp]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], eax
+ mov eax, [ebp - 04h]
+ mov [edi + BS3TRAPFRAME.fHandlerRfl], eax
+ mov eax, [ebp - 08h]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], eax
+ mov eax, [ebp - 0ch]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], eax
+ mov eax, [ebp - 10h]
+ mov [edi + BS3TRAPFRAME.uHandlerRsp], eax
+ mov eax, [ebp - 14h]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], eax
+ mov ax, [ebp - 18h]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], ax
+ mov [edi + BS3TRAPFRAME.uHandlerSs], ax
+ mov ax, [ebp - 1ch]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], ax
+
+ lea ebp, [ebp + 8] ; iret - 4 (i.e. ebp frame chain location)
+ jmp bs3Trap32GenericCommon
+BS3_PROC_END bs3Trap32GenericTrapErrCode
+
+
+;;
+; Common context saving code and dispatching.
+;
+; @param edi Pointer to the trap frame. The following members have been
+; filled in by the previous code:
+; - bXcpt
+; - uErrCd
+; - fHandlerRfl
+; - uHandlerRsp
+; - uHandlerSs
+; - Ctx.rax
+; - Ctx.rbp
+; - Ctx.rdi
+; - Ctx.rsp - assuming same CPL
+; - Ctx.ds
+; - Ctx.ss
+;
+; @param ebp Pointer to the dword before the iret frame, i.e. where ebp
+; would be saved if this was a normal call.
+;
+; @remarks This is a separate function for hysterical raisins.
+;
+BS3_PROC_BEGIN bs3Trap32GenericCommon
+ ;
+ ; Fake EBP frame.
+ ;
+ mov eax, [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp]
+ mov [ebp], eax
+
+ ;
+ ; Save the remaining GPRs and segment registers.
+ ;
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], ebx
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.es], es
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs
+
+ ;
+ ; Load 32-bit data selector for the DPL we're executing at into DS and ES.
+ ; Save the handler CS value first.
+ ;
+ mov ax, cs
+ mov [edi + BS3TRAPFRAME.uHandlerCs], ax
+ and al, 3
+ AssertCompile(BS3_SEL_RING_SHIFT == 8)
+ mov ah, al
+ add ax, BS3_SEL_R0_DS32
+ mov ds, ax
+ mov es, ax
+
+ ;
+ ; Copy and update the mode now that we've got a flat DS.
+ ;
+ mov al, [BS3_DATA16_WRT(g_bBs3CurrentMode)]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], al
+ and al, ~BS3_MODE_CODE_MASK
+ or al, BS3_MODE_CODE_32
+ mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], al
+
+ ;
+ ; Copy iret info.
+ ;
+ mov ecx, [ebp + 4]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], ecx
+ mov ecx, [ebp + 12]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], ecx
+ mov cx, [ebp + 8]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx
+ test dword [ebp + 12], X86_EFL_VM
+ jnz .iret_frame_v8086
+ mov ax, ss
+ and al, 3
+ and cl, 3
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl
+ cmp cl, al
+ je .iret_frame_same_cpl
+
+.iret_frame_different_cpl:
+ mov ecx, [ebp + 16]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx
+ mov cx, [ebp + 20]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx
+ mov byte [edi + BS3TRAPFRAME.cbIretFrame], 5*4
+ jmp .iret_frame_done
+
+.iret_frame_v8086:
+ mov byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], 3
+ or byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], BS3_MODE_CODE_V86 ; paranoia ^ 2
+ mov ecx, [ebp + 16]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx
+ mov cx, [ebp + 20]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx
+ mov cx, [ebp + 24]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx
+ mov cx, [ebp + 28]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx
+ mov cx, [ebp + 32]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], cx
+ mov cx, [ebp + 36]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], cx
+ mov byte [edi + BS3TRAPFRAME.cbIretFrame], 9*4
+ jmp .iret_frame_done
+
+.iret_frame_same_cpl: ; (caller already set SS:RSP and uHandlerRsp for same CPL iret frames)
+ mov byte [edi + BS3TRAPFRAME.cbIretFrame], 3*4
+
+.iret_frame_done:
+ ;
+ ; Control registers.
+ ;
+ str ax
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.tr], ax
+ sldt ax
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr], ax
+
+ mov ax, ss
+ test al, 3
+ jnz .skip_crX_because_cpl_not_0
+
+ mov eax, cr3
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], eax
+.save_cr0_cr2_cr4: ; The double fault code joins us here.
+ mov eax, cr0
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], eax
+ mov eax, cr2
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], eax
+
+ test byte [1 + BS3_DATA16_WRT(g_uBs3CpuDetected)], (BS3CPU_F_CPUID >> 8) ; CR4 first appeared in later 486es.
+ jz .skip_cr4_because_not_there
+ mov eax, cr4
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], eax
+ jmp .set_flags
+
+.skip_cr4_because_not_there:
+ mov byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4
+ jmp .set_flags
+
+.skip_crX_because_cpl_not_0:
+ or byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], \
+ BS3REG_CTX_F_NO_CR0_IS_MSW | BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4
+ smsw [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0]
+.set_flags:
+ or byte [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64
+
+ ;
+ ; Dispatch it to C code.
+ ;
+.dispatch_to_handler:
+ movzx ebx, byte [edi + BS3TRAPFRAME.bXcpt]
+ mov eax, [ebx * 4 + BS3_DATA16_WRT(_g_apfnBs3TrapHandlers_c32)]
+ or eax, eax
+ jnz .call_handler
+ mov eax, Bs3TrapDefaultHandler
+.call_handler:
+ push edi
+ call eax
+
+ ;
+ ; Resume execution using trap frame.
+ ;
+ push 0
+ add edi, BS3TRAPFRAME.Ctx
+ push edi
+ call Bs3RegCtxRestore
+.panic:
+ hlt
+ jmp .panic
+BS3_PROC_END bs3Trap32GenericCommon
+
+
+;;
+; Helper.
+;
+; @retruns Flat address in eax.
+; @param ax
+; @uses eax
+;
+bs3Trap32TssInAxToFlatInEax:
+ ; Get the GDT base address and find the descriptor address (EAX)
+ sub esp, 8+2
+ sgdt [esp]
+ and eax, 0fff8h
+ add eax, [esp + 2] ; GDT base address.
+ add esp, 8+2
+
+ ; Get the flat TSS address from the descriptor.
+ mov al, [eax + (X86DESCGENERIC_BIT_OFF_BASE_HIGH1 / 8)]
+ mov ah, [eax + (X86DESCGENERIC_BIT_OFF_BASE_HIGH2 / 8)]
+ shl eax, 16
+ mov ax, [eax + (X86DESCGENERIC_BIT_OFF_BASE_LOW / 8)]
+ ret
+
+;;
+; Double fault handler.
+;
+; We don't have to load any selectors or clear anything in EFLAGS because the
+; TSS specified sane values which got loaded during the task switch.
+;
+BS3_PROC_BEGIN Bs3Trap32DoubleFaultHandler
+ push 0 ; We'll copy the rip from the other TSS here later to create a more sensible call chain.
+ push ebp
+ mov ebp, esp
+
+ pushfd ; Get handler flags.
+ pop ecx
+
+ xor edx, edx ; NULL register.
+
+ ;
+ ; Allocate a zero filled trap frame.
+ ;
+ mov eax, (BS3TRAPFRAME_size + 7) / 8
+AssertCompileSizeAlignment(BS3TRAPFRAME, 8)
+.more_zeroed_space:
+ push edx
+ push edx
+ dec eax
+ jz .more_zeroed_space
+ mov edi, esp
+
+ ;
+ ; Fill in the non-context trap frame bits.
+ ;
+ mov [edi + BS3TRAPFRAME.fHandlerRfl], ecx
+ mov word [edi + BS3TRAPFRAME.bXcpt], X86_XCPT_DF
+ mov [edi + BS3TRAPFRAME.uHandlerCs], cs
+ mov [edi + BS3TRAPFRAME.uHandlerSs], ss
+ lea ecx, [ebp + 3*4] ; two pushes, one error code.
+ mov [edi + BS3TRAPFRAME.uHandlerRsp], ecx
+ mov ecx, [ebp + 8]
+ mov [edi + BS3TRAPFRAME.uErrCd], ecx
+
+ ;
+ ; Copy the register state from the previous task segment.
+ ;
+
+ ; Find our TSS.
+ str ax
+ call bs3Trap32TssInAxToFlatInEax
+
+ ; Find the previous TSS.
+ mov ax, [eax + X86TSS32.selPrev]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.tr], ax
+ call bs3Trap32TssInAxToFlatInEax
+
+ ; Do the copying.
+ mov ecx, [eax + X86TSS32.eax]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], ecx
+ mov ecx, [eax + X86TSS32.ecx]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx
+ mov ecx, [eax + X86TSS32.edx]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], ecx
+ mov ecx, [eax + X86TSS32.ebx]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], ecx
+ mov ecx, [eax + X86TSS32.esp]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx
+ mov ecx, [eax + X86TSS32.ebp]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], ecx
+ mov [ebp], ecx ; For better call stacks.
+ mov ecx, [eax + X86TSS32.esi]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], ecx
+ mov ecx, [eax + X86TSS32.edi]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], ecx
+ mov ecx, [eax + X86TSS32.esi]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], ecx
+ mov ecx, [eax + X86TSS32.eflags]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], ecx
+ mov ecx, [eax + X86TSS32.eip]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], ecx
+ mov [ebp + 4], ecx ; For better call stacks.
+ mov cx, [eax + X86TSS32.cs]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx
+ mov cx, [eax + X86TSS32.ds]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx
+ mov cx, [eax + X86TSS32.es]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx
+ mov cx, [eax + X86TSS32.fs]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], cx
+ mov cx, [eax + X86TSS32.gs]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], cx
+ mov cx, [eax + X86TSS32.ss]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx
+ mov cx, [eax + X86TSS32.selLdt] ; Note! This isn't necessarily the ldtr at the time of the fault.
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr], cx
+ mov cx, [eax + X86TSS32.cr3] ; Note! This isn't necessarily the cr3 at the time of the fault.
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], ecx
+
+ ;
+ ; Set CPL; copy and update mode.
+ ;
+ mov cl, [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.ss]
+ and cl, 3
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl
+
+ mov cl, [BS3_DATA16_WRT(g_bBs3CurrentMode)]
+ mov [edi + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], cl
+ and cl, ~BS3_MODE_CODE_MASK
+ or cl, BS3_MODE_CODE_32
+ mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], cl
+
+ ;
+ ; Join code paths with the generic handler code.
+ ;
+ jmp bs3Trap32GenericCommon.save_cr0_cr2_cr4
+BS3_PROC_END Bs3Trap32DoubleFaultHandler
+