diff options
Diffstat (limited to '')
-rw-r--r-- | src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c32-Trap32Generic.asm | 546 |
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 + |