|
|
;++ ; ; 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
|