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__
;
60 static void print_address(PVOID address
)
62 PLIST_ENTRY current_entry
;
63 PMODULE_OBJECT current
;
64 extern LIST_ENTRY ModuleListHead
;
66 current_entry
= ModuleListHead
.Flink
;
68 while (current_entry
!= &ModuleListHead
&&
69 current_entry
!= NULL
)
71 current
= CONTAINING_RECORD(current_entry
, MODULE_OBJECT
, ListEntry
);
73 if (address
>= current
->Base
&&
74 address
< (current
->Base
+ current
->Length
))
76 DbgPrint("<%wZ: %x>", ¤t
->Name
,
77 address
- current
->Base
);
81 current_entry
= current_entry
->Flink
;
83 DbgPrint("<%x>", address
);
87 exception_handler(struct trap_frame
* tf
)
89 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
90 * message and halt the computer
92 * Complete CPU context
95 unsigned int cr2
, cr3
;
97 // unsigned int j, sym;
100 static char *TypeStrings
[] =
107 "BOUND range exceeded",
109 "No Math Coprocessor",
113 "Segment Not Present",
114 "Stack Segment Fault",
115 "General Protection",
122 __asm__("movl %%cr2,%0\n\t"
125 if (tf
->eflags
& (1 << 17))
127 return(KeV86Exception(tf
, cr2
));
130 if (PsGetCurrentThread() != NULL
&&
131 tf
->esp
< (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
)
133 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
134 tf
->esp
, (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
);
141 Status
= MmPageFault(tf
->cs
&0xffff,
146 if (NT_SUCCESS(Status
))
153 * FIXME: Something better
157 DbgPrint("Trap at CS:EIP %x:%x\n",tf
->cs
&0xffff,tf
->eip
);
162 * Print out the CPU registers
166 DbgPrint("%s Exception: %d(%x)\n",TypeStrings
[tf
->type
],tf
->type
,
167 tf
->error_code
&0xffff);
171 DbgPrint("Exception: %d(%x)\n",tf
->type
,tf
->error_code
&0xffff);
173 DbgPrint("CS:EIP %x:%x ",tf
->cs
&0xffff,tf
->eip
);
174 print_address((PVOID
)tf
->eip
);
176 __asm__("movl %%cr3,%0\n\t"
178 DbgPrint("cr2 %x cr3 %x ",cr2
,cr3
);
180 DbgPrint("Proc: %x ",PsGetCurrentProcess());
181 if (PsGetCurrentProcess() != NULL
)
183 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId
);
184 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName
);
186 if (PsGetCurrentThread() != NULL
)
188 DbgPrint("Thrd: %x Tid: %x",
189 PsGetCurrentThread(),
190 PsGetCurrentThread()->Cid
.UniqueThread
);
193 DbgPrint("DS %x ES %x FS %x GS %x\n", tf
->ds
&0xffff, tf
->es
&0xffff,
194 tf
->fs
&0xffff, tf
->gs
&0xfff);
195 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", tf
->eax
, tf
->ebx
, tf
->ecx
);
196 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", tf
->edx
, tf
->ebp
, tf
->esi
);
197 DbgPrint("EDI: %.8x EFLAGS: %.8x ", tf
->edi
, tf
->eflags
);
198 if ((tf
->cs
&0xffff) == KERNEL_CS
)
200 DbgPrint("kESP %.8x ", tf
->esp
);
201 if (PsGetCurrentThread() != NULL
)
203 DbgPrint("kernel stack base %x\n",
204 PsGetCurrentThread()->Tcb
.StackLimit
);
210 DbgPrint("kernel ESP %.8x\n", tf
->esp
);
212 if ((tf
->cs
& 0xffff) == KERNEL_CS
)
214 DbgPrint("ESP %x\n", tf
->esp
);
215 stack
= (PULONG
) (tf
->esp
+ 24);
216 stack
= (PULONG
)(((ULONG
)stack
) & (~0x3));
218 DbgPrint("stack<%p>: ", stack
);
220 for (i
= 0; i
< 18; i
= i
+ 6)
222 DbgPrint("%.8x %.8x %.8x %.8x\n",
223 stack
[i
], stack
[i
+1],
224 stack
[i
+2], stack
[i
+3],
225 stack
[i
+4], stack
[i
+5]);
227 DbgPrint("Frames:\n");
228 for (i
= 0; i
< 32; i
++)
230 if (stack
[i
] > ((unsigned int) &_text_start__
) &&
231 !(stack
[i
] >= ((ULONG
)&init_stack
) &&
232 stack
[i
] <= ((ULONG
)&init_stack_top
)))
234 // DbgPrint(" %.8x", stack[i]);
235 print_address((PVOID
)stack
[i
]);
243 DbgPrint("SS:ESP %x:%x\n", tf
->ss0
, tf
->esp0
);
244 stack
=(PULONG
)(tf
->esp0
);
246 DbgPrint("Stack:\n");
249 if (MmIsPagePresent(NULL
,&stack
[i
]))
251 DbgPrint("%.8x ",stack
[i
]);
259 if (MmIsPagePresent(NULL
, (PVOID
)tf
->eip
))
261 unsigned char instrs
[512];
263 memcpy(instrs
, (PVOID
)tf
->eip
, 512);
265 DbgPrint("Instrs: ");
269 DbgPrint("%x ", instrs
[i
]);
276 if ((tf
->cs
&0xffff) == USER_CS
&&
277 tf
->eip
< KERNEL_BASE
)
279 DbgPrint("Killing current task\n");
281 KeLowerIrql(PASSIVE_LEVEL
);
282 if ((tf
->cs
&0xffff) == USER_CS
)
284 ZwTerminateProcess(NtCurrentProcess(),
285 STATUS_NONCONTINUABLE_EXCEPTION
);
291 VOID
KeDumpStackFrames(PVOID _Stack
, ULONG NrFrames
)
293 PULONG Stack
= (PULONG
)_Stack
;
296 Stack
= (PVOID
)(((ULONG
)Stack
) & (~0x3));
297 DbgPrint("Stack: %x\n", Stack
);
298 if (PsGetCurrentThread() != NULL
)
300 DbgPrint("kernel stack base %x\n",
301 PsGetCurrentThread()->Tcb
.StackLimit
);
304 DbgPrint("Frames:\n");
305 for (i
=0; i
<NrFrames
; i
++)
307 // if (Stack[i] > KERNEL_BASE && Stack[i] < ((ULONG)&etext))
308 if (Stack
[i
] > KERNEL_BASE
)
310 // DbgPrint("%.8x ",Stack[i]);
311 print_address((PVOID
)Stack
[i
]);
314 if (Stack
[i
] == 0xceafbeef)
322 static void set_system_call_gate(unsigned int sel
, unsigned int func
)
324 DPRINT("sel %x %d\n",sel
,sel
);
325 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
327 KiIdt
[sel
].b
= 0xef00 + (((int)func
)&0xffff0000);
328 DPRINT("idt[sel].b %x\n",KiIdt
[sel
].b
);
331 static void set_interrupt_gate(unsigned int sel
, unsigned int func
)
333 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel
,func
);
334 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
336 KiIdt
[sel
].b
= 0x8f00 + (((int)func
)&0xffff0000);
339 void KeInitExceptions(void)
341 * FUNCTION: Initalize CPU exception handling
346 DPRINT("KeInitExceptions()\n",0);
348 set_interrupt_gate(0,(int)exception_handler0
);
349 set_interrupt_gate(1,(int)exception_handler1
);
350 set_interrupt_gate(2,(int)exception_handler2
);
351 set_interrupt_gate(3,(int)exception_handler3
);
352 set_interrupt_gate(4,(int)exception_handler4
);
353 set_interrupt_gate(5,(int)exception_handler5
);
354 set_interrupt_gate(6,(int)exception_handler6
);
355 set_interrupt_gate(7,(int)exception_handler7
);
356 set_interrupt_gate(8,(int)exception_handler8
);
357 set_interrupt_gate(9,(int)exception_handler9
);
358 set_interrupt_gate(10,(int)exception_handler10
);
359 set_interrupt_gate(11,(int)exception_handler11
);
360 set_interrupt_gate(12,(int)exception_handler12
);
361 set_interrupt_gate(13,(int)exception_handler13
);
362 set_interrupt_gate(14,(int)exception_handler14
);
363 set_interrupt_gate(15,(int)exception_handler15
);
364 set_interrupt_gate(16,(int)exception_handler16
);
368 set_interrupt_gate(i
,(int)exception_handler_unknown
);
371 set_system_call_gate(0x2d,(int)interrupt_handler2d
);
372 set_system_call_gate(0x2e,(int)interrupt_handler2e
);