1320 lines
44 KiB
NASM
1320 lines
44 KiB
NASM
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;
|
|
;; Microsoft Research Singularity
|
|
;;
|
|
;; Copyright (c) Microsoft Corporation. All rights reserved.
|
|
;;
|
|
;; File: halidt.asm
|
|
;;
|
|
;; Note:
|
|
;;
|
|
|
|
.686p
|
|
.mmx
|
|
.xmm
|
|
.model flat
|
|
.code
|
|
|
|
assume ds:flat
|
|
assume es:flat
|
|
assume ss:flat
|
|
assume fs:nothing
|
|
assume gs:nothing
|
|
|
|
include hal.inc
|
|
|
|
DEBUG_INTERRUPTS EQU 0
|
|
ifdef DEBUG
|
|
SPINLOCK_RELEASE_SANITY_CHECK EQU 1
|
|
else
|
|
SPINLOCK_RELEASE_SANITY_CHECK EQU 0
|
|
endif
|
|
|
|
ifdef PAGING
|
|
public _SysEnter
|
|
endif
|
|
|
|
externdef ?c_exceptionHandler@@3P6IXHPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@ZA:uintPtr
|
|
; static void __fastcall Class.Microsoft.SingularityIoSystem.DispatchException(
|
|
; int interrupt [ECX], ref ThreadContex [EDX]))
|
|
; __fastcall:
|
|
; Arg0 passed in ECX
|
|
; Arg1 passed in EDX
|
|
; Others passed right to left on stack.
|
|
; EBX, ESI, EDI, and EBP are callee saved.
|
|
; EAX receives return value if any.
|
|
|
|
public _EdtEnter0
|
|
public _EdtEnter1
|
|
public _EdtEnterBody
|
|
|
|
externdef ?c_interruptHandler@@3P6IXHPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@ZA:uintPtr
|
|
; static void __fastcall Class.Microsoft.SingularityIoSystem.DispatchInterrupt(
|
|
; int interrupt [ECX], ref ThreadContex [EDX]))
|
|
; __fastcall:
|
|
; Arg0 passed in ECX
|
|
; Arg1 passed in EDX
|
|
; Others passed right to left on stack.
|
|
; EBX, ESI, EDI, and EBP are callee saved.
|
|
; EAX receives return value if any.
|
|
|
|
public _IdtEnter20
|
|
public _IdtEnter21
|
|
public _IdtEnterBody
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;
|
|
;;; The IDT_ENTER building macros insure that each IDT target has
|
|
;;; an offset of form (_IdtEnter0 or _EdtEnter0) + 0x10 * interrupt_number.
|
|
;;;
|
|
IDT_ENTER_IN STRUCT 1
|
|
_esi UINT32 ?
|
|
_num UINT32 ?
|
|
_err UINT32 ?
|
|
_eip UINT32 ?
|
|
_cs0 UINT32 ?
|
|
_efl UINT32 ?
|
|
IDT_ENTER_IN ENDS
|
|
|
|
ifdef PAGING
|
|
IDT_ENTER_IN_LARGE STRUCT 1
|
|
_esi UINT32 ?
|
|
_num UINT32 ?
|
|
_err UINT32 ?
|
|
_eip UINT32 ?
|
|
_cs0 UINT32 ?
|
|
_efl UINT32 ?
|
|
_esp UINT32 ?
|
|
_ss UINT32 ?
|
|
IDT_ENTER_IN_LARGE ENDS
|
|
endif
|
|
|
|
IDT_ENTER_OUT STRUCT 1
|
|
_esi UINT32 ?
|
|
_eip UINT32 ?
|
|
_cs0 UINT32 ?
|
|
_efl UINT32 ?
|
|
IDT_ENTER_OUT ENDS
|
|
|
|
ifdef PAGING
|
|
IDT_ENTER_OUT_LARGE STRUCT 1
|
|
_esi UINT32 ?
|
|
_eip UINT32 ?
|
|
_cs0 UINT32 ?
|
|
_efl UINT32 ?
|
|
_esp UINT32 ?
|
|
_ss UINT32 ?
|
|
IDT_ENTER_OUT_LARGE ENDS
|
|
endif
|
|
|
|
EDT_ENTER_CLEAN MACRO num
|
|
push 0 ; No error
|
|
push num
|
|
jmp _EdtEnterBody
|
|
align 16
|
|
ENDM
|
|
|
|
EDT_ENTER_ERR MACRO num
|
|
push num
|
|
jmp _EdtEnterBody
|
|
align 16
|
|
ENDM
|
|
|
|
IDT_ENTER_CLEAN MACRO num
|
|
push 0 ; No error
|
|
push num
|
|
jmp _IdtEnterBody
|
|
align 16
|
|
ENDM
|
|
|
|
IDT_SAVE_CONTEXT MACRO fxregs, error, dregs
|
|
;; Save the processor's thread context.
|
|
;; Mark that the context contains caller-saved registers as well.
|
|
;; Input:
|
|
;; ESI = address of ThreadContext structure.
|
|
;; ESP = bottom of IDT_ENTER_IN context:
|
|
;; ESP[ 0] = esi
|
|
;; ESP[ 4] = num
|
|
;; ESP[ 8] = err
|
|
;; ESP[12] = eip
|
|
;; ESP[16] = cs
|
|
;; ESP[20] = efl
|
|
|
|
;; XXX - if we came from ring 3 then stack also has SS and ESP
|
|
;; ESP[24] = esp
|
|
;; ESP[28] = ss
|
|
;; This code needs to check cs&3 and if non-zero save ss:esp to thread context
|
|
|
|
;; Output:
|
|
;; ESI = address of ThreadContext structure.
|
|
;; ESP = stack w/o IDT_ENTER_IN context
|
|
;; ECX = num
|
|
;;
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._eax, eax
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ebx, ebx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ecx, ecx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._edx, edx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ebp, ebp
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._edi, edi
|
|
mov eax, cr3
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._cr3, eax
|
|
|
|
mov eax, [esp].IDT_ENTER_IN._esi
|
|
mov ebx, [esp].IDT_ENTER_IN._eip
|
|
mov ecx, [esp].IDT_ENTER_IN._cs0
|
|
mov edx, [esp].IDT_ENTER_IN._efl
|
|
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esi, eax
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._eip, ebx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._cs0, ecx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._efl, edx
|
|
|
|
if dregs
|
|
mov eax, dr0
|
|
mov ebx, dr1
|
|
mov ecx, dr2
|
|
mov edx, dr3
|
|
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr0, eax
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr1, ebx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr2, ecx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr3, edx
|
|
|
|
mov eax, dr6
|
|
mov ebx, dr7
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr6, eax
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr7, ebx
|
|
|
|
xor eax, eax
|
|
mov dr6, eax
|
|
endif
|
|
|
|
mov ecx, [esp].IDT_ENTER_IN._num ; this flows through
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._num, cx
|
|
|
|
if error
|
|
mov ebx, [esp].IDT_ENTER_IN._err
|
|
mov eax, cr2
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._err, ebx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._cr2, eax
|
|
endif
|
|
|
|
if fxregs
|
|
if dregs
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 3
|
|
else
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 1
|
|
endif
|
|
fxsave [esi].Struct_Microsoft_Singularity_X86_ThreadContext._mmx
|
|
fninit
|
|
mov eax, 37eh
|
|
push eax
|
|
fldcw [esp]
|
|
pop eax
|
|
else
|
|
if dregs
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 2
|
|
else
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 0
|
|
endif
|
|
endif
|
|
|
|
ifdef PAGING
|
|
;; Is it a small or large frame?
|
|
mov eax, [esp].IDT_ENTER_IN._cs0
|
|
and eax, 3
|
|
jz s_case_0
|
|
|
|
;; Case ring-3: IDT_ENTER_IN_LARGE
|
|
mov eax, [esp].IDT_ENTER_IN_LARGE._esp
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esp, eax
|
|
add esp, SIZEOF IDT_ENTER_IN_LARGE
|
|
jmp s_case_0_3
|
|
|
|
s_case_0:
|
|
endif
|
|
;; Case ring-0: IDT_ENTER_IN
|
|
add esp, SIZEOF IDT_ENTER_IN
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esp, esp
|
|
|
|
ifdef PAGING
|
|
s_case_0_3:
|
|
endif
|
|
|
|
ENDM
|
|
|
|
IDT_LOAD_CONTEXT MACRO dregs
|
|
;; Create the outgoing stack frame.
|
|
ifdef PAGING
|
|
;; Is it a small or large frame?
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._cs0
|
|
and eax, 3
|
|
jz l_case_0
|
|
|
|
;; Case ring-3: push an IDT_ENTER_OUT_LARGE
|
|
sub esp, SIZEOF IDT_ENTER_OUT_LARGE
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esp
|
|
mov [esp].IDT_ENTER_OUT_LARGE._esp, eax
|
|
mov eax, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtUD - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull + 3
|
|
mov [esp].IDT_ENTER_OUT_LARGE._ss, eax
|
|
mov es, ax
|
|
;; For the moment, share UF and PF:
|
|
mov eax, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPF - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull + 3
|
|
mov fs, ax
|
|
jmp l_cases_0_3
|
|
|
|
l_case_0:
|
|
endif ;; PAGING
|
|
;; Case ring-0: push an IDT_ENTER_OUT
|
|
mov esp, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esp
|
|
sub esp, SIZEOF IDT_ENTER_OUT
|
|
|
|
ifdef PAGING
|
|
l_cases_0_3:
|
|
;; Code common to ring-0 and ring-3
|
|
endif ;; PAGING
|
|
|
|
;; Check if we need to restore the floating-point registers
|
|
test [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 1
|
|
jz skip_fxrstor
|
|
fxrstor [esi].Struct_Microsoft_Singularity_X86_ThreadContext._mmx
|
|
skip_fxrstor:
|
|
|
|
if dregs
|
|
;; Check if we need to restore the debug registers
|
|
test [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 2
|
|
jz skip_drstor
|
|
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr0
|
|
mov ebx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr1
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr2
|
|
mov edx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr3
|
|
|
|
mov dr0, eax
|
|
mov dr1, ebx
|
|
mov dr2, ecx
|
|
mov dr3, edx
|
|
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr6
|
|
mov ebx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr7
|
|
|
|
mov dr6, eax
|
|
mov dr7, ebx
|
|
skip_drstor:
|
|
endif
|
|
|
|
ifdef PAGING
|
|
;; Zero for cr3 in the ThreadContext means "don't care" (no paging)
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._cr3
|
|
cmp eax, 0
|
|
je skip_cr3
|
|
|
|
;; Avoid TLB flushes if possible
|
|
mov ebx, CR3
|
|
cmp eax, ebx
|
|
je skip_cr3
|
|
|
|
mov CR3, eax
|
|
|
|
skip_cr3:
|
|
endif ;; PAGING
|
|
|
|
;; Restore the registers
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esi
|
|
mov ebx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._eip
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._cs0
|
|
mov edx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._efl
|
|
|
|
mov [esp].IDT_ENTER_OUT._esi, eax
|
|
mov [esp].IDT_ENTER_OUT._eip, ebx
|
|
mov [esp].IDT_ENTER_OUT._cs0, ecx
|
|
mov [esp].IDT_ENTER_OUT._efl, edx
|
|
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._eax
|
|
mov ebx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ebx
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ecx
|
|
mov edx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._edx
|
|
mov ebp, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ebp
|
|
mov edi, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._edi
|
|
pop esi
|
|
ifdef PAGING
|
|
push es
|
|
pop ds
|
|
endif
|
|
ENDM
|
|
|
|
DBG_EDX_FROM_EAX MACRO edxval, eaxval
|
|
if DEBUG_INTERRUPTS
|
|
mov edx, edxval
|
|
mov eax, eaxval
|
|
mov [edx], eax
|
|
endif
|
|
ENDM
|
|
|
|
DBG_SCREEN_AS_VALUE MACRO edxval, eaxval
|
|
if DEBUG_INTERRUPTS
|
|
push eax
|
|
push edx
|
|
DBG_EDX_FROM_EAX edxval, eaxval
|
|
pop edx
|
|
pop eax
|
|
endif
|
|
ENDM
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;;
|
|
ifdef DEBUG
|
|
?g_TestSave@Class_Microsoft_Singularity_Processor@@SIXPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@Z proc
|
|
pop eax
|
|
push eax
|
|
pushad
|
|
|
|
mov ebx, 0fffffeb0h
|
|
mov edx, 0fffffed0h
|
|
mov ebp, 0fffffeb1h
|
|
mov edi, 0fffffed1h
|
|
mov esi, 0fffffef1h
|
|
|
|
pushfd ; _efl
|
|
push cs ; _cs0
|
|
push eax ; _eip
|
|
push 0eeeh ; _err
|
|
push 0fffh ; _num
|
|
push esi ; _esi
|
|
|
|
mov esi, ecx
|
|
IDT_SAVE_CONTEXT 1,1,1
|
|
|
|
popad
|
|
ret
|
|
?g_TestSave@Class_Microsoft_Singularity_Processor@@SIXPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@Z endp
|
|
|
|
?g_TestSaveLoad@Class_Microsoft_Singularity_Processor@@SIXPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@Z proc
|
|
pop eax
|
|
|
|
pushfd ; _efl
|
|
push cs ; _cs0
|
|
push eax ; _eip
|
|
push 0eeeh ; _err
|
|
push 0fffh ; _num
|
|
push esi ; _esi
|
|
|
|
mov esi, ecx
|
|
IDT_SAVE_CONTEXT 1,1,1
|
|
IDT_LOAD_CONTEXT 0
|
|
iretd
|
|
|
|
?g_TestSaveLoad@Class_Microsoft_Singularity_Processor@@SIXPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@Z endp
|
|
endif
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Exceptions.
|
|
;;;
|
|
align 16
|
|
_EdtEnter proc
|
|
_EdtEnter0::
|
|
EDT_ENTER_CLEAN 000h ; #DE Divide-by-Zero
|
|
_EdtEnter1::
|
|
EDT_ENTER_CLEAN 001h ; #DB Debug Exception
|
|
EDT_ENTER_CLEAN 002h ; NMI Non-Maskable-Interrupt
|
|
EDT_ENTER_CLEAN 003h ; #BP Breakpoint
|
|
EDT_ENTER_CLEAN 004h ; #OF OVerflow
|
|
EDT_ENTER_CLEAN 005h ; #BR Bound-Range
|
|
EDT_ENTER_CLEAN 006h ; #UD Invalid Opcode
|
|
EDT_ENTER_CLEAN 007h ; #NM Device Not Available
|
|
EDT_ENTER_ERR 008h ; #DF Double Fault
|
|
EDT_ENTER_CLEAN 009h ; Unused (was x87 segment except)
|
|
EDT_ENTER_ERR 00ah ; #TS Invalid TSS
|
|
EDT_ENTER_ERR 00bh ; #NP Sgement Not Present
|
|
EDT_ENTER_ERR 00ch ; #SS Stack Exception
|
|
EDT_ENTER_ERR 00dh ; #GP General Protection
|
|
EDT_ENTER_ERR 00eh ; #PF Page Fault
|
|
EDT_ENTER_CLEAN 00fh ; Reserved
|
|
EDT_ENTER_CLEAN 010h ; #MF x87 Math Error
|
|
EDT_ENTER_ERR 011h ; #AC Alignment Check
|
|
EDT_ENTER_CLEAN 012h ; #MC Machine Check
|
|
EDT_ENTER_CLEAN 013h ; #XF SIMD Exception
|
|
EDT_ENTER_CLEAN 014h ; 014h exception
|
|
EDT_ENTER_CLEAN 015h ; 015h exception
|
|
EDT_ENTER_CLEAN 016h ; 016h exception
|
|
EDT_ENTER_CLEAN 017h ; 017h exception
|
|
EDT_ENTER_CLEAN 018h ; 018h exception
|
|
EDT_ENTER_CLEAN 019h ; 019h exception
|
|
EDT_ENTER_CLEAN 01ah ; 01ah exception
|
|
EDT_ENTER_CLEAN 01bh ; 01bh exception
|
|
EDT_ENTER_CLEAN 01ch ; 01ch exception
|
|
EDT_ENTER_CLEAN 01dh ; 01dh exception
|
|
EDT_ENTER_CLEAN 01eh ; 01eh exception
|
|
EDT_ENTER_CLEAN 01fh ; 01fh exception
|
|
|
|
_EdtEnterBody::
|
|
push esi
|
|
|
|
ifdef PAGING
|
|
push ss
|
|
pop ds ; Copy stack segment selector to DS so we can access memory!
|
|
push ss
|
|
pop es ; Copy stack segment selector to ES so we can access memory!
|
|
endif
|
|
|
|
DBG_SCREEN_AS_VALUE 0b8020h, 01f301f40h ; @0
|
|
|
|
ifdef PAGING
|
|
; XXX if we've arrived from ring 3 FS will be invalid
|
|
push Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPF - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
|
pop fs
|
|
endif
|
|
|
|
;; Exceptions spill to the per-processor exceptionContext.
|
|
mov esi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._processorContext]
|
|
lea esi, [esi].Struct_Microsoft_Singularity_X86_ProcessorContext._exceptionContext
|
|
|
|
IDT_SAVE_CONTEXT 1,1,1 ; Save fxregs, error codes, and dregs.
|
|
|
|
|
|
;; Link the per-processor exception to the faulting thread
|
|
mov edi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext]
|
|
mov eax, [edi].Struct_Microsoft_Singularity_X86_ThreadContext.__thread
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext.__thread, eax
|
|
|
|
;; Link the per-processor thread context to the original thread context.
|
|
mov [edi].Struct_Microsoft_Singularity_X86_ThreadContext._next, esi
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._prev, edi
|
|
|
|
DBG_EDX_FROM_EAX 0b8024h, 01f311f40h ; @1
|
|
|
|
;; Switch to the exception stack and adjust the stack limit values.
|
|
mov esp, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._exceptionStackBegin]
|
|
mov eax, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._exceptionStackLimit]
|
|
mov edx, [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit
|
|
mov [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit, eax
|
|
mov fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._exceptionStackPreLimit], edx
|
|
|
|
DBG_EDX_FROM_EAX 0b8028h, 01f321f40h ; @2
|
|
|
|
;; Call the exception handler.
|
|
mov edx, esi
|
|
mov eax, [?c_exceptionHandler@@3P6IXHPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@ZA]
|
|
call eax
|
|
|
|
DBG_EDX_FROM_EAX 0b802ch, 01f331f40h ; @3
|
|
|
|
;; mov esi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._processorContext]
|
|
;; lea esi, [esi].Struct_Microsoft_Singularity_X86_ProcessorContext._exceptionContext
|
|
|
|
;; Restore the stack limit (edi should still be good)
|
|
mov eax, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._exceptionStackPreLimit]
|
|
mov [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit, eax
|
|
|
|
;; Unlink the per-processor context.
|
|
mov edi, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._prev
|
|
mov [edi].Struct_Microsoft_Singularity_X86_ThreadContext._next, 0
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._prev, 0
|
|
|
|
IDT_LOAD_CONTEXT 1
|
|
|
|
iretd
|
|
|
|
_EdtEnter endp
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Interrupts.
|
|
;;;
|
|
|
|
align 16
|
|
_IdtEnter proc
|
|
_IdtEnter20::
|
|
IDT_ENTER_CLEAN 020h ; 021h: first interrupt
|
|
_IdtEnter21::
|
|
_num = 021h ; 021h to 0ffh
|
|
WHILE _num LE 0ffh
|
|
IDT_ENTER_CLEAN _num
|
|
_num = _num + 1
|
|
ENDM
|
|
|
|
_IdtEnterBody::
|
|
push esi
|
|
|
|
ifdef PAGING
|
|
push ss
|
|
pop ds ; Copy stack segment selector to DS so we can access memory!
|
|
push ss
|
|
pop es ; Copy stack segment selector to ES so we can access memory!
|
|
endif
|
|
|
|
DBG_SCREEN_AS_VALUE 0b8000h, 01f301f40h ; @0
|
|
|
|
ifdef PAGING
|
|
; XXX if we've arrived from ring 3 FS will be invalid
|
|
push Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPF - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
|
pop fs
|
|
endif
|
|
|
|
;; Interrupts spill to the thread's context.
|
|
mov esi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext]
|
|
|
|
IDT_SAVE_CONTEXT 1,0,0 ; Save fxregs, but not error codes or dregs.
|
|
|
|
|
|
DBG_EDX_FROM_EAX 0b8004h, 01f311f40h ; @1
|
|
|
|
;; Switch to the interrupt stack and adjust the stack limit values.
|
|
mov edi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext]
|
|
mov esp, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._interruptStackBegin]
|
|
mov eax, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._interruptStackLimit]
|
|
mov edx, [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit
|
|
mov [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit, eax
|
|
mov fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._interruptStackPreLimit], edx
|
|
|
|
DBG_EDX_FROM_EAX 0b8008h, 01f321f40h ; @2
|
|
|
|
;; Call the interrupt handler.
|
|
mov edx, esi
|
|
mov eax, [?c_interruptHandler@@3P6IXHPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@ZA]
|
|
call eax
|
|
|
|
DBG_EDX_FROM_EAX 0b800ch, 01f331f40h ; @3
|
|
|
|
;; Restore the stack limit (edi should still be good)
|
|
mov eax, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._interruptStackPreLimit]
|
|
mov [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit, eax
|
|
|
|
;; Select the processor's thread context (may have been changed by scheduler).
|
|
mov esi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext]
|
|
|
|
IDT_LOAD_CONTEXT 0
|
|
|
|
iretd
|
|
|
|
_IdtEnter endp
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Syscall via SYSENTER
|
|
;;;
|
|
ifdef PAGING
|
|
|
|
SYSENTER_IN STRUCT 1
|
|
_esi UINT32 ?
|
|
_num UINT32 ?
|
|
SYSENTER_IN ENDS
|
|
|
|
SYSENTER_SAVE_CONTEXT MACRO fxregs, dregs
|
|
;; Save the processor's thread context.
|
|
;; Input:
|
|
;; ESI = address of ThreadContext structure.
|
|
;; EDX = orig ESP
|
|
;; ECX = orig EIP
|
|
;; Output:
|
|
;; ESI = address of ThreadContext structure.
|
|
;; ESP = stack w/o IDT_ENTER_IN context
|
|
;; ECX = num
|
|
;;
|
|
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._eip, ecx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esp, edx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._cs0, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtUD - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull + 3
|
|
;mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ss, 05bh ; XXX no room at the inn
|
|
|
|
pushfd
|
|
pop edx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._efl, edx
|
|
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._eax, eax
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ebx, ebx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ecx, ecx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._edx, edx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ebp, ebp
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._edi, edi
|
|
|
|
mov eax, [esp].SYSENTER_IN._esi
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esi, eax
|
|
|
|
mov ecx, [esp].SYSENTER_IN._num ; this flows through
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._num, cx
|
|
|
|
;; XXX Need to save segment registers!!
|
|
|
|
if dregs
|
|
mov eax, dr0
|
|
mov ebx, dr1
|
|
mov ecx, dr2
|
|
mov edx, dr3
|
|
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr0, eax
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr1, ebx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr2, ecx
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr3, edx
|
|
|
|
mov eax, dr6
|
|
mov ebx, dr7
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr6, eax
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr7, ebx
|
|
|
|
xor eax, eax
|
|
mov dr6, eax
|
|
endif
|
|
|
|
if fxregs
|
|
if dregs
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 3
|
|
else
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 1
|
|
endif
|
|
fxsave [esi].Struct_Microsoft_Singularity_X86_ThreadContext._mmx
|
|
fninit
|
|
mov eax, 37eh
|
|
push eax
|
|
fldcw [esp]
|
|
pop eax
|
|
else
|
|
if dregs
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 2
|
|
else
|
|
mov [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 0
|
|
endif
|
|
endif
|
|
;; XXX this is wrong for the ring 3 case...
|
|
add esp, SIZEOF SYSENTER_IN
|
|
|
|
ENDM
|
|
|
|
SYSENTER_LOAD_CONTEXT MACRO dregs
|
|
;; Check if we need to restore the floating-point registers
|
|
test [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 1
|
|
jz skip_fxrstor
|
|
fxrstor [esi].Struct_Microsoft_Singularity_X86_ThreadContext._mmx
|
|
skip_fxrstor:
|
|
|
|
if dregs
|
|
;; Check if we need to restore the debug registers
|
|
test [esi].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 2
|
|
jz skip_drstor
|
|
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr0
|
|
mov ebx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr1
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr2
|
|
mov edx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr3
|
|
|
|
mov dr0, eax
|
|
mov dr1, ebx
|
|
mov dr2, ecx
|
|
mov dr3, edx
|
|
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr6
|
|
mov ebx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._dr7
|
|
|
|
mov dr6, eax
|
|
mov dr7, ebx
|
|
skip_drstor:
|
|
endif
|
|
|
|
;; Restore the registers
|
|
mov eax, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._eax
|
|
mov ebx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ebx
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ecx ; pointless
|
|
mov edx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._edx ; pointless
|
|
mov ebp, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._ebp
|
|
mov edi, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._edi
|
|
|
|
;; We restore EIP into edx and ESP into ECX
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esp
|
|
mov edx, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._eip
|
|
|
|
|
|
;; Need to restore segment registers
|
|
|
|
; Restore flags - is this necessary?
|
|
push [esi].Struct_Microsoft_Singularity_X86_ThreadContext._efl
|
|
mov esi, [esi].Struct_Microsoft_Singularity_X86_ThreadContext._esi
|
|
popfd
|
|
ENDM
|
|
|
|
align 16
|
|
_SysEnter proc
|
|
; SYSENTER doesn't put *anything* on the stack - the only way
|
|
; we can know the return EIP/ESP is if they are passed in registers.
|
|
; On Windows there is only one SYSENTER instruction in ntdll, so sysexit
|
|
; knows where to return to, and the ring 3 stack pointer is passed in edx.
|
|
;
|
|
; Entry state: ss:esp0, cs:eip loaded from processor MSRs
|
|
;
|
|
push 0
|
|
push 02Fh
|
|
push esi ; This is to make the stack frame look like IDT_ENTER_ expects
|
|
|
|
push ss
|
|
pop ds ; Copy stack segment selector to DS so we can access memory!
|
|
|
|
DBG_SCREEN_AS_VALUE 0b8000h, 01f301f40h ; @0
|
|
|
|
; XXX if we've arrived from ring 3 FS will be invalid
|
|
push Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPF - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
|
pop fs
|
|
push ss
|
|
pop es ; Copy stack segment selector to ES so we can access memory!
|
|
|
|
;; Interrupts spill to the thread's context.
|
|
mov esi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext]
|
|
|
|
;; XXX - Can save some time by not saving caller-save regs
|
|
SYSENTER_SAVE_CONTEXT 1,0 ; Save fxregs, but not error codes or dregs.
|
|
|
|
DBG_EDX_FROM_EAX 0b8004h, 01f311f40h ; @1
|
|
|
|
;; Switch to the interrupt stack and adjust the stack limit values.
|
|
mov edi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext]
|
|
mov esp, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._interruptStackBegin]
|
|
mov eax, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._interruptStackLimit]
|
|
mov edx, [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit
|
|
mov [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit, eax
|
|
mov fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._interruptStackPreLimit], edx
|
|
|
|
DBG_EDX_FROM_EAX 0b8008h, 01f321f40h ; @2
|
|
|
|
;; Call the interrupt handler.
|
|
mov edx, esi
|
|
mov eax, [?c_interruptHandler@@3P6IXHPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@ZA]
|
|
call eax
|
|
|
|
DBG_EDX_FROM_EAX 0b800ch, 01f331f40h ; @3
|
|
|
|
;; Restore the stack limit (edi should still be good)
|
|
mov eax, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._interruptStackPreLimit]
|
|
mov [edi].Struct_Microsoft_Singularity_X86_ThreadContext._stackLimit, eax
|
|
|
|
;; Select the processor's thread context (may have been changed by scheduler).
|
|
mov esi, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext]
|
|
|
|
;
|
|
SYSENTER_LOAD_CONTEXT 0
|
|
|
|
; SYSEXIT does the following
|
|
; EIP <-- EDX
|
|
; ESP <-- ECX
|
|
; CS <-- MSR[IA32_CS_SYSENTER] + 0x18
|
|
sysexit
|
|
|
|
_SysEnter endp
|
|
|
|
endif
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;
|
|
; void Processor.SwitchToThreadContext(ref X86_ThreadContext newContext);
|
|
; Saves the current context and load the new context from
|
|
; newContext(ecx), effectively switching contexts between threads.
|
|
; Always returns executing in the new context.
|
|
; The code after _SwitchedInContextSwitch will only run if the context was
|
|
; switch out using this routine.
|
|
;
|
|
; precondition: Scheduler.dispatchLock held
|
|
;
|
|
align 16
|
|
?g_SwitchToThreadContextNoGC@Class_Microsoft_Singularity_Processor@@SIXPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@Z proc
|
|
;; Save the old processor context.
|
|
|
|
pushfd
|
|
|
|
;; From here on we need interrupts disabled.
|
|
cli
|
|
|
|
mov edx, fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext]
|
|
|
|
;; On clean switch, no need to save caller-saved registers (eax,ecx,edx,fxsave)
|
|
ifdef PAGING
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._cs0, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPC - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
|
endif
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._ebx, ebx
|
|
|
|
pop eax ; pop flags from stack.
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._efl, eax
|
|
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._esp, esp
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._ebp, ebp
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._esi, esi
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._edi, edi
|
|
ifdef PAGING
|
|
mov eax, CR3
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._cr3, eax
|
|
endif
|
|
|
|
lea eax, _SwitchedInContextSwitch
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._eip, eax
|
|
|
|
ifdef THREAD_TIME_ACCOUNTING
|
|
;; thread execution time accouting
|
|
;; Get and save current timestamp
|
|
mov ebx, edx ; save edx
|
|
rdtsc ; -> edx:eax
|
|
|
|
push eax ; save timestamp for later use
|
|
push edx
|
|
|
|
;; now - old.lastExecutionTimeUpdate
|
|
sub eax, dword ptr [ebx ].Struct_Microsoft_Singularity_X86_ThreadContext._lastExecutionTimeUpdate
|
|
sbb edx, dword ptr [ebx + 4].Struct_Microsoft_Singularity_X86_ThreadContext._lastExecutionTimeUpdate
|
|
|
|
;; old.executionTime += now - old.lastExecutionTimeUpdate
|
|
add dword ptr [ebx ].Struct_Microsoft_Singularity_X86_ThreadContext._executionTime, eax
|
|
adc dword ptr [ebx + 4].Struct_Microsoft_Singularity_X86_ThreadContext._executionTime, edx
|
|
|
|
pop edx ; restore timestamp
|
|
pop eax
|
|
|
|
;; new.lastExecutionTimeUpdate = now
|
|
mov dword ptr [ecx ].Struct_Microsoft_Singularity_X86_ThreadContext._lastExecutionTimeUpdate, eax
|
|
mov dword ptr [ecx + 4].Struct_Microsoft_Singularity_X86_ThreadContext._lastExecutionTimeUpdate, edx
|
|
|
|
mov edx, ebx ; restore edx
|
|
;; End thread execution time accouting
|
|
endif
|
|
;; On clean switch, no need to save caller-saved registers
|
|
; fxsave [edx].Struct_Microsoft_Singularity_X86_ThreadContext._mmx
|
|
mov [edx].Struct_Microsoft_Singularity_X86_ThreadContext._regs, 0
|
|
|
|
;; The old context has been saved, so we can now release the dispatch
|
|
;; lock and let other processors load the old context.
|
|
;; (We've released the old stack pointer and haven't yet
|
|
;; set up a new stack pointer, so the following code
|
|
;; does not touch the stack.)
|
|
;; This code duplicates code from SpinLock.Release.
|
|
|
|
if SPINLOCK_RELEASE_SANITY_CHECK
|
|
; if (this.lockWord != 1 || this.lockingThreadIndexPlusOne-1 != currentThreadId) throw ...
|
|
cmp ?c_dispatchLock@Class_Microsoft_Singularity_Scheduling_Scheduler@@2?AUStruct_System_Threading_SpinLock@@A.Struct_System_Threading_SpinLock._lockWord, 1
|
|
je spinLockOk1
|
|
int 3
|
|
spinLockOk1:
|
|
mov eax, ?c_dispatchLock@Class_Microsoft_Singularity_Scheduling_Scheduler@@2?AUStruct_System_Threading_SpinLock@@A.Struct_System_Threading_SpinLock._lockingThreadIndexPlusOne
|
|
sub eax, 1
|
|
cmp [edx].Struct_Microsoft_Singularity_X86_ThreadContext._threadIndex, ax
|
|
je spinLockOk2
|
|
int 3
|
|
spinLockOk2:
|
|
endif ; SPINLOCK_RELEASE_SANITY_CHECK
|
|
; this.lockingThreadIndexPlusOne = 0;
|
|
; this.lockWord = 0;
|
|
mov ?c_dispatchLock@Class_Microsoft_Singularity_Scheduling_Scheduler@@2?AUStruct_System_Threading_SpinLock@@A.Struct_System_Threading_SpinLock._lockingThreadIndexPlusOne, 0
|
|
mov ?c_dispatchLock@Class_Microsoft_Singularity_Scheduling_Scheduler@@2?AUStruct_System_Threading_SpinLock@@A.Struct_System_Threading_SpinLock._lockWord, 0
|
|
|
|
;; Load the new processor context.
|
|
|
|
mov fs:[Struct_Microsoft_Singularity_X86_ProcessorContext._threadContext], ecx
|
|
mov esi, ecx
|
|
|
|
IDT_LOAD_CONTEXT 0
|
|
|
|
iretd
|
|
|
|
_SwitchedInContextSwitch:
|
|
ret
|
|
|
|
?g_SwitchToThreadContextNoGC@Class_Microsoft_Singularity_Processor@@SIXPAUStruct_Microsoft_Singularity_X86_ThreadContext@@@Z endp
|
|
|
|
ifdef DOUBLE_FAULT_HANDLER
|
|
align 16
|
|
?CallTaskGate@@YIXGI@Z proc
|
|
;
|
|
; FAR JMP to double-fault task gate. This is hand-coded, because I can't figure out
|
|
; how to make MASM do this for me.
|
|
;
|
|
db 09Ah ; CALL FAR PTR
|
|
dd 0
|
|
dw Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtDFG - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
|
|
|
ret
|
|
?CallTaskGate@@YIXGI@Z endp
|
|
|
|
PRINTAL MACRO
|
|
mov ah, 0ah;0ah
|
|
mov [edx], ax
|
|
add edx, 2
|
|
ENDM
|
|
|
|
PRINTC MACRO num
|
|
mov al, num
|
|
mov ah, 02h;0ah
|
|
mov [edx], ax
|
|
add edx, 2
|
|
ENDM
|
|
|
|
; DoubleFault
|
|
; Entered in 32-bit protected mode.
|
|
PUBLIC ?DoubleFault@@YIXXZ
|
|
?DoubleFault@@YIXXZ PROC NEAR
|
|
mov edx, 0b8000h
|
|
|
|
PRINTC '*'
|
|
PRINTC '*'
|
|
PRINTC '2'
|
|
PRINTC '*'
|
|
PRINTC '*'
|
|
PRINTC ' '
|
|
|
|
PRINTC 'e'
|
|
PRINTC 'b'
|
|
PRINTC 'p'
|
|
mov ecx, ebp
|
|
call printdw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 'f'
|
|
PRINTC 'l'
|
|
pushfd
|
|
pop ecx
|
|
call printdw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 'f'
|
|
PRINTC 'l'
|
|
pushfd
|
|
pop ecx
|
|
; or ecx, 04000h
|
|
; push ecx
|
|
; popfd
|
|
call printdw
|
|
|
|
mov edx, 0b8000h + 160
|
|
|
|
PRINTC 'c'
|
|
PRINTC 's'
|
|
push cs
|
|
pop cx
|
|
call printw
|
|
|
|
PRINTC 's'
|
|
PRINTC 's'
|
|
mov cx, ss
|
|
call printw
|
|
|
|
PRINTC 'd'
|
|
PRINTC 's'
|
|
mov cx, ds
|
|
call printw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 's'
|
|
mov cx, es
|
|
call printw
|
|
|
|
PRINTC 'f'
|
|
PRINTC 's'
|
|
mov cx, fs
|
|
call printw
|
|
|
|
PRINTC 'g'
|
|
PRINTC 's'
|
|
mov cx, gs
|
|
call printw
|
|
|
|
PRINTC 't'
|
|
PRINTC 'r'
|
|
str cx
|
|
call printw
|
|
|
|
mov edx, 0b8000h + 160 * 2
|
|
|
|
PRINTC 'e'
|
|
PRINTC 's'
|
|
PRINTC 'p'
|
|
mov ecx, esp
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '0'
|
|
mov ecx, [esp]
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '4'
|
|
mov ecx, [esp+4]
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '8'
|
|
mov ecx, [esp+8]
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '1'
|
|
PRINTC '2'
|
|
mov ecx, [esp+12]
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '1'
|
|
PRINTC '6'
|
|
mov ecx, [esp+16]
|
|
call printdw
|
|
|
|
mov edx, 0b8000h + 160 * 3
|
|
|
|
PRINTC 'e'
|
|
PRINTC 's'
|
|
PRINTC 'i'
|
|
mov ecx, esi
|
|
call printdw
|
|
|
|
PRINTC 'p'
|
|
PRINTC 't'
|
|
mov cx, [esi].Struct_Microsoft_Singularity_X86_TSS._previous_tss
|
|
call printw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 's'
|
|
PRINTC 'p'
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_TSS._esp
|
|
call printdw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 'i'
|
|
PRINTC 'p'
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_TSS._eip
|
|
call printdw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 'f'
|
|
PRINTC 'l'
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_TSS._eflags
|
|
call printdw
|
|
|
|
PRINTC 'c'
|
|
PRINTC 'r'
|
|
PRINTC '3'
|
|
mov ecx, [esi].Struct_Microsoft_Singularity_X86_TSS._cr3
|
|
call printdw
|
|
|
|
PRINTC 'u'
|
|
mov cx, [esi].Struct_Microsoft_Singularity_X86_TSS._trap_bit
|
|
call printw
|
|
|
|
mov edx, 0b8000h + 160 * 4
|
|
|
|
PRINTC 'e'
|
|
PRINTC 'd'
|
|
PRINTC 'i'
|
|
mov ecx, edi
|
|
call printdw
|
|
|
|
PRINTC 'p'
|
|
PRINTC 't'
|
|
mov cx, [edi].Struct_Microsoft_Singularity_X86_TSS._previous_tss
|
|
call printw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 's'
|
|
PRINTC 'p'
|
|
mov ecx, [edi].Struct_Microsoft_Singularity_X86_TSS._esp
|
|
call printdw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 'i'
|
|
PRINTC 'p'
|
|
mov ecx, [edi].Struct_Microsoft_Singularity_X86_TSS._eip
|
|
call printdw
|
|
|
|
PRINTC 'e'
|
|
PRINTC 'f'
|
|
PRINTC 'l'
|
|
mov ecx, [edi].Struct_Microsoft_Singularity_X86_TSS._eflags
|
|
call printdw
|
|
|
|
PRINTC 'c'
|
|
PRINTC 'r'
|
|
PRINTC '3'
|
|
mov ecx, [edi].Struct_Microsoft_Singularity_X86_TSS._cr3
|
|
call printdw
|
|
|
|
PRINTC 'u'
|
|
mov cx, [edi].Struct_Microsoft_Singularity_X86_TSS._trap_bit
|
|
call printw
|
|
|
|
mov edx, 0b8000h + 160 * 5
|
|
mov ebp, [esi].Struct_Microsoft_Singularity_X86_TSS._esp
|
|
|
|
PRINTC 'e'
|
|
PRINTC 's'
|
|
PRINTC 'p'
|
|
mov ecx, ebp
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '0'
|
|
mov ecx, [ebp]
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '4'
|
|
mov ecx, [ebp+4]
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '8'
|
|
mov ecx, [ebp+8]
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '1'
|
|
PRINTC '2'
|
|
mov ecx, [ebp+12]
|
|
call printdw
|
|
|
|
PRINTC '+'
|
|
PRINTC '1'
|
|
PRINTC '6'
|
|
mov ecx, [ebp+16]
|
|
call printdw
|
|
|
|
|
|
iretd ; // note, should clear CR0.TS
|
|
again:
|
|
jmp again
|
|
|
|
?DoubleFault@@YIXXZ ENDP
|
|
|
|
; Print a DWORD to the screen
|
|
; [in] ecx = dword to print
|
|
; [in] edx = address of screen
|
|
; [use] eax = trashed for temporary
|
|
;
|
|
printdw PROC NEAR
|
|
PRINTC ':'
|
|
|
|
mov eax, ecx
|
|
shr eax, 28
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print28
|
|
add eax, 7h
|
|
print28:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 24
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print24
|
|
add eax, 7h
|
|
print24:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 20
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print20
|
|
add eax, 7h
|
|
print20:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 16
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print16
|
|
add eax, 7h
|
|
print16:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 12
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print12
|
|
add eax, 7h
|
|
print12:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 08
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print08
|
|
add eax, 7h
|
|
print08:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 04
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print04
|
|
add eax, 7h
|
|
print04:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 00
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print00
|
|
add eax, 7h
|
|
print00:
|
|
PRINTAL
|
|
|
|
PRINTC ' '
|
|
|
|
ret
|
|
printdw ENDP
|
|
|
|
; Print a WORD to the screen
|
|
; [in] ecx = word to print (in low 16-bits, high 16-bits ignored)
|
|
; [in] edx = address of screen
|
|
; [use] eax = trashed for temporary
|
|
;
|
|
printw PROC NEAR
|
|
PRINTC ':'
|
|
|
|
mov eax, ecx
|
|
shr eax, 12
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print12
|
|
add eax, 7h
|
|
print12:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 08
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print08
|
|
add eax, 7h
|
|
print08:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 04
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print04
|
|
add eax, 7h
|
|
print04:
|
|
PRINTAL
|
|
|
|
mov eax, ecx
|
|
shr eax, 00
|
|
and eax, 0fh
|
|
add eax, 030h
|
|
cmp eax, 03ah
|
|
jl print00
|
|
add eax, 7h
|
|
print00:
|
|
PRINTAL
|
|
|
|
PRINTC ' '
|
|
|
|
ret
|
|
printw ENDP
|
|
endif ;; DOUBLE_FAULT_HANDLER
|
|
|
|
END
|