3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/i386/exp.c
22 * PURPOSE: Handling exceptions
23 * PROGRAMMER: David Welch (welch@cwcom.net)
28 /* INCLUDES *****************************************************************/
30 #include <ddk/ntddk.h>
32 #include <internal/ntoskrnl.h>
33 #include <internal/ke.h>
34 #include <internal/i386/segment.h>
35 #include <internal/i386/mm.h>
36 #include <internal/module.h>
37 #include <internal/mm.h>
38 #include <internal/ps.h>
39 #include <internal/trap.h>
40 #include <ntdll/ldr.h>
41 #include <internal/safe.h>
42 #include <internal/kd.h>
45 #include <internal/debug.h>
47 /* GLOBALS *****************************************************************/
49 #define FLAG_IF (1<<9)
52 #define STR(x) _STR(x)
54 extern void interrupt_handler2e(void);
55 extern void interrupt_handler2d(void);
57 extern VOID KiTrap0(VOID);
58 extern VOID KiTrap1(VOID);
59 extern VOID KiTrap2(VOID);
60 extern VOID KiTrap3(VOID);
61 extern VOID KiTrap4(VOID);
62 extern VOID KiTrap5(VOID);
63 extern VOID KiTrap6(VOID);
64 extern VOID KiTrap7(VOID);
65 extern VOID KiTrap8(VOID);
66 extern VOID KiTrap9(VOID);
67 extern VOID KiTrap10(VOID);
68 extern VOID KiTrap11(VOID);
69 extern VOID KiTrap12(VOID);
70 extern VOID KiTrap13(VOID);
71 extern VOID KiTrap14(VOID);
72 extern VOID KiTrap15(VOID);
73 extern VOID KiTrap16(VOID);
74 extern VOID KiTrapUnknown(VOID);
76 extern ULONG init_stack;
77 extern ULONG init_stack_top;
79 static char *ExceptionTypeStrings[] =
86 "BOUND range exceeded",
88 "No Math Coprocessor",
92 "Segment Not Present",
93 "Stack Segment Fault",
101 static NTSTATUS ExceptionToNtStatus[] =
103 STATUS_INTEGER_DIVIDE_BY_ZERO,
105 STATUS_ACCESS_VIOLATION,
107 STATUS_INTEGER_OVERFLOW,
108 STATUS_ARRAY_BOUNDS_EXCEEDED,
109 STATUS_ILLEGAL_INSTRUCTION,
110 STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
111 STATUS_ACCESS_VIOLATION,
112 STATUS_ACCESS_VIOLATION,
113 STATUS_ACCESS_VIOLATION,
114 STATUS_ACCESS_VIOLATION,
115 STATUS_STACK_OVERFLOW,
116 STATUS_ACCESS_VIOLATION,
117 STATUS_ACCESS_VIOLATION,
118 STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
119 STATUS_DATATYPE_MISALIGNMENT,
120 STATUS_ACCESS_VIOLATION
123 extern unsigned int _text_start__, _text_end__;
125 /* FUNCTIONS ****************************************************************/
128 print_address(PVOID address)
130 PLIST_ENTRY current_entry;
131 MODULE_TEXT_SECTION* current;
132 extern LIST_ENTRY ModuleTextListHead;
133 ULONG_PTR RelativeAddress;
135 current_entry = ModuleTextListHead.Flink;
137 while (current_entry != &ModuleTextListHead &&
138 current_entry != NULL)
141 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
143 if (address >= (PVOID)current->Base &&
144 address < (PVOID)(current->Base + current->Length))
146 RelativeAddress = (ULONG_PTR) address - current->Base;
147 DbgPrint("<%ws: %x>", current->Name, RelativeAddress);
150 current_entry = current_entry->Flink;
156 KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
160 Er.ExceptionFlags = 0;
161 Er.ExceptionRecord = NULL;
162 Er.ExceptionAddress = (PVOID)Tf->Eip;
164 if (ExceptionNr == 14)
166 Er.NumberParameters = 2;
167 Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
168 Er.ExceptionInformation[1] = (ULONG)Cr2;
172 if (ExceptionNr < 16)
174 Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
178 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
180 Er.NumberParameters = 0;
183 KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
189 KiDoubleFaultHandler(VOID)
195 ULONG ExceptionNr = 8;
201 static PVOID StackTrace[MM_STACK_SIZE / sizeof(PVOID)];
202 static ULONG StackRepeatCount[MM_STACK_SIZE / sizeof(PVOID)];
203 static ULONG StackRepeatLength[MM_STACK_SIZE / sizeof(PVOID)];
208 OldTss = KeGetCurrentKPCR()->TSS;
212 __asm__("movl %%cr2,%0\n\t" : "=d" (cr2));
214 if (PsGetCurrentThread() != NULL &&
215 PsGetCurrentThread()->ThreadsProcess != NULL)
218 PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart;
226 * Check for stack underflow
228 if (PsGetCurrentThread() != NULL &&
229 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
231 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
232 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
237 * Print out the CPU registers
239 if (ExceptionNr < 19)
241 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
246 DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
248 DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
249 print_address((PVOID)OldTss->Eip);
251 DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
252 DbgPrint("Proc: %x ",PsGetCurrentProcess());
253 if (PsGetCurrentProcess() != NULL)
255 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
256 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
258 if (PsGetCurrentThread() != NULL)
260 DbgPrint("Thrd: %x Tid: %x",
261 PsGetCurrentThread(),
262 PsGetCurrentThread()->Cid.UniqueThread);
265 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es,
266 OldTss->Fs, OldTss->Gs);
267 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
269 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", OldTss->Edx, OldTss->Ebp,
271 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
272 if (OldTss->Cs == KERNEL_CS)
274 DbgPrint("kESP %.8x ", Esp0);
275 if (PsGetCurrentThread() != NULL)
277 DbgPrint("kernel stack base %x\n",
278 PsGetCurrentThread()->Tcb.StackLimit);
284 DbgPrint("User ESP %.8x\n", OldTss->Esp);
286 if ((OldTss->Cs & 0xffff) == KERNEL_CS)
288 DbgPrint("ESP %x\n", Esp0);
289 if (PsGetCurrentThread() != NULL)
291 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
292 StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit;
296 StackLimit = (ULONG)&init_stack_top;
297 StackBase = (ULONG)&init_stack;
301 DbgPrint("Frames: ");
302 Frame = (PULONG)OldTss->Ebp;
303 while (Frame != NULL && (ULONG)Frame >= StackBase)
305 print_address((PVOID)Frame[1]);
306 Frame = (PULONG)Frame[0];
310 DbgPrint("Frames: ");
312 Frame = (PULONG)OldTss->Ebp;
313 while (Frame != NULL && (ULONG)Frame >= StackBase)
315 StackTrace[i] = (PVOID)Frame[1];
316 Frame = (PULONG)Frame[0];
322 while (i < TraceLength)
324 StackRepeatCount[i] = 0;
327 while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE)
329 if (memcmp(&StackTrace[i], &StackTrace[j],
330 (j - i) * sizeof(PVOID)) == 0)
332 StackRepeatCount[i] = 2;
333 StackRepeatLength[i] = j - i;
341 if (FoundRepeat == FALSE)
346 j = j + StackRepeatLength[i];
347 while ((TraceLength - j) >= StackRepeatLength[i] &&
350 if (memcmp(&StackTrace[i], &StackTrace[j],
351 StackRepeatLength[i] * sizeof(PVOID)) == 0)
353 StackRepeatCount[i]++;
354 j = j + StackRepeatLength[i];
365 while (i < TraceLength)
367 if (StackRepeatCount[i] == 0)
369 print_address(StackTrace[i]);
375 if (StackRepeatLength[i] == 0)
379 for (j = 0; j < StackRepeatLength[i]; j++)
381 print_address(StackTrace[i + j]);
383 DbgPrint("}*%d", StackRepeatCount[i]);
384 i = i + StackRepeatLength[i] * StackRepeatCount[i];
395 KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
402 ULONG ExceptionNr = (ULONG)Tf->DebugArgMark;
403 ULONG cr2 = (ULONG)Tf->DebugPointer;
408 * Print out the CPU registers
410 if (ExceptionNr < 19)
412 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
413 ExceptionNr, Tf->ErrorCode&0xffff);
417 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
419 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
420 Tf->Cs&0xffff, Tf->Eip);
421 print_address((PVOID)Tf->Eip);
423 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
424 DbgPrint("cr2 %x cr3 %x ", cr2, cr3);
425 DbgPrint("Proc: %x ",PsGetCurrentProcess());
426 if (PsGetCurrentProcess() != NULL)
428 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
429 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
431 if (PsGetCurrentThread() != NULL)
433 DbgPrint("Thrd: %x Tid: %x",
434 PsGetCurrentThread(),
435 PsGetCurrentThread()->Cid.UniqueThread);
438 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
439 Tf->Fs&0xffff, Tf->Gs&0xfff);
440 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
441 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf->Edx, Tf->Ebp, Tf->Esi);
442 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
443 if ((Tf->Cs&0xffff) == KERNEL_CS)
445 DbgPrint("kESP %.8x ", Esp0);
446 if (PsGetCurrentThread() != NULL)
448 DbgPrint("kernel stack base %x\n",
449 PsGetCurrentThread()->Tcb.StackLimit);
454 DbgPrint("ESP %x\n", Esp0);
456 if (PsGetCurrentThread() != NULL)
458 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
462 StackLimit = (ULONG)&init_stack_top;
466 * Dump the stack frames
468 DbgPrint("Frames: ");
470 Frame = (PULONG)Tf->Ebp;
471 while (Frame != NULL)
473 print_address((PVOID)Frame[1]);
474 Frame = (PULONG)Frame[0];
481 KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
483 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
484 * message and halt the computer
486 * Complete CPU context
493 /* Store the exception number in an unused field in the trap frame. */
494 Tf->DebugArgMark = (PVOID)ExceptionNr;
496 /* Use the address of the trap frame as approximation to the ring0 esp */
497 Esp0 = (ULONG)&Tf->Eip;
500 __asm__("movl %%cr2,%0\n\t" : "=d" (cr2));
501 Tf->DebugPointer = (PVOID)cr2;
504 * If this was a V86 mode exception then handle it specially
506 if (Tf->Eflags & (1 << 17))
508 return(KeV86Exception(ExceptionNr, Tf, cr2));
512 * Check for stack underflow, this may be obsolete
514 if (PsGetCurrentThread() != NULL &&
515 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
517 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
518 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
523 * Maybe handle the page fault and return
525 if (ExceptionNr == 14)
527 if (Tf->Eflags & FLAG_IF)
531 Status = MmPageFault(Tf->Cs&0xffff,
536 if (NT_SUCCESS(Status))
544 * Handle user exceptions differently
546 if ((Tf->Cs & 0xFFFF) == USER_CS)
548 return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
552 return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
557 KeDumpStackFrames(PULONG Frame)
561 DbgPrint("Frames: ");
563 while (Frame != NULL)
565 print_address((PVOID)Frame[1]);
566 Frame = (PULONG)Frame[0];
572 static void set_system_call_gate(unsigned int sel, unsigned int func)
574 DPRINT("sel %x %d\n",sel,sel);
575 KiIdt[sel].a = (((int)func)&0xffff) +
577 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
578 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
581 static void set_interrupt_gate(unsigned int sel, unsigned int func)
583 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
584 KiIdt[sel].a = (((int)func)&0xffff) +
586 KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
589 static void set_trap_gate(unsigned int sel, unsigned int func)
591 DPRINT("set_trap_gate(sel %d, func %x)\n",sel,func);
592 KiIdt[sel].a = (((int)func)&0xffff) +
594 KiIdt[sel].b = 0x8f00 + (((int)func)&0xffff0000);
598 set_task_gate(unsigned int sel, unsigned task_sel)
600 KiIdt[sel].a = task_sel << 16;
601 KiIdt[sel].b = 0x8500;
605 KeInitExceptions(VOID)
607 * FUNCTION: Initalize CPU exception handling
612 DPRINT("KeInitExceptions()\n");
615 * Set up the other gates
617 set_trap_gate(0, (ULONG)KiTrap0);
618 set_trap_gate(1, (ULONG)KiTrap1);
619 set_trap_gate(2, (ULONG)KiTrap2);
620 set_trap_gate(3, (ULONG)KiTrap3);
621 set_trap_gate(4, (ULONG)KiTrap4);
622 set_trap_gate(5, (ULONG)KiTrap5);
623 set_trap_gate(6, (ULONG)KiTrap6);
624 set_trap_gate(7, (ULONG)KiTrap7);
625 set_task_gate(8, TRAP_TSS_SELECTOR);
626 set_trap_gate(9, (ULONG)KiTrap9);
627 set_trap_gate(10, (ULONG)KiTrap10);
628 set_trap_gate(11, (ULONG)KiTrap11);
629 set_trap_gate(12, (ULONG)KiTrap12);
630 set_trap_gate(13, (ULONG)KiTrap13);
631 set_trap_gate(14, (ULONG)KiTrap14);
632 set_interrupt_gate(14, (ULONG)KiTrap14);
633 set_trap_gate(15, (ULONG)KiTrap15);
634 set_trap_gate(16, (ULONG)KiTrap16);
638 set_trap_gate(i,(int)KiTrapUnknown);
641 set_system_call_gate(0x2d,(int)interrupt_handler2d);
642 set_system_call_gate(0x2e,(int)interrupt_handler2e);