diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm')
-rw-r--r-- | src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm | 720 |
1 files changed, 720 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm new file mode 100644 index 00000000..3db838a2 --- /dev/null +++ b/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-c16-Trap16Generic.asm @@ -0,0 +1,720 @@ +; $Id: bs3-c16-Trap16Generic.asm $ +;; @file +; BS3Kit - Trap, 16-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_16BIT + %error "16-bit only template" +%endif + + +;********************************************************************************************************************************* +;* External Symbols * +;********************************************************************************************************************************* +BS3_EXTERN_DATA16 g_bBs3CurrentMode +BS3_EXTERN_DATA16 g_uBs3TrapEipHint +BS3_EXTERN_DATA16 g_uBs3CpuDetected +BS3_EXTERN_DATA16 g_apfnBs3TrapHandlers_c16 +BS3_EXTERN_SYSTEM16 Bs3Gdt +TMPL_BEGIN_TEXT +BS3_EXTERN_CMN Bs3TrapDefaultHandler +BS3_EXTERN_CMN Bs3RegCtxRestore +TMPL_BEGIN_TEXT + + +;; +; Generic entry points for IDT handlers, 8 byte spacing. +; +BS3_PROC_BEGIN _Bs3Trap16GenericEntries +BS3_PROC_BEGIN Bs3Trap16GenericEntries +%macro Bs3Trap16GenericEntryNoErr 1 + push byte 0 ; 2 byte: fake error code + db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value. + jmp %1 ; 3 byte + ALIGNCODE(8) +%assign i i+1 +%endmacro + +%macro Bs3Trap16GenericEntryErrCd 1 + db 06ah, i ; 2 byte: push imm8 - note that this is a signextended value. + jmp %1 ; 3 byte + ALIGNCODE(8) +%assign i i+1 +%endmacro + +%assign i 0 ; start counter. + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 0 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 2 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 3 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 4 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 5 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 6 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 7 + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 8 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 9 + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; a + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; b + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; c + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; d + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; e + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; f (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 10 + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 11 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 12 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 13 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 14 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 15 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 16 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 17 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 18 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 19 (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1a (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1b (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1c (reserved) + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1d (reserved) + Bs3Trap16GenericEntryErrCd bs3Trap16GenericTrapOrInt ; 1e + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt ; 1f (reserved) +%rep 224 + Bs3Trap16GenericEntryNoErr bs3Trap16GenericTrapOrInt +%endrep +BS3_PROC_END Bs3Trap16GenericEntries +AssertCompile(Bs3Trap16GenericEntries_EndProc - Bs3Trap16GenericEntries == 8*256) + + +;; +; Trap or interrupt with error code, faked if necessary. +; +; Note! This code is going to "misbehave" if the high word of ESP is not cleared. +; +BS3_PROC_BEGIN _bs3Trap16GenericTrapOrInt +BS3_PROC_BEGIN bs3Trap16GenericTrapOrInt +CPU 386 + jmp near bs3Trap16GenericTrapErrCode80286 ; Bs3Trap16Init adjusts this on 80386+ + push ebp + movzx ebp, sp + push ebx ; BP - 04h + pushfd ; BP - 08h + cld + push edx ; BP - 0ch + push ss ; BP - 0eh + push esp ; BP - 12h + + ; + ; We may be comming from 32-bit code where SS is flat and ESP has a non- + ; zero high word. We need to thunk it for C code to work correctly with + ; [BP+xx] and [SS:BX+xx] style addressing that leaves out the high word. + ; + ; Note! Require ring-0 handler for non-standard stacks (SS.DPL must equal CPL). + ; + mov bx, ss + lar ebx, bx + test ebx, X86LAR_F_D + jz .stack_fine + test esp, 0ffff0000h + jnz .stack_thunk +.stack_load_r0_ss16: + mov bx, ss + and bl, 3 + AssertCompile(BS3_SEL_RING_SHIFT == 8) + mov bh, bl + add bx, BS3_SEL_R0_SS16 + jmp .stack_load_bx_into_ss +.stack_thunk: + mov ebx, esp + shr ebx, 16 + shl ebx, X86_SEL_SHIFT + add ebx, BS3_SEL_TILED_R0 + cmp ebx, BS3_SEL_TILED_R0_LAST + ja .stack_esp_out_of_bounds +.stack_load_bx_into_ss: + mov ss, bx +.stack_fine: + movzx esp, sp + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 7) / 8 +.more_zeroed_space: + push 0 + push 0 + push 0 + push 0 + dec bx + jnz .more_zeroed_space + movzx ebx, sp + + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], eax + mov edx, [bp - 12h] ; This isn't quite right for wrap arounds, but close enough for now + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], edx ; high bits + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], edx ; high bits + mov dx, [bp - 0eh] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], dx + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], dx + mov edx, [bp - 0ch] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx + mov edx, [bp - 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], edx ; high bits + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], edx + mov edx, [bp - 4] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], edx + mov edx, [bp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], edx + + mov dl, [bp + 4] + mov [ss:bx + BS3TRAPFRAME.bXcpt], dl + + mov dx, [bp + 6] +;; @todo Do voodoo checks for 'int xx' or misguided hardware interrupts. + mov [ss:bx + BS3TRAPFRAME.uErrCd], dx + + add bp, 6 ; adjust so it points to the word before the iret frame. + xor dx, dx + jmp bs3Trap16GenericCommon + +.stack_esp_out_of_bounds: +%ifdef BS3_STRICT + int3 +%endif + jmp .stack_esp_out_of_bounds +BS3_PROC_END bs3Trap16GenericTrapErrCode + +;; +; Trap with error code - 80286 code variant. +; +BS3_PROC_BEGIN bs3Trap16GenericTrapErrCode80286 +CPU 286 + push bp + mov bp, sp + push bx + pushf + cld + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 7) / 8 +.more_zeroed_space: + push 0 + push 0 + push 0 + push 0 + dec bx + jnz .more_zeroed_space + mov bx, sp + + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], ax + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], ss + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], dx + mov dx, [bp - 4] + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], dx + mov dx, [bp - 2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], dx + mov dx, [bp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], dx + + mov dl, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.bXcpt], dl + + mov dx, [bp + 4] +;; @todo Do voodoo checks for 'int xx' or misguided hardware interrupts. + mov [ss:bx + BS3TRAPFRAME.uErrCd], dx + + add bp, 4 ; adjust so it points to the word before the iret frame. + mov dl, 1 + jmp bs3Trap16GenericCommon +BS3_PROC_END bs3Trap16GenericTrapErrCode80286 + + +;; +; Common context saving code and dispatching. +; +; @param bx Pointer to the trap frame, zero filled. The following members +; have been filled in by the previous code: +; - bXcpt +; - uErrCd +; - fHandlerRFL +; - Ctx.eax +; - Ctx.edx +; - Ctx.ebx +; - Ctx.ebp +; - Ctx.rflags - high bits only. +; - Ctx.esp - high bits only. +; - Ctx.ss - for same cpl frames +; - All other bytes are zeroed. +; +; @param bp Pointer to the word before the iret frame, i.e. where bp +; would be saved if this was a normal near call. +; @param dx One (1) if 286, zero (0) if 386+. +; +BS3_PROC_BEGIN bs3Trap16GenericCommon +CPU 286 + ; + ; Fake EBP frame. + ; + mov ax, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp] + mov [bp], ax + + ; + ; Save the remaining GPRs and segment registers. + ; + test dx, dx + jnz .save_word_grps +CPU 386 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], edi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs + jmp .save_segment_registers +.save_word_grps: +CPU 286 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], cx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], di + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], si +.save_segment_registers: + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], ds + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], es + mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs + + ; + ; Load 16-bit data selector for the DPL we're executing at into DS and ES. + ; + mov ax, ss + and ax, 3 + mov cx, ax + shl ax, BS3_SEL_RING_SHIFT + or ax, cx + add ax, BS3_SEL_R0_DS16 + 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 [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], al + mov cl, al + and cl, ~BS3_MODE_CODE_MASK + or cl, BS3_MODE_CODE_16 + mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], cl + + ; + ; Copy iret info. + ; + lea cx, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], cx + mov cx, [bp + 2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], cx + mov cx, [bp + 6] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], cx + mov cx, [bp + 4] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx + + test al, BS3_MODE_CODE_V86 + jnz .iret_frame_v8086 + + mov ax, ss + and al, 3 + and cl, 3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl + cmp cl, al + je .iret_frame_same_cpl + +.ret_frame_different_cpl: + mov cx, [bp + 10] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx + mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 5*2 + test dx, dx + jnz .iret_frame_done + jmp .iret_frame_seed_high_eip_word + +.iret_frame_same_cpl: ; (ss and high bits was saved by CPU specific part) + lea cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx + mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 3*2 + test dx, dx + jnz .iret_frame_done + jmp .iret_frame_seed_high_eip_word + +.iret_frame_v8086: +CPU 386 + or dword [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], X86_EFL_VM + mov byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], 3 + or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], BS3_MODE_CODE_V86 ; paranoia ^ 2 +%if 0 ;; @todo testcase: high ESP word from V86 mode, 16-bit TSS. + movzx ecx, word [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], ecx +%else + mov cx, word [bp + 8] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx +%endif + mov cx, [bp + 10] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov cx, [bp + 12] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx + mov cx, [bp + 14] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx + mov cx, [bp + 16] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], cx + mov cx, [bp + 18] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], cx + mov byte [ss:bx + BS3TRAPFRAME.cbIretFrame], 9*2 + jmp .iret_frame_done + + ; + ; For 386 we do special tricks to supply the high word of EIP when + ; arriving here from 32-bit code. (ESP was seeded earlier.) + ; +.iret_frame_seed_high_eip_word: + lar eax, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs] + jnz .iret_frame_done + test eax, X86LAR_F_D + jz .iret_frame_done + mov ax, [g_uBs3TrapEipHint+2] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip + 2], ax + +.iret_frame_done: + ; + ; Control registers. + ; + str [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.tr] + sldt [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr] + test dx, dx + jnz .save_286_control_registers +.save_386_control_registers: +CPU 386 + mov ax, ss + test al, 3 + jnz .skip_crX_because_cpl_not_0 + mov eax, cr0 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], eax + mov eax, cr2 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], eax + mov eax, cr3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], 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 [ss:bx + 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 [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], \ + BS3REG_CTX_F_NO_CR2_CR3 | BS3REG_CTX_F_NO_CR4 | BS3REG_CTX_F_NO_CR0_IS_MSW + +CPU 286 +.save_286_control_registers: + smsw [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0] + +.set_flags: ; The double fault code joins us here. + or byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_AMD64 + + ; + ; Dispatch it to C code. + ; +.dispatch_to_handler: + mov di, bx + mov bl, byte [ss:bx + BS3TRAPFRAME.bXcpt] + mov bh, 0 + shl bx, 1 + mov bx, [bx + BS3_DATA16_WRT(_g_apfnBs3TrapHandlers_c16)] + or bx, bx + jnz .call_handler + mov bx, Bs3TrapDefaultHandler +.call_handler: + push ss + push di + call bx + + ; + ; Resume execution using trap frame. + ; + push 0 + push ss + add di, BS3TRAPFRAME.Ctx + push di + call Bs3RegCtxRestore +.panic: + hlt + jmp .panic +BS3_PROC_END bs3Trap16GenericCommon + + +;; +; Helper. +; +; @retruns Flat address in es:di. +; @param di +; @uses eax +; +bs3Trap16TssInDiToFar1616InEsDi: +CPU 286 + push ax + + ; ASSUME Bs3Gdt is being used. + push BS3_SEL_SYSTEM16 + pop es + and di, 0fff8h + add di, Bs3Gdt wrt BS3SYSTEM16 + + ; Load the TSS base into ax:di (di is low, ax high) + mov al, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_HIGH1 / 8)] + mov ah, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_HIGH2 / 8)] + mov di, [es:di + (X86DESCGENERIC_BIT_OFF_BASE_LOW / 8)] + + ; Convert ax to tiled selector, if not within the tiling area we read + ; random BS3SYSTEM16 bits as that's preferable to #GP'ing. + shl ax, X86_SEL_SHIFT + cmp ax, BS3_SEL_TILED_LAST - BS3_SEL_TILED +%ifdef BS3_STRICT + jbe .tiled + int3 +%endif + ja .return ; don't crash again. +.tiled: + add ax, BS3_SEL_TILED + mov es, ax +.return: + pop ax + 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. +; +; @param dx Zero (0) for indicating 386+ to the common code. +; +BS3_PROC_BEGIN _Bs3Trap16DoubleFaultHandler80386 +BS3_PROC_BEGIN Bs3Trap16DoubleFaultHandler80386 +CPU 386 + push 0 ; We'll copy the rip from the other TSS here later to create a more sensible call chain. + push ebp + mov bp, sp + pushfd ; Handler flags. + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 15) / 16 +.more_zeroed_space: + push dword 0 + push dword 0 + push dword 0 + push dword 0 + dec bx + jz .more_zeroed_space + mov bx, sp + + ; + ; Fill in the high GRP register words before we mess them up. + ; + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], eax + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], ebx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], ecx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], edx + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], esi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], edi + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], ebp + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], esp + + ; + ; FS and GS are not part of the 16-bit TSS because they are 386+ specfic. + ; + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fs], fs + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.gs], gs + + ; + ; Fill in the non-context trap frame bits. + ; + mov ecx, [bp - 4] + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], ecx + mov byte [ss:bx + BS3TRAPFRAME.bXcpt], X86_XCPT_DF + mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss + mov ecx, esp + lea cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], ecx + mov cx, [bp + 6] + mov [ss:bx + BS3TRAPFRAME.uErrCd], cx + + ; + ; Copy 80386+ control registers. + ; + mov ecx, cr0 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0], ecx + mov ecx, cr2 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr2], ecx + mov ecx, cr3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr3], ecx + + 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 ecx, cr4 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr4], ecx + jmp .common + +.skip_cr4_because_not_there: + mov byte [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.fbFlags], BS3REG_CTX_F_NO_CR4 + + ; + ; Copy the register state from the previous task segment. + ; The 80286 code with join us here. + ; +.common: +CPU 286 + ; Find our TSS. + str di + call bs3Trap16TssInDiToFar1616InEsDi + + ; Find the previous TSS. + mov di, [es:di + X86TSS32.selPrev] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.tr], ax + call bs3Trap16TssInDiToFar1616InEsDi + + ; Do the copying. + mov cx, [es:di + X86TSS16.ax] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rax], cx + mov cx, [es:di + X86TSS16.cx] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rcx], cx + mov cx, [es:di + X86TSS16.dx] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdx], cx + mov cx, [es:di + X86TSS16.bx] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbx], cx + mov cx, [es:di + X86TSS16.sp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsp], cx + mov cx, [es:di + X86TSS16.bp] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rbp], cx + mov [bp], cx ; For better call stacks. + mov cx, [es:di + X86TSS16.si] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], cx + mov cx, [es:di + X86TSS16.di] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rdi], cx + mov cx, [es:di + X86TSS16.si] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rsi], cx + mov cx, [es:di + X86TSS16.flags] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rflags], cx + mov cx, [es:di + X86TSS16.ip] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.rip], cx + mov [bp + 2], cx ; For better call stacks. + mov cx, [es:di + X86TSS16.cs] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cs], cx + mov cx, [es:di + X86TSS16.ds] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ds], cx + mov cx, [es:di + X86TSS16.es] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.es], cx + mov cx, [es:di + X86TSS16.ss] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss], cx + mov cx, [es:di + X86TSS16.selLdt] ; Note! This isn't necessarily the ldtr at the time of the fault. + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ldtr], cx + + ; + ; Set CPL; copy and update mode. + ; + mov cl, [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.ss] + and cl, 3 + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bCpl], cl + + mov cl, [BS3_DATA16_WRT(g_bBs3CurrentMode)] + mov [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.bMode], cl + and cl, ~BS3_MODE_CODE_MASK + or cl, BS3_MODE_CODE_16 + mov [BS3_DATA16_WRT(g_bBs3CurrentMode)], cl + + ; + ; Join code paths with the generic handler code. + ; + jmp bs3Trap16GenericCommon.set_flags +BS3_PROC_END Bs3Trap16DoubleFaultHandler + + +;; +; 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. +; +; @param dx One (1) for indicating 386+ to the common code. +; +BS3_PROC_BEGIN _Bs3Trap16DoubleFaultHandler80286 +BS3_PROC_BEGIN Bs3Trap16DoubleFaultHandler80286 +CPU 286 + push 0 ; We'll copy the rip from the other TSS here later to create a more sensible call chain. + push bp + mov bp, sp + pushf ; Handler flags. + + ; Reserve space for the register and trap frame. + mov bx, (BS3TRAPFRAME_size + 7) / 8 +.more_zeroed_space: + push 0 + push 0 + push 0 + push 0 + dec bx + jz .more_zeroed_space + mov bx, sp + + ; + ; Fill in the non-context trap frame bits. + ; + mov cx, [bp - 2] + mov [ss:bx + BS3TRAPFRAME.fHandlerRfl], cx + mov byte [ss:bx + BS3TRAPFRAME.bXcpt], X86_XCPT_DF + mov [ss:bx + BS3TRAPFRAME.uHandlerCs], cs + mov [ss:bx + BS3TRAPFRAME.uHandlerSs], ss + lea cx, [bp + 8] + mov [ss:bx + BS3TRAPFRAME.uHandlerRsp], cx + mov cx, [bp + 6] + mov [ss:bx + BS3TRAPFRAME.uErrCd], cx + + ; + ; Copy 80286 specific control register. + ; + smsw [ss:bx + BS3TRAPFRAME.Ctx + BS3REGCTX.cr0] + + jmp Bs3Trap16DoubleFaultHandler80386.common +BS3_PROC_END Bs3Trap16DoubleFaultHandler80286 + |