388 lines
9.1 KiB
NASM
388 lines
9.1 KiB
NASM
;++
|
||
;
|
||
; Module Name:
|
||
;
|
||
; trap.asm
|
||
;
|
||
; Author:
|
||
;
|
||
; Thomas Parslow [tomp]
|
||
;
|
||
; Created:
|
||
;
|
||
; 15-Jan-91
|
||
;
|
||
;
|
||
; Description:
|
||
;
|
||
; x86 exception code
|
||
;
|
||
;
|
||
|
||
include su.inc
|
||
|
||
;
|
||
; Exception Routing Table:
|
||
; ~~~~~~~~~~~~~~~~~~~~~~~~
|
||
; When an exception occurs in the SU module or before the OS loader
|
||
; is able to setup its own IDT, control is vectored to one of the
|
||
; Trap0 though TrapF labels. We push a number on the stack identifying
|
||
; the exception number and then jump to code that pushes the register set
|
||
; onto the stack. We then call a general purpose C routine that will dump
|
||
; the register contents, the trap number, and error code information
|
||
; onto the display.
|
||
;
|
||
|
||
_TEXT segment para use16 public 'CODE'
|
||
ASSUME CS: _TEXT, DS: DGROUP, SS: DGROUP
|
||
.386p
|
||
|
||
extrn _TrapHandler:near
|
||
extrn _putx:near
|
||
extrn _GDTregister:fword
|
||
extrn _IDTregister:fword
|
||
extrn _InDebugger:word
|
||
extrn SaveSP:word
|
||
|
||
public Trap0,Trap1,Trap2,Trap3,Trap4,Trap5,Trap6,Trap7
|
||
public Trap8,Trap9,TrapA,TrapB,TrapC,TrapD,TrapE,TrapF
|
||
|
||
|
||
Trap0: TRAP_NUMBER 0,MakeTrapFrame
|
||
Trap1: TRAP_NUMBER 1,MakeTrapFrame
|
||
Trap2: TRAP_NUMBER 2,MakeTrapFrame
|
||
Trap3: TRAP_NUMBER 3,MakeTrapFrame
|
||
Trap4: TRAP_NUMBER 4,MakeTrapFrame
|
||
Trap5: TRAP_NUMBER 5,MakeTrapFrame
|
||
Trap6: TRAP_NUMBER 6,MakeTrapFrame
|
||
Trap7: TRAP_NUMBER 7,MakeTrapFrame
|
||
Trap8: TRAP_NUMBER 8,MakeTrapFrame
|
||
Trap9: TRAP_NUMBER 9,MakeTrapFrame
|
||
TrapA: TRAP_NUMBER 0Ah,MakeTrapFrame
|
||
TrapB: TRAP_NUMBER 0Bh,MakeTrapFrame
|
||
TrapC: TRAP_NUMBER 0Ch,MakeTrapFrame
|
||
TrapD: TRAP_NUMBER 0Dh,MakeTrapFrame
|
||
TrapE: TRAP_NUMBER 0Eh,MakeTrapFrame
|
||
TrapF: TRAP_NUMBER 0Fh,MakeTrapFrame
|
||
|
||
|
||
;
|
||
; We save the user's register contents here on the stack and call
|
||
; a C routine to display those contents.
|
||
; Uses 42 bytes of stack. (40 for frame)
|
||
;
|
||
; Note that we build a stack frame that's independent of the code and
|
||
; stack segments' "size" during execution. That way whether we enter
|
||
; with a 16bit or 32bit stack, the arguments frame is exacely the same.
|
||
;
|
||
|
||
MakeTrapFrame:
|
||
|
||
mov eax,esp
|
||
push ecx
|
||
push edx
|
||
push ebx
|
||
push eax ; (eax)=(esp)
|
||
push ebp
|
||
push esi
|
||
push edi
|
||
|
||
mov ax,ds
|
||
push ax
|
||
mov ax,es
|
||
push ax
|
||
mov ax,fs
|
||
push ax
|
||
mov ax,gs
|
||
push ax
|
||
mov ax,ss
|
||
push ax
|
||
mov eax,cr3
|
||
push eax
|
||
mov eax,cr2
|
||
push eax
|
||
mov eax,cr0
|
||
push eax
|
||
mov eax,dr6
|
||
push eax
|
||
str ax
|
||
push ax
|
||
;
|
||
; Clear out debug register signals
|
||
;
|
||
|
||
xor eax,eax
|
||
mov dr6,eax
|
||
|
||
;
|
||
; Get a known good data segment
|
||
;
|
||
mov ax,SuDataSelector
|
||
mov ds,ax
|
||
;
|
||
; Save system registers
|
||
;
|
||
mov bx,offset DGROUP:_GDTregister
|
||
sgdt fword ptr [bx]
|
||
mov bx,offset DGROUP:_IDTregister
|
||
sidt fword ptr [bx]
|
||
;
|
||
; Is the exception frame on a 16bit or 32bit stack?
|
||
;
|
||
mov ax,ss
|
||
cmp ax,KeDataSelector
|
||
je Trap32
|
||
cmp ax,DbDataSelector
|
||
jne mtf8
|
||
;
|
||
; Most likely we took a trap while initializing the 386 kernel debugger
|
||
; So we've got a 16bit stack that isn't ours. We need to move
|
||
; the stack frame onto the SU module's stack.
|
||
|
||
jmp Trap16
|
||
|
||
mtf8:
|
||
;
|
||
; Frame on a our 16bit stack so just call the trap dump routine
|
||
;
|
||
mov bx,offset DGROUP:SaveSP
|
||
mov [bx],sp
|
||
|
||
call _TrapHandler
|
||
|
||
;
|
||
; Get rid of the junk we saved just to display
|
||
;
|
||
pop eax ; get rid of ebp pushed for other returns
|
||
add sp,ExceptionFrame.Fgs
|
||
;
|
||
; Reload the user's context and return to 16bit code
|
||
;
|
||
pop gs
|
||
pop fs
|
||
pop es
|
||
pop ds
|
||
pop edi
|
||
pop esi
|
||
pop ebp
|
||
pop eax
|
||
pop ebx
|
||
pop edx
|
||
pop ecx
|
||
pop eax ; get rid of trap #
|
||
pop eax ; get original eax
|
||
add esp,4 ; get rid of error code
|
||
;
|
||
; Pop IRET frame and return to where the trap occured
|
||
;
|
||
OPSIZE
|
||
iret
|
||
|
||
|
||
|
||
|
||
|
||
Trap32:
|
||
;
|
||
; The exception frame is on a 32bit stack so we must setup a 16bit
|
||
; stack and then move the exception frame on to it before calling
|
||
; the trap dump routine.
|
||
;
|
||
|
||
mov ebx,esp
|
||
;
|
||
; Setup a known good stack
|
||
;
|
||
mov ax,SuDataSelector
|
||
mov ss,ax
|
||
mov sp,EXPORT_STACK
|
||
;
|
||
; Copy the exception frame to the new stack
|
||
;
|
||
|
||
mov ecx, (size ExceptionFrame)/2 ; # of words in frame
|
||
mov esi,ebx ; (esi) = offset of argument frame
|
||
push KeDataSelector ; (ax) = Flat 32bit segment selector
|
||
pop ds ; (ds:esi) points to argument frame
|
||
push ss ;
|
||
pop es ; (es) = 16bit stack selector
|
||
sub sp, size ExceptionFrame ; make room for the arguments
|
||
xor edi,edi ; clear out upper 16bits of edi
|
||
mov di,sp ; (es:edi) points to top of stack
|
||
;
|
||
; Loop and copy a word at a time.
|
||
;
|
||
msf1:
|
||
mov ax,[esi]
|
||
mov es:[edi],ax
|
||
add esi,2
|
||
add edi,2
|
||
loop msf1
|
||
|
||
push es ;
|
||
pop ds ; put 16bit selector back into ds
|
||
|
||
;
|
||
; Now call the general purpose exception handler
|
||
;
|
||
push ebx ; save esp for return
|
||
;
|
||
; Save SP in order to restore the stack in case we
|
||
; take a fault in the debugger
|
||
;
|
||
mov bx,offset DGROUP:SaveSP
|
||
mov [bx],sp
|
||
|
||
call _TrapHandler
|
||
|
||
IFDEF DEBUG0
|
||
public DebugReturn
|
||
DebugReturn:
|
||
ENDIF ;DEBUG
|
||
pop ebx
|
||
;
|
||
; We may have changed the flags while in the debugger. Copy the
|
||
; new eflag to the iret frame. After we restore the original stack
|
||
; pointers.
|
||
;
|
||
|
||
mov bp,sp
|
||
mov ecx,[bp].Feflags
|
||
|
||
mov ax,KeDataSelector
|
||
mov ss,ax
|
||
mov esp,ebx
|
||
|
||
mov [esp].Feflags,ecx
|
||
;
|
||
; Get rid of the junk we saved just to display
|
||
;
|
||
add esp,ExceptionFrame.Fgs
|
||
;
|
||
; Reload the user's context
|
||
;
|
||
pop gs
|
||
pop fs
|
||
pop es
|
||
pop ds
|
||
pop edi
|
||
pop esi
|
||
pop ebp
|
||
pop eax
|
||
pop ebx
|
||
pop edx
|
||
pop ecx
|
||
pop eax ; get rid of trap #
|
||
pop eax ; get original eax
|
||
add esp,4 ; get rid of error code
|
||
;
|
||
; Pop IRET frame and return to where the trap occured
|
||
;
|
||
OPSIZE
|
||
iret
|
||
|
||
|
||
Trap16:
|
||
|
||
; The exception frame is on a 16bit stack that isn't ours. So we must
|
||
; move the exception frame on to the SU module's stack before calling
|
||
; the trap dump routine.
|
||
;
|
||
|
||
mov ebx,esp
|
||
;
|
||
; Setup a known good stack
|
||
;
|
||
mov ax,SuDataSelector
|
||
mov ss,ax
|
||
mov sp,EXPORT_STACK
|
||
;
|
||
; Copy the exception frame to the new stack
|
||
;
|
||
|
||
mov ecx, (size ExceptionFrame)/2
|
||
mov si,bx ; (esi) = offset of argument frame
|
||
push DbDataSelector ;
|
||
pop ds ; (ds:esi) points to argument frame
|
||
push ss ;
|
||
pop es ; (es) = 16bit stack selector
|
||
sub sp, size ExceptionFrame ; make room for the arguments
|
||
mov di,sp ; (es:edi) points to top of stack
|
||
;
|
||
; Loop and copy a word at a time.
|
||
;
|
||
Trap16_10:
|
||
mov ax,[si]
|
||
mov es:[di],ax
|
||
add si,2
|
||
add di,2
|
||
loop Trap16_10
|
||
|
||
push es ;
|
||
pop ds ; put 16bit selector back into ds
|
||
|
||
;
|
||
; Now call the general purpose exception handler
|
||
;
|
||
|
||
push ebx ; save (original esp) for return
|
||
;
|
||
; Save SP in order to restore the stack in case we
|
||
; take a fault in the debugger
|
||
;
|
||
mov bx,offset DGROUP:SaveSP
|
||
mov [bx],sp
|
||
|
||
call _TrapHandler
|
||
|
||
IFDEF DEBUG0
|
||
public Debug16Return
|
||
Debug16Return:
|
||
ENDIF ;DEBUG
|
||
pop ebx
|
||
;
|
||
; We may have changed the flags while in the debugger. Copy the
|
||
; new eflag to the iret frame. After we restore the original stack
|
||
; pointers.
|
||
;
|
||
|
||
mov bp,sp
|
||
mov ecx,dword ptr [bp].Feflags
|
||
|
||
mov ax,DbDataSelector
|
||
mov ss,ax
|
||
mov esp,ebx
|
||
|
||
mov dword ptr ss:[bx].Feflags,ecx
|
||
;
|
||
; Get rid of the junk we saved just to display
|
||
;
|
||
add sp,ExceptionFrame.Fgs
|
||
;
|
||
; Reload the user's context
|
||
;
|
||
pop gs
|
||
pop fs
|
||
pop es
|
||
pop ds
|
||
pop edi
|
||
pop esi
|
||
pop ebp
|
||
pop eax
|
||
pop ebx
|
||
pop edx
|
||
pop ecx
|
||
pop eax ; get rid of trap #
|
||
pop eax ; get original eax
|
||
add esp,4 ; get rid of error code
|
||
;
|
||
; Pop IRET frame and return to where the trap occured
|
||
;
|
||
OPSIZE
|
||
iret
|
||
|
||
|
||
|
||
_TEXT ends
|
||
end
|
||
|