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 *****************************************************************/
50 #define STR(x) _STR(x)
52 extern void interrupt_handler2e(void);
53 extern void interrupt_handler2d(void);
55 extern VOID KiTrap0(VOID);
56 extern VOID KiTrap1(VOID);
57 extern VOID KiTrap2(VOID);
58 extern VOID KiTrap3(VOID);
59 extern VOID KiTrap4(VOID);
60 extern VOID KiTrap5(VOID);
61 extern VOID KiTrap6(VOID);
62 extern VOID KiTrap7(VOID);
63 extern VOID KiTrap8(VOID);
64 extern VOID KiTrap9(VOID);
65 extern VOID KiTrap10(VOID);
66 extern VOID KiTrap11(VOID);
67 extern VOID KiTrap12(VOID);
68 extern VOID KiTrap13(VOID);
69 extern VOID KiTrap14(VOID);
70 extern VOID KiTrap15(VOID);
71 extern VOID KiTrap16(VOID);
72 extern VOID KiTrapUnknown(VOID);
74 extern ULONG init_stack;
75 extern ULONG init_stack_top;
77 static char *ExceptionTypeStrings[] =
84 "BOUND range exceeded",
86 "No Math Coprocessor",
90 "Segment Not Present",
91 "Stack Segment Fault",
99 static NTSTATUS ExceptionToNtStatus[] =
101 STATUS_INTEGER_DIVIDE_BY_ZERO,
103 STATUS_ACCESS_VIOLATION,
105 STATUS_INTEGER_OVERFLOW,
106 STATUS_ARRAY_BOUNDS_EXCEEDED,
107 STATUS_ILLEGAL_INSTRUCTION,
108 STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
109 STATUS_ACCESS_VIOLATION,
110 STATUS_ACCESS_VIOLATION,
111 STATUS_ACCESS_VIOLATION,
112 STATUS_ACCESS_VIOLATION,
113 STATUS_STACK_OVERFLOW,
114 STATUS_ACCESS_VIOLATION,
115 STATUS_ACCESS_VIOLATION,
116 STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
117 STATUS_DATATYPE_MISALIGNMENT,
118 STATUS_ACCESS_VIOLATION
121 extern unsigned int _text_start__, _text_end__;
123 /* FUNCTIONS ****************************************************************/
126 print_address(PVOID address)
128 PLIST_ENTRY current_entry;
129 MODULE_TEXT_SECTION* current;
130 extern LIST_ENTRY ModuleTextListHead;
131 ULONG_PTR RelativeAddress;
133 current_entry = ModuleTextListHead.Flink;
135 while (current_entry != &ModuleTextListHead &&
136 current_entry != NULL)
139 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
141 if (address >= (PVOID)current->Base &&
142 address < (PVOID)(current->Base + current->Length))
144 RelativeAddress = (ULONG_PTR) address - current->Base;
145 DbgPrint("<%ws: %x>", current->Name, RelativeAddress);
148 current_entry = current_entry->Flink;
154 KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
158 Er.ExceptionFlags = 0;
159 Er.ExceptionRecord = NULL;
160 Er.ExceptionAddress = (PVOID)Tf->Eip;
162 if (ExceptionNr == 14)
164 Er.NumberParameters = 2;
165 Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
166 Er.ExceptionInformation[1] = (ULONG)Cr2;
170 if (ExceptionNr < 16)
172 Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
176 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
178 Er.NumberParameters = 0;
181 KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
187 KiDoubleFaultHandler(VOID)
193 ULONG ExceptionNr = 8;
199 static PVOID StackTrace[MM_STACK_SIZE / sizeof(PVOID)];
200 static ULONG StackRepeatCount[MM_STACK_SIZE / sizeof(PVOID)];
201 static ULONG StackRepeatLength[MM_STACK_SIZE / sizeof(PVOID)];
206 OldTss = KeGetCurrentKPCR()->TSS;
210 __asm__("movl %%cr2,%0\n\t" : "=d" (cr2));
212 if (PsGetCurrentThread() != NULL &&
213 PsGetCurrentThread()->ThreadsProcess != NULL)
216 PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart;
224 * Check for stack underflow
226 if (PsGetCurrentThread() != NULL &&
227 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
229 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
230 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
235 * Print out the CPU registers
237 if (ExceptionNr < 19)
239 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
244 DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
246 DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
247 print_address((PVOID)OldTss->Eip);
249 DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
250 DbgPrint("Proc: %x ",PsGetCurrentProcess());
251 if (PsGetCurrentProcess() != NULL)
253 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
254 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
256 if (PsGetCurrentThread() != NULL)
258 DbgPrint("Thrd: %x Tid: %x",
259 PsGetCurrentThread(),
260 PsGetCurrentThread()->Cid.UniqueThread);
263 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es,
264 OldTss->Fs, OldTss->Gs);
265 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
267 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", OldTss->Edx, OldTss->Ebp,
269 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
270 if (OldTss->Cs == KERNEL_CS)
272 DbgPrint("kESP %.8x ", Esp0);
273 if (PsGetCurrentThread() != NULL)
275 DbgPrint("kernel stack base %x\n",
276 PsGetCurrentThread()->Tcb.StackLimit);
282 DbgPrint("User ESP %.8x\n", OldTss->Esp);
284 if ((OldTss->Cs & 0xffff) == KERNEL_CS)
286 DbgPrint("ESP %x\n", Esp0);
287 if (PsGetCurrentThread() != NULL)
289 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
290 StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit;
294 StackLimit = (ULONG)&init_stack_top;
295 StackBase = (ULONG)&init_stack;
299 DbgPrint("Frames: ");
300 Frame = (PULONG)OldTss->Ebp;
301 while (Frame != NULL && (ULONG)Frame >= StackBase)
303 print_address((PVOID)Frame[1]);
304 Frame = (PULONG)Frame[0];
308 DbgPrint("Frames: ");
310 Frame = (PULONG)OldTss->Ebp;
311 while (Frame != NULL && (ULONG)Frame >= StackBase)
313 StackTrace[i] = (PVOID)Frame[1];
314 Frame = (PULONG)Frame[0];
320 while (i < TraceLength)
322 StackRepeatCount[i] = 0;
325 while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE)
327 if (memcmp(&StackTrace[i], &StackTrace[j],
328 (j - i) * sizeof(PVOID)) == 0)
330 StackRepeatCount[i] = 2;
331 StackRepeatLength[i] = j - i;
339 if (FoundRepeat == FALSE)
344 j = j + StackRepeatLength[i];
345 while ((TraceLength - j) >= StackRepeatLength[i] &&
348 if (memcmp(&StackTrace[i], &StackTrace[j],
349 StackRepeatLength[i] * sizeof(PVOID)) == 0)
351 StackRepeatCount[i]++;
352 j = j + StackRepeatLength[i];
363 while (i < TraceLength)
365 if (StackRepeatCount[i] == 0)
367 print_address(StackTrace[i]);
373 if (StackRepeatLength[i] == 0)
377 for (j = 0; j < StackRepeatLength[i]; j++)
379 print_address(StackTrace[i + j]);
381 DbgPrint("}*%d", StackRepeatCount[i]);
382 i = i + StackRepeatLength[i] * StackRepeatCount[i];
393 KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
400 ULONG ExceptionNr = (ULONG)Tf->DebugArgMark;
401 ULONG cr2 = (ULONG)Tf->DebugPointer;
406 * Print out the CPU registers
408 if (ExceptionNr < 19)
410 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
411 ExceptionNr, Tf->ErrorCode&0xffff);
415 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
417 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
418 Tf->Cs&0xffff, Tf->Eip);
419 print_address((PVOID)Tf->Eip);
421 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
422 DbgPrint("cr2 %x cr3 %x ", cr2, cr3);
423 DbgPrint("Proc: %x ",PsGetCurrentProcess());
424 if (PsGetCurrentProcess() != NULL)
426 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
427 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
429 if (PsGetCurrentThread() != NULL)
431 DbgPrint("Thrd: %x Tid: %x",
432 PsGetCurrentThread(),
433 PsGetCurrentThread()->Cid.UniqueThread);
436 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
437 Tf->Fs&0xffff, Tf->Gs&0xfff);
438 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
439 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf->Edx, Tf->Ebp, Tf->Esi);
440 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
441 if ((Tf->Cs&0xffff) == KERNEL_CS)
443 DbgPrint("kESP %.8x ", Esp0);
444 if (PsGetCurrentThread() != NULL)
446 DbgPrint("kernel stack base %x\n",
447 PsGetCurrentThread()->Tcb.StackLimit);
452 DbgPrint("ESP %x\n", Esp0);
454 if (PsGetCurrentThread() != NULL)
456 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
460 StackLimit = (ULONG)&init_stack_top;
464 * Dump the stack frames
466 DbgPrint("Frames: ");
468 Frame = (PULONG)Tf->Ebp;
469 while (Frame != NULL)
471 print_address((PVOID)Frame[1]);
472 Frame = (PULONG)Frame[0];
479 KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
481 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
482 * message and halt the computer
484 * Complete CPU context
491 /* Store the exception number in an unused field in the trap frame. */
492 Tf->DebugArgMark = (PVOID)ExceptionNr;
494 /* Use the address of the trap frame as approximation to the ring0 esp */
495 Esp0 = (ULONG)&Tf->Eip;
498 __asm__("movl %%cr2,%0\n\t" : "=d" (cr2));
499 Tf->DebugPointer = (PVOID)cr2;
502 * If this was a V86 mode exception then handle it specially
504 if (Tf->Eflags & (1 << 17))
506 return(KeV86Exception(ExceptionNr, Tf, cr2));
510 * Check for stack underflow, this may be obsolete
512 if (PsGetCurrentThread() != NULL &&
513 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
515 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
516 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
521 * Maybe handle the page fault and return
523 if (ExceptionNr == 14)
526 Status = MmPageFault(Tf->Cs&0xffff,
531 if (NT_SUCCESS(Status))
539 * Handle user exceptions differently
541 if ((Tf->Cs & 0xFFFF) == USER_CS)
543 return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
547 return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
552 KeDumpStackFrames(PULONG Frame)
556 DbgPrint("Frames: ");
558 while (Frame != NULL)
560 print_address((PVOID)Frame[1]);
561 Frame = (PULONG)Frame[0];
567 static void set_system_call_gate(unsigned int sel, unsigned int func)
569 DPRINT("sel %x %d\n",sel,sel);
570 KiIdt[sel].a = (((int)func)&0xffff) +
572 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
573 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
576 static void set_interrupt_gate(unsigned int sel, unsigned int func)
578 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
579 KiIdt[sel].a = (((int)func)&0xffff) +
581 KiIdt[sel].b = 0x8f00 + (((int)func)&0xffff0000);
585 set_task_gate(unsigned int sel, unsigned task_sel)
587 KiIdt[sel].a = task_sel << 16;
588 KiIdt[sel].b = 0x8500;
592 KeInitExceptions(VOID)
594 * FUNCTION: Initalize CPU exception handling
599 DPRINT("KeInitExceptions()\n");
602 * Set up the other gates
604 set_interrupt_gate(0, (ULONG)KiTrap0);
605 set_interrupt_gate(1, (ULONG)KiTrap1);
606 set_interrupt_gate(2, (ULONG)KiTrap2);
607 set_interrupt_gate(3, (ULONG)KiTrap3);
608 set_interrupt_gate(4, (ULONG)KiTrap4);
609 set_interrupt_gate(5, (ULONG)KiTrap5);
610 set_interrupt_gate(6, (ULONG)KiTrap6);
611 set_interrupt_gate(7, (ULONG)KiTrap7);
612 set_task_gate(8, TRAP_TSS_SELECTOR);
613 set_interrupt_gate(9, (ULONG)KiTrap9);
614 set_interrupt_gate(10, (ULONG)KiTrap10);
615 set_interrupt_gate(11, (ULONG)KiTrap11);
616 set_interrupt_gate(12, (ULONG)KiTrap12);
617 set_interrupt_gate(13, (ULONG)KiTrap13);
618 set_interrupt_gate(14, (ULONG)KiTrap14);
619 set_interrupt_gate(15, (ULONG)KiTrap15);
620 set_interrupt_gate(16, (ULONG)KiTrap16);
624 set_interrupt_gate(i,(int)KiTrapUnknown);
627 set_system_call_gate(0x2d,(int)interrupt_handler2d);
628 set_system_call_gate(0x2e,(int)interrupt_handler2e);