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/symbol.h>
17 #include <internal/i386/segment.h>
18 #include <internal/mmhal.h>
19 #include <internal/module.h>
20 #include <internal/mm.h>
23 #include <internal/debug.h>
25 /* GLOBALS *****************************************************************/
27 static exception_hook
* exception_hooks
[256]={NULL
,};
30 #define STR(x) _STR(x)
32 extern void interrupt_handler2e(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("<%w: %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\n", PsGetCurrentProcess()->UniqueProcessId
);
256 if (PsGetCurrentThread() != NULL
)
258 DbgPrint("Thread: %x Thread id: %x\n",
259 PsGetCurrentThread(),
260 PsGetCurrentThread()->Cid
.UniqueThread
);
262 DbgPrint("DS %x ES %x FS %x GS %x\n",ds
&0xffff,es
&0xffff,fs
&0xffff,
264 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n",eax
,ebx
,ecx
);
265 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n",edx
,ebp
,esi
);
266 DbgPrint("EDI: %.8x EFLAGS: %.8x ",edi
,eflags
);
267 if ((cs
&0xffff) == KERNEL_CS
)
269 DbgPrint("kESP %.8x\n",esp
);
270 if (PsGetCurrentThread() != NULL
)
272 DbgPrint("kernel stack base %x\n",
273 PsGetCurrentThread()->Tcb
.Context
.KernelStackBase
);
279 DbgPrint("kernel ESP %.8x\n",esp
);
281 if ((cs
& 0xffff) == KERNEL_CS
)
283 DbgPrint("ESP %x\n",esp
);
284 stack
= (unsigned int *) (esp
+ 24);
286 DbgPrint("Stack:\n");
287 for (i
= 0; i
< 16; i
= i
+ 4)
289 DbgPrint("%.8x %.8x %.8x %.8x\n",
295 DbgPrint("Frames:\n");
296 for (i
= 0; i
< 32; i
++)
298 if (stack
[i
] > ((unsigned int) &stext
) &&
299 !(stack
[i
] >= ((ULONG
)&init_stack
) &&
300 stack
[i
] <= ((ULONG
)&init_stack_top
)))
302 // DbgPrint(" %.8x", stack[i]);
303 print_address((PVOID
)stack
[i
]);
310 DbgPrint("SS:ESP %x:%x\n",ss0
,esp0
);
311 stack
=(unsigned int *)(esp0
);
313 DbgPrint("Stack:\n");
316 if (MmIsPagePresent(NULL
,&stack
[i
]))
318 DbgPrint("%.8x ",stack
[i
]);
328 DbgPrint("Killing current task\n");
330 KeLowerIrql(PASSIVE_LEVEL
);
331 if ((cs
&0xffff) == USER_CS
)
333 ZwTerminateProcess(NtCurrentProcess(),
334 STATUS_NONCONTINUABLE_EXCEPTION
);
340 VOID
KeDumpStackFrames(PVOID _Stack
, ULONG NrFrames
)
342 PULONG Stack
= (PULONG
)_Stack
;
345 Stack
= (PVOID
)(((ULONG
)Stack
) & (~0x3));
346 DbgPrint("Stack: %x\n", Stack
);
348 DbgPrint("Frames:\n");
349 for (i
=0; i
<NrFrames
; i
++)
351 // if (Stack[i] > KERNEL_BASE && Stack[i] < ((ULONG)&etext))
352 if (Stack
[i
] > KERNEL_BASE
)
354 // DbgPrint("%.8x ",Stack[i]);
355 print_address((PVOID
)Stack
[i
]);
358 if (Stack
[i
] == 0xceafbeef)
366 static void set_system_call_gate(unsigned int sel
, unsigned int func
)
368 DPRINT("sel %x %d\n",sel
,sel
);
369 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
371 KiIdt
[sel
].b
= 0xef00 + (((int)func
)&0xffff0000);
372 DPRINT("idt[sel].b %x\n",KiIdt
[sel
].b
);
375 static void set_interrupt_gate(unsigned int sel
, unsigned int func
)
377 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel
,func
);
378 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
380 KiIdt
[sel
].b
= 0x8f00 + (((int)func
)&0xffff0000);
383 asmlinkage
unsigned int ExHookException(exception_hook fn
, unsigned int exp
)
385 * FUNCTION: Hook an exception
392 exception_hooks
[exp
]=fn
;
396 asmlinkage
void KeInitExceptions(void)
398 * FUNCTION: Initalize CPU exception handling
403 DPRINT("KeInitExceptions()\n",0);
405 set_interrupt_gate(0,(int)exception_handler0
);
406 set_interrupt_gate(1,(int)exception_handler1
);
407 set_interrupt_gate(2,(int)exception_handler2
);
408 set_interrupt_gate(3,(int)exception_handler3
);
409 set_interrupt_gate(4,(int)exception_handler4
);
410 set_interrupt_gate(5,(int)exception_handler5
);
411 set_interrupt_gate(6,(int)exception_handler6
);
412 set_interrupt_gate(7,(int)exception_handler7
);
413 set_interrupt_gate(8,(int)exception_handler8
);
414 set_interrupt_gate(9,(int)exception_handler9
);
415 set_interrupt_gate(10,(int)exception_handler10
);
416 set_interrupt_gate(11,(int)exception_handler11
);
417 set_interrupt_gate(12,(int)exception_handler12
);
418 set_interrupt_gate(13,(int)exception_handler13
);
419 set_interrupt_gate(14,(int)exception_handler14
);
420 set_interrupt_gate(15,(int)exception_handler15
);
421 set_interrupt_gate(16,(int)exception_handler16
);
425 set_interrupt_gate(i
,(int)exception_handler_unknown
);
428 set_system_call_gate(0x2e,(int)interrupt_handler2e
);