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>
20 #include <internal/ps.h>
21 #include <internal/trap.h>
24 #include <internal/debug.h>
26 /* GLOBALS *****************************************************************/
29 #define STR(x) _STR(x)
31 extern void interrupt_handler2e(void);
32 extern void interrupt_handler2d(void);
34 extern void exception_handler0(void);
35 extern void exception_handler1(void);
36 extern void exception_handler2(void);
37 extern void exception_handler3(void);
38 extern void exception_handler4(void);
39 extern void exception_handler5(void);
40 extern void exception_handler6(void);
41 extern void exception_handler7(void);
42 extern void exception_handler8(void);
43 extern void exception_handler9(void);
44 extern void exception_handler10(void);
45 extern void exception_handler11(void);
46 extern void exception_handler12(void);
47 extern void exception_handler13(void);
48 extern void exception_handler14(void);
49 extern void exception_handler15(void);
50 extern void exception_handler16(void);
51 extern void exception_handler_unknown(void);
53 extern ULONG init_stack
;
54 extern ULONG init_stack_top
;
56 /* FUNCTIONS ****************************************************************/
58 extern unsigned int _text_start__
, _text_end__
;
61 print_address(PVOID address
)
63 PLIST_ENTRY current_entry
;
64 PMODULE_OBJECT current
;
65 extern LIST_ENTRY ModuleListHead
;
67 current_entry
= ModuleListHead
.Flink
;
69 while (current_entry
!= &ModuleListHead
&&
70 current_entry
!= NULL
)
72 current
= CONTAINING_RECORD(current_entry
, MODULE_OBJECT
, ListEntry
);
74 if (address
>= current
->Base
&&
75 address
< (current
->Base
+ current
->Length
))
77 DbgPrint("<%wZ: %x>", ¤t
->Name
,
78 address
- current
->Base
);
82 current_entry
= current_entry
->Flink
;
85 DbgPrint("<%x>", address
);
91 exception_handler(struct trap_frame
* tf
)
93 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
94 * message and halt the computer
96 * Complete CPU context
99 unsigned int cr2
, cr3
;
101 // unsigned int j, sym;
104 static char *TypeStrings
[] =
111 "BOUND range exceeded",
113 "No Math Coprocessor",
117 "Segment Not Present",
118 "Stack Segment Fault",
119 "General Protection",
126 __asm__("movl %%cr2,%0\n\t"
129 if (tf
->eflags
& (1 << 17))
131 return(KeV86Exception(tf
, cr2
));
134 if (PsGetCurrentThread() != NULL
&&
135 tf
->esp
< (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
)
137 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
138 tf
->esp
, (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
);
145 Status
= MmPageFault(tf
->cs
&0xffff,
150 if (NT_SUCCESS(Status
))
157 * FIXME: Something better
161 DbgPrint("Trap at CS:EIP %x:%x\n",tf
->cs
&0xffff,tf
->eip
);
166 * Print out the CPU registers
170 DbgPrint("%s Exception: %d(%x)\n",TypeStrings
[tf
->type
],tf
->type
,
171 tf
->error_code
&0xffff);
175 DbgPrint("Exception: %d(%x)\n",tf
->type
,tf
->error_code
&0xffff);
177 DbgPrint("CS:EIP %x:%x ",tf
->cs
&0xffff,tf
->eip
);
178 print_address((PVOID
)tf
->eip
);
180 __asm__("movl %%cr3,%0\n\t"
182 DbgPrint("cr2 %x cr3 %x ",cr2
,cr3
);
184 DbgPrint("Proc: %x ",PsGetCurrentProcess());
185 if (PsGetCurrentProcess() != NULL
)
187 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId
);
188 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName
);
190 if (PsGetCurrentThread() != NULL
)
192 DbgPrint("Thrd: %x Tid: %x",
193 PsGetCurrentThread(),
194 PsGetCurrentThread()->Cid
.UniqueThread
);
197 DbgPrint("DS %x ES %x FS %x GS %x\n", tf
->ds
&0xffff, tf
->es
&0xffff,
198 tf
->fs
&0xffff, tf
->gs
&0xfff);
199 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", tf
->eax
, tf
->ebx
, tf
->ecx
);
200 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", tf
->edx
, tf
->ebp
, tf
->esi
);
201 DbgPrint("EDI: %.8x EFLAGS: %.8x ", tf
->edi
, tf
->eflags
);
202 if ((tf
->cs
&0xffff) == KERNEL_CS
)
204 DbgPrint("kESP %.8x ", tf
->esp
);
205 if (PsGetCurrentThread() != NULL
)
207 DbgPrint("kernel stack base %x\n",
208 PsGetCurrentThread()->Tcb
.StackLimit
);
214 DbgPrint("kernel ESP %.8x\n", tf
->esp
);
216 if ((tf
->cs
& 0xffff) == KERNEL_CS
)
218 DbgPrint("ESP %x\n", tf
->esp
);
219 stack
= (PULONG
) (tf
->esp
+ 24);
220 stack
= (PULONG
)(((ULONG
)stack
) & (~0x3));
222 DbgPrint("stack<%p>: ", stack
);
224 for (i
= 0; i
< 18; i
= i
+ 6)
226 DbgPrint("%.8x %.8x %.8x %.8x\n",
227 stack
[i
], stack
[i
+1],
228 stack
[i
+2], stack
[i
+3],
229 stack
[i
+4], stack
[i
+5]);
231 DbgPrint("Frames:\n");
232 for (i
= 0; i
< 32; i
++)
234 if (stack
[i
] > ((unsigned int) &_text_start__
) &&
235 !(stack
[i
] >= ((ULONG
)&init_stack
) &&
236 stack
[i
] <= ((ULONG
)&init_stack_top
)))
238 // DbgPrint(" %.8x", stack[i]);
239 print_address((PVOID
)stack
[i
]);
247 DbgPrint("SS:ESP %x:%x\n", tf
->ss0
, tf
->esp0
);
248 stack
=(PULONG
)(tf
->esp0
);
250 DbgPrint("Stack:\n");
253 if (MmIsPagePresent(NULL
,&stack
[i
]))
255 DbgPrint("%.8x ",stack
[i
]);
263 if (MmIsPagePresent(NULL
, (PVOID
)tf
->eip
))
265 unsigned char instrs
[512];
267 memcpy(instrs
, (PVOID
)tf
->eip
, 512);
269 DbgPrint("Instrs: ");
273 DbgPrint("%x ", instrs
[i
]);
280 if ((tf
->cs
&0xffff) == USER_CS
&&
281 tf
->eip
< KERNEL_BASE
)
283 DbgPrint("Killing current task\n");
285 KeLowerIrql(PASSIVE_LEVEL
);
286 if ((tf
->cs
&0xffff) == USER_CS
)
288 ZwTerminateProcess(NtCurrentProcess(),
289 STATUS_NONCONTINUABLE_EXCEPTION
);
295 VOID
KeDumpStackFrames(PVOID _Stack
, ULONG NrFrames
)
297 PULONG Stack
= (PULONG
)_Stack
;
300 Stack
= (PVOID
)(((ULONG
)Stack
) & (~0x3));
301 DbgPrint("Stack: %x\n", Stack
);
302 if (PsGetCurrentThread() != NULL
)
304 DbgPrint("kernel stack base %x\n",
305 PsGetCurrentThread()->Tcb
.StackLimit
);
308 DbgPrint("Frames:\n");
309 for (i
=0; i
<NrFrames
; i
++)
311 // if (Stack[i] > KERNEL_BASE && Stack[i] < ((ULONG)&etext))
312 if (Stack
[i
] > KERNEL_BASE
)
314 // DbgPrint("%.8x ",Stack[i]);
315 print_address((PVOID
)Stack
[i
]);
318 if (Stack
[i
] == 0xceafbeef)
326 static void set_system_call_gate(unsigned int sel
, unsigned int func
)
328 DPRINT("sel %x %d\n",sel
,sel
);
329 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
331 KiIdt
[sel
].b
= 0xef00 + (((int)func
)&0xffff0000);
332 DPRINT("idt[sel].b %x\n",KiIdt
[sel
].b
);
335 static void set_interrupt_gate(unsigned int sel
, unsigned int func
)
337 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel
,func
);
338 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
340 KiIdt
[sel
].b
= 0x8f00 + (((int)func
)&0xffff0000);
343 void KeInitExceptions(void)
345 * FUNCTION: Initalize CPU exception handling
350 DPRINT("KeInitExceptions()\n",0);
352 set_interrupt_gate(0,(int)exception_handler0
);
353 set_interrupt_gate(1,(int)exception_handler1
);
354 set_interrupt_gate(2,(int)exception_handler2
);
355 set_interrupt_gate(3,(int)exception_handler3
);
356 set_interrupt_gate(4,(int)exception_handler4
);
357 set_interrupt_gate(5,(int)exception_handler5
);
358 set_interrupt_gate(6,(int)exception_handler6
);
359 set_interrupt_gate(7,(int)exception_handler7
);
360 set_interrupt_gate(8,(int)exception_handler8
);
361 set_interrupt_gate(9,(int)exception_handler9
);
362 set_interrupt_gate(10,(int)exception_handler10
);
363 set_interrupt_gate(11,(int)exception_handler11
);
364 set_interrupt_gate(12,(int)exception_handler12
);
365 set_interrupt_gate(13,(int)exception_handler13
);
366 set_interrupt_gate(14,(int)exception_handler14
);
367 set_interrupt_gate(15,(int)exception_handler15
);
368 set_interrupt_gate(16,(int)exception_handler16
);
372 set_interrupt_gate(i
,(int)exception_handler_unknown
);
375 set_system_call_gate(0x2d,(int)interrupt_handler2d
);
376 set_system_call_gate(0x2e,(int)interrupt_handler2e
);