2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/hal/x86/exp.c
5 * PURPOSE: Handling exceptions
6 * PROGRAMMER: David Welch (welch@cwcom.net)
11 /* INCLUDES *****************************************************************/
13 #include <ddk/ntddk.h>
14 #include <internal/ntoskrnl.h>
15 #include <internal/ke.h>
16 #include <internal/i386/segment.h>
17 #include <internal/mmhal.h>
18 #include <internal/module.h>
19 #include <internal/mm.h>
22 #include <internal/debug.h>
24 /* GLOBALS *****************************************************************/
26 static exception_hook
* exception_hooks
[256]={NULL
,};
29 #define STR(x) _STR(x)
31 extern void interrupt_handler2e(void);
32 extern void interrupt_handler2d(void);
34 extern ULONG init_stack
;
35 extern ULONG init_stack_top
;
37 /* FUNCTIONS ****************************************************************/
39 #define EXCEPTION_HANDLER_WITH_ERROR(x,y) \
40 void exception_handler##y (void); \
41 void tmp_exception_handler##y (void) { \
42 __asm__("\n\t_exception_handler"##x":\n\t" \
49 "movw $"STR(KERNEL_DS)",%ax\n\t" \
54 "call _exception_handler\n\t" \
64 #define EXCEPTION_HANDLER_WITHOUT_ERROR(x,y) \
65 asmlinkage void exception_handler##y (void); \
66 void tmp_exception_handler##y (void) { \
67 __asm__("\n\t_exception_handler"##x":\n\t" \
75 "movw $"STR(KERNEL_DS)",%ax\n\t" \
80 "call _exception_handler\n\t" \
90 asmlinkage
void exception_handler_unknown(void);
91 asmlinkage
void tmp_exception_handler_unknown(void)
93 __asm__("\n\t_exception_handler_unknown:\n\t"
102 "movw $"STR(KERNEL_DS
)",%ax\n\t"
107 "call _exception_handler\n\t"
113 EXCEPTION_HANDLER_WITHOUT_ERROR("0",0);
114 EXCEPTION_HANDLER_WITHOUT_ERROR("1",1);
115 EXCEPTION_HANDLER_WITHOUT_ERROR("2",2);
116 EXCEPTION_HANDLER_WITHOUT_ERROR("3",3);
117 EXCEPTION_HANDLER_WITHOUT_ERROR("4",4);
118 EXCEPTION_HANDLER_WITHOUT_ERROR("5",5);
119 EXCEPTION_HANDLER_WITHOUT_ERROR("6",6);
120 EXCEPTION_HANDLER_WITHOUT_ERROR("7",7);
121 EXCEPTION_HANDLER_WITH_ERROR("8",8);
122 EXCEPTION_HANDLER_WITHOUT_ERROR("9",9);
123 EXCEPTION_HANDLER_WITH_ERROR("10",10);
124 EXCEPTION_HANDLER_WITH_ERROR("11",11);
125 EXCEPTION_HANDLER_WITH_ERROR("12",12);
126 EXCEPTION_HANDLER_WITH_ERROR("13",13);
127 EXCEPTION_HANDLER_WITH_ERROR("14",14);
128 EXCEPTION_HANDLER_WITH_ERROR("15",15);
129 EXCEPTION_HANDLER_WITHOUT_ERROR("16",16);
131 extern unsigned int stext
, etext
;
133 static void print_address(PVOID address
)
135 PLIST_ENTRY current_entry
;
136 PMODULE_OBJECT current
;
137 extern LIST_ENTRY ModuleListHead
;
139 current_entry
= ModuleListHead
.Flink
;
141 while (current_entry
!= &ModuleListHead
&&
142 current_entry
!= NULL
)
144 current
= CONTAINING_RECORD(current_entry
, MODULE_OBJECT
, ListEntry
);
146 if (address
>= current
->Base
&&
147 address
< (current
->Base
+ current
->Length
))
149 DbgPrint("<%S: %x>", current
->Name
,
150 address
- current
->Base
);
154 current_entry
= current_entry
->Flink
;
156 DbgPrint("<%x>", address
);
159 asmlinkage
void exception_handler(unsigned int edi
,
160 unsigned int esi
, unsigned int ebp
,
161 unsigned int esp
, unsigned int ebx
,
162 unsigned int edx
, unsigned int ecx
,
169 unsigned int error_code
,
171 unsigned int cs
, unsigned int eflags
,
172 unsigned int esp0
, unsigned int ss0
)
174 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
175 * message and halt the computer
177 * Complete CPU context
180 unsigned int cr2
, cr3
;
182 // unsigned int j, sym;
184 static char *TypeStrings
[] =
191 "BOUND range exceeded",
193 "No Math Coprocessor",
197 "Segment Not Present",
198 "Stack Segment Fault",
199 "General Protection",
210 if (MmPageFault(cs
&0xffff, eip
, error_code
))
217 DbgPrint("Trap at CS:EIP %x:%x\n",cs
&0xffff,eip
);
222 * Activate any hook for the exception
224 if (exception_hooks
[type
]!=NULL
)
226 exception_hooks
[type
](NULL
,type
);
230 * Print out the CPU registers
234 DbgPrint("%s Exception: %d(%x)\n",TypeStrings
[type
],type
,
239 DbgPrint("Exception: %d(%x)\n",type
,error_code
&0xffff);
241 DbgPrint("CS:EIP %x:%x\n",cs
&0xffff,eip
);
242 DbgPrint("CS:EIP %x:", cs
&0xffff);
243 print_address((PVOID
)eip
);
245 __asm__("movl %%cr2,%0\n\t"
247 __asm__("movl %%cr3,%0\n\t"
249 DbgPrint("cr2 %x cr3 %x\n",cr2
,cr3
);
251 DbgPrint("Process: %x\n",PsGetCurrentProcess());
252 if (PsGetCurrentProcess() != NULL
)
254 DbgPrint("Process id: %x <", PsGetCurrentProcess()->UniqueProcessId
);
255 DbgPrint("%.8s>", PsGetCurrentProcess()->ImageFileName
);
257 if (PsGetCurrentThread() != NULL
)
259 DbgPrint("Thread: %x Thread id: %x\n",
260 PsGetCurrentThread(),
261 PsGetCurrentThread()->Cid
.UniqueThread
);
263 DbgPrint("DS %x ES %x FS %x GS %x\n",ds
&0xffff,es
&0xffff,fs
&0xffff,
265 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n",eax
,ebx
,ecx
);
266 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n",edx
,ebp
,esi
);
267 DbgPrint("EDI: %.8x EFLAGS: %.8x ",edi
,eflags
);
268 if ((cs
&0xffff) == KERNEL_CS
)
270 DbgPrint("kESP %.8x ",esp
);
271 if (PsGetCurrentThread() != NULL
)
273 DbgPrint("kernel stack base %x\n",
274 PsGetCurrentThread()->Tcb
.Context
.KernelStackBase
);
280 DbgPrint("kernel ESP %.8x\n",esp
);
282 if ((cs
& 0xffff) == KERNEL_CS
)
284 DbgPrint("ESP %x\n",esp
);
285 stack
= (PULONG
) (esp
+ 24);
286 // stack = (PULONG)(((ULONG)stack) & (~0x3));
288 DbgPrint("stack<%p>: ", stack
);
290 for (i
= 0; i
< 16; i
= i
+ 4)
292 DbgPrint("%.8x %.8x %.8x %.8x\n",
298 DbgPrint("Frames:\n");
299 for (i
= 0; i
< 32; i
++)
301 if (stack
[i
] > ((unsigned int) &stext
) &&
302 !(stack
[i
] >= ((ULONG
)&init_stack
) &&
303 stack
[i
] <= ((ULONG
)&init_stack_top
)))
305 // DbgPrint(" %.8x", stack[i]);
306 print_address((PVOID
)stack
[i
]);
314 DbgPrint("SS:ESP %x:%x\n",ss0
,esp0
);
315 stack
=(PULONG
)(esp0
);
317 DbgPrint("Stack:\n");
320 if (MmIsPagePresent(NULL
,&stack
[i
]))
322 DbgPrint("%.8x ",stack
[i
]);
333 if ((cs
&0xffff) == USER_CS
&&
336 DbgPrint("Killing current task\n");
338 KeLowerIrql(PASSIVE_LEVEL
);
339 if ((cs
&0xffff) == USER_CS
)
341 ZwTerminateProcess(NtCurrentProcess(),
342 STATUS_NONCONTINUABLE_EXCEPTION
);
348 VOID
KeDumpStackFrames(PVOID _Stack
, ULONG NrFrames
)
350 PULONG Stack
= (PULONG
)_Stack
;
353 Stack
= (PVOID
)(((ULONG
)Stack
) & (~0x3));
354 DbgPrint("Stack: %x\n", Stack
);
355 if (PsGetCurrentThread() != NULL
)
357 DbgPrint("kernel stack base %x\n",
358 PsGetCurrentThread()->Tcb
.Context
.KernelStackBase
);
361 DbgPrint("Frames:\n");
362 for (i
=0; i
<NrFrames
; i
++)
364 // if (Stack[i] > KERNEL_BASE && Stack[i] < ((ULONG)&etext))
365 if (Stack
[i
] > KERNEL_BASE
)
367 // DbgPrint("%.8x ",Stack[i]);
368 print_address((PVOID
)Stack
[i
]);
371 if (Stack
[i
] == 0xceafbeef)
379 static void set_system_call_gate(unsigned int sel
, unsigned int func
)
381 DPRINT("sel %x %d\n",sel
,sel
);
382 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
384 KiIdt
[sel
].b
= 0xef00 + (((int)func
)&0xffff0000);
385 DPRINT("idt[sel].b %x\n",KiIdt
[sel
].b
);
388 static void set_interrupt_gate(unsigned int sel
, unsigned int func
)
390 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel
,func
);
391 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
393 KiIdt
[sel
].b
= 0x8f00 + (((int)func
)&0xffff0000);
396 asmlinkage
unsigned int ExHookException(exception_hook fn
, unsigned int exp
)
398 * FUNCTION: Hook an exception
405 exception_hooks
[exp
]=fn
;
409 asmlinkage
void KeInitExceptions(void)
411 * FUNCTION: Initalize CPU exception handling
416 DPRINT("KeInitExceptions()\n",0);
418 set_interrupt_gate(0,(int)exception_handler0
);
419 set_interrupt_gate(1,(int)exception_handler1
);
420 set_interrupt_gate(2,(int)exception_handler2
);
421 set_interrupt_gate(3,(int)exception_handler3
);
422 set_interrupt_gate(4,(int)exception_handler4
);
423 set_interrupt_gate(5,(int)exception_handler5
);
424 set_interrupt_gate(6,(int)exception_handler6
);
425 set_interrupt_gate(7,(int)exception_handler7
);
426 set_interrupt_gate(8,(int)exception_handler8
);
427 set_interrupt_gate(9,(int)exception_handler9
);
428 set_interrupt_gate(10,(int)exception_handler10
);
429 set_interrupt_gate(11,(int)exception_handler11
);
430 set_interrupt_gate(12,(int)exception_handler12
);
431 set_interrupt_gate(13,(int)exception_handler13
);
432 set_interrupt_gate(14,(int)exception_handler14
);
433 set_interrupt_gate(15,(int)exception_handler15
);
434 set_interrupt_gate(16,(int)exception_handler16
);
438 set_interrupt_gate(i
,(int)exception_handler_unknown
);
441 set_system_call_gate(0x2d,(int)interrupt_handler2d
);
442 set_system_call_gate(0x2e,(int)interrupt_handler2e
);