Removed references to obsolete config.h preventing compilation
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /*
20 * PROJECT: ReactOS kernel
21 * FILE: ntoskrnl/ke/i386/exp.c
22 * PURPOSE: Handling exceptions
23 * PROGRAMMER: David Welch (welch@cwcom.net)
24 * REVISION HISTORY:
25 * ??/??/??: Created
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <internal/ntoskrnl.h>
32 #include <internal/ke.h>
33 #include <internal/i386/segment.h>
34 #include <internal/i386/mm.h>
35 #include <internal/module.h>
36 #include <internal/mm.h>
37 #include <internal/ps.h>
38 #include <internal/trap.h>
39
40 #define NDEBUG
41 #include <internal/debug.h>
42
43 /* GLOBALS *****************************************************************/
44
45 #define _STR(x) #x
46 #define STR(x) _STR(x)
47
48 extern void interrupt_handler2e(void);
49 extern void interrupt_handler2d(void);
50
51 extern VOID KiTrap0(VOID);
52 extern VOID KiTrap1(VOID);
53 extern VOID KiTrap2(VOID);
54 extern VOID KiTrap3(VOID);
55 extern VOID KiTrap4(VOID);
56 extern VOID KiTrap5(VOID);
57 extern VOID KiTrap6(VOID);
58 extern VOID KiTrap7(VOID);
59 extern VOID KiTrap8(VOID);
60 extern VOID KiTrap9(VOID);
61 extern VOID KiTrap10(VOID);
62 extern VOID KiTrap11(VOID);
63 extern VOID KiTrap12(VOID);
64 extern VOID KiTrap13(VOID);
65 extern VOID KiTrap14(VOID);
66 extern VOID KiTrap15(VOID);
67 extern VOID KiTrap16(VOID);
68 extern VOID KiTrapUnknown(VOID);
69
70 extern ULONG init_stack;
71 extern ULONG init_stack_top;
72
73 static char *ExceptionTypeStrings[] =
74 {
75 "Divide Error",
76 "Debug Trap",
77 "NMI",
78 "Breakpoint",
79 "Overflow",
80 "BOUND range exceeded",
81 "Invalid Opcode",
82 "No Math Coprocessor",
83 "Double Fault",
84 "Unknown(9)",
85 "Invalid TSS",
86 "Segment Not Present",
87 "Stack Segment Fault",
88 "General Protection",
89 "Page Fault",
90 "Math Fault",
91 "Alignment Check",
92 "Machine Check"
93 };
94
95 /* FUNCTIONS ****************************************************************/
96
97 extern unsigned int _text_start__, _text_end__;
98
99 STATIC BOOLEAN
100 print_address(PVOID address)
101 {
102 #ifdef KDBG
103 ULONG Offset;
104 PSYMBOL Symbol, NextSymbol;
105 BOOLEAN Printed = FALSE;
106 ULONG NextAddress;
107 #endif /* KDBG */
108 PLIST_ENTRY current_entry;
109 MODULE_TEXT_SECTION* current;
110 extern LIST_ENTRY ModuleTextListHead;
111
112 current_entry = ModuleTextListHead.Flink;
113
114 while (current_entry != &ModuleTextListHead &&
115 current_entry != NULL)
116 {
117 current =
118 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
119
120 if (address >= (PVOID)current->Base &&
121 address < (PVOID)(current->Base + current->Length))
122 {
123
124 #ifdef KDBG
125
126 Offset = (ULONG)((ULONG)address - current->Base);
127 Symbol = current->Symbols.Symbols;
128 while (Symbol != NULL)
129 {
130 NextSymbol = Symbol->Next;
131 if (NextSymbol != NULL)
132 NextAddress = NextSymbol->RelativeAddress;
133 else
134 NextAddress = current->Length;
135
136 if ((Offset >= Symbol->RelativeAddress) &&
137 (Offset < NextAddress))
138 {
139 DbgPrint("<%ws: %x (%wZ)>", current->Name, Offset, &Symbol->Name);
140 Printed = TRUE;
141 break;
142 }
143 Symbol = NextSymbol;
144 }
145 if (!Printed)
146 DbgPrint("<%ws: %x>", current->Name, Offset);
147
148 #else /* KDBG */
149
150 DbgPrint("<%ws: %x>", current->Name,
151 address - current->Base);
152
153 #endif /* KDBG */
154
155 return(TRUE);
156 }
157
158 current_entry = current_entry->Flink;
159 }
160 return(FALSE);
161 }
162
163 #if 0
164 ULONG
165 KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
166 {
167 EXCEPTION_RECORD Er;
168
169 if (ExceptionNr == 0)
170 {
171 Er.ExceptionCode = STATUS_INTEGER_DIVIDE_BY_ZERO;
172 }
173 else if (ExceptionNr == 1)
174 {
175 Er.ExceptionCode = STATUS_SINGLE_STEP;
176 }
177 else if (ExceptionNr == 3)
178 {
179 Er.ExceptionCode = STATUS_BREAKPOINT;
180 }
181 else if (ExceptionNr == 4)
182 {
183 Er.ExceptionCode = STATUS_INTEGER_OVERFLOW;
184 }
185 else if (ExceptionNr == 5)
186 {
187 Er.ExceptionCode = STATUS_ARRAY_BOUNDS_EXCEEDED;
188 }
189 else if (ExceptionNr == 6)
190 {
191 Er.ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
192 }
193 else
194 {
195 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
196 }
197 Er.ExceptionFlags = 0;
198 Er.ExceptionRecord = NULL;
199 Er.ExceptionAddress = (PVOID)Tf->Eip;
200 if (ExceptionNr == 14)
201 {
202 Er.NumberParameters = 2;
203 Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
204 Er.ExceptionInformation[1] = (ULONG)Cr2;
205 }
206 else
207 {
208 Er.NumberParameters = 0;
209 }
210
211
212 KiDispatchException(&Er, 0, Tf, UserMode, TRUE);
213 return(0);
214 }
215 #endif
216
217 ULONG
218 KiUserTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
219 {
220 PULONG Frame;
221 ULONG cr3;
222 ULONG i;
223
224 /*
225 * Get the PDBR
226 */
227 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
228
229 /*
230 * Print out the CPU registers
231 */
232 if (ExceptionNr < 19)
233 {
234 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
235 ExceptionNr, Tf->ErrorCode&0xffff);
236 }
237 else
238 {
239 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
240 }
241 DbgPrint("CS:EIP %x:%x ", Tf->Cs&0xffff, Tf->Eip);
242 print_address((PVOID)Tf->Eip);
243 DbgPrint("\n");
244 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
245 DbgPrint("CR2 %x CR3 %x ", Cr2, cr3);
246 DbgPrint("Proc: %x ",PsGetCurrentProcess());
247 if (PsGetCurrentProcess() != NULL)
248 {
249 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
250 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
251 }
252 if (PsGetCurrentThread() != NULL)
253 {
254 DbgPrint("Thrd: %x Tid: %x",
255 PsGetCurrentThread(),
256 PsGetCurrentThread()->Cid.UniqueThread);
257 }
258 DbgPrint("\n");
259 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
260 Tf->Fs&0xffff, Tf->Gs&0xfff);
261 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
262 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf->Edx, Tf->Ebp, Tf->Esi);
263 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
264 DbgPrint("SS:ESP %x:%x\n", Tf->Ss, Tf->Esp);
265
266 #if 0
267 stack=(PULONG)(Tf->Esp);
268
269 DbgPrint("Stack:\n");
270 for (i=0; i<64; i++)
271 {
272 if (MmIsPagePresent(NULL,&stack[i]))
273 {
274 DbgPrint("%.8x ",stack[i]);
275 if (((i+1)%8) == 0)
276 {
277 DbgPrint("\n");
278 }
279 }
280 }
281 #endif
282
283 #if 0
284 if (MmIsPagePresent(NULL, (PVOID)Tf->Eip))
285 {
286 unsigned char instrs[512];
287
288 memcpy(instrs, (PVOID)Tf->Eip, 512);
289
290 DbgPrint("Instrs: ");
291
292 for (i=0; i<10; i++)
293 {
294 DbgPrint("%x ", instrs[i]);
295 }
296 }
297 #endif
298
299 /*
300 * Dump the stack frames
301 */
302 DbgPrint("Frames: ");
303 i = 1;
304 Frame = (PULONG)Tf->Ebp;
305 while (Frame != NULL)
306 {
307 DbgPrint("%.8x ", Frame[1]);
308 Frame = (PULONG)Frame[0];
309 i++;
310 }
311 if ((i % 8) != 0)
312 {
313 DbgPrint("\n");
314 }
315
316 /*
317 * Kill the faulting task
318 */
319 __asm__("sti\n\t");
320 ZwTerminateProcess(NtCurrentProcess(),
321 STATUS_NONCONTINUABLE_EXCEPTION);
322
323 /*
324 * If terminating the process fails then bugcheck
325 */
326 KeBugCheck(0);
327 return(0);
328 }
329
330 ULONG
331 KiDoubleFaultHandler(VOID)
332 {
333 unsigned int cr2;
334 unsigned int i;
335 PULONG stack;
336 ULONG StackLimit;
337 ULONG Esp0;
338 ULONG ExceptionNr = 8;
339 KTSS* OldTss;
340
341 /* Use the address of the trap frame as approximation to the ring0 esp */
342 OldTss = KeGetCurrentKPCR()->TSS;
343 Esp0 = OldTss->Esp0;
344
345 /* Get CR2 */
346 __asm__("movl %%cr2,%0\n\t" : "=d" (cr2));
347
348 /*
349 * Check for stack underflow
350 */
351 if (PsGetCurrentThread() != NULL &&
352 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
353 {
354 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
355 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
356 ExceptionNr = 12;
357 }
358
359 /*
360 * Print out the CPU registers
361 */
362 if (ExceptionNr < 19)
363 {
364 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
365 ExceptionNr, 0);
366 }
367 else
368 {
369 DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
370 }
371 DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
372 print_address((PVOID)OldTss->Eip);
373 DbgPrint("\n");
374 DbgPrint("cr2 %x cr3 %x ", cr2, OldTss->Cr3);
375 DbgPrint("Proc: %x ",PsGetCurrentProcess());
376 if (PsGetCurrentProcess() != NULL)
377 {
378 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
379 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
380 }
381 if (PsGetCurrentThread() != NULL)
382 {
383 DbgPrint("Thrd: %x Tid: %x",
384 PsGetCurrentThread(),
385 PsGetCurrentThread()->Cid.UniqueThread);
386 }
387 DbgPrint("\n");
388 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es,
389 OldTss->Fs, OldTss->Gs);
390 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
391 OldTss->Ecx);
392 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", OldTss->Edx, OldTss->Ebp,
393 OldTss->Esi);
394 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
395 if (OldTss->Cs == KERNEL_CS)
396 {
397 DbgPrint("kESP %.8x ", Esp0);
398 if (PsGetCurrentThread() != NULL)
399 {
400 DbgPrint("kernel stack base %x\n",
401 PsGetCurrentThread()->Tcb.StackLimit);
402
403 }
404 }
405 else
406 {
407 DbgPrint("User ESP %.8x\n", OldTss->Esp);
408 }
409 if ((OldTss->Cs & 0xffff) == KERNEL_CS)
410 {
411 DbgPrint("ESP %x\n", Esp0);
412 stack = (PULONG) (Esp0 + 24);
413 stack = (PULONG)(((ULONG)stack) & (~0x3));
414 if (PsGetCurrentThread() != NULL)
415 {
416 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
417 }
418 else
419 {
420 StackLimit = (ULONG)&init_stack_top;
421 }
422
423 DbgPrint("stack<%p>: ", stack);
424
425 for (i = 0; i < 18 && (((ULONG)&stack[i+5]) < StackLimit); i = i + 6)
426 {
427 DbgPrint("%.8x %.8x %.8x %.8x\n",
428 stack[i], stack[i+1],
429 stack[i+2], stack[i+3],
430 stack[i+4], stack[i+5]);
431 }
432 DbgPrint("Frames:\n");
433 for (i = 0; i < 32 && (((ULONG)&stack[i]) < StackLimit); i++)
434 {
435 if (stack[i] > ((unsigned int) &_text_start__) &&
436 !(stack[i] >= ((ULONG)&init_stack) &&
437 stack[i] <= ((ULONG)&init_stack_top)))
438 {
439 print_address((PVOID)stack[i]);
440 DbgPrint(" ");
441 }
442 }
443 }
444
445 DbgPrint("\n");
446 for(;;);
447 }
448
449 ULONG
450 KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
451 /*
452 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
453 * message and halt the computer
454 * ARGUMENTS:
455 * Complete CPU context
456 */
457 {
458 unsigned int cr2, cr3;
459 unsigned int i;
460 // unsigned int j, sym;
461 NTSTATUS Status;
462 ULONG Esp0;
463 ULONG StackLimit;
464 PULONG Frame;
465
466 /* Use the address of the trap frame as approximation to the ring0 esp */
467 Esp0 = (ULONG)&Tf->Eip;
468
469 /* Get CR2 */
470 __asm__("movl %%cr2,%0\n\t" : "=d" (cr2));
471
472 /*
473 * If this was a V86 mode exception then handle it specially
474 */
475 if (Tf->Eflags & (1 << 17))
476 {
477 return(KeV86Exception(ExceptionNr, Tf, cr2));
478 }
479
480 /*
481 * Check for stack underflow, this may be obsolete
482 */
483 if (PsGetCurrentThread() != NULL &&
484 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
485 {
486 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
487 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
488 ExceptionNr = 12;
489 }
490
491 /*
492 * Maybe handle the page fault and return
493 */
494 if (ExceptionNr == 14)
495 {
496 __asm__("sti\n\t");
497 Status = MmPageFault(Tf->Cs&0xffff,
498 &Tf->Eip,
499 &Tf->Eax,
500 cr2,
501 Tf->ErrorCode);
502 if (NT_SUCCESS(Status))
503 {
504 return(0);
505 }
506 }
507
508 /*
509 * Handle user exceptions differently
510 */
511 if ((Tf->Cs & 0xFFFF) == USER_CS)
512 {
513 return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
514 }
515
516 /*
517 * Print out the CPU registers
518 */
519 if (ExceptionNr < 19)
520 {
521 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
522 ExceptionNr, Tf->ErrorCode&0xffff);
523 }
524 else
525 {
526 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
527 }
528 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
529 Tf->Cs&0xffff, Tf->Eip);
530 print_address((PVOID)Tf->Eip);
531 DbgPrint("\n");
532 __asm__("movl %%cr3,%0\n\t" : "=d" (cr3));
533 DbgPrint("cr2 %x cr3 %x ", cr2, cr3);
534 DbgPrint("Proc: %x ",PsGetCurrentProcess());
535 if (PsGetCurrentProcess() != NULL)
536 {
537 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
538 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
539 }
540 if (PsGetCurrentThread() != NULL)
541 {
542 DbgPrint("Thrd: %x Tid: %x",
543 PsGetCurrentThread(),
544 PsGetCurrentThread()->Cid.UniqueThread);
545 }
546 DbgPrint("\n");
547 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
548 Tf->Fs&0xffff, Tf->Gs&0xfff);
549 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
550 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", Tf->Edx, Tf->Ebp, Tf->Esi);
551 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
552 if ((Tf->Cs&0xffff) == KERNEL_CS)
553 {
554 DbgPrint("kESP %.8x ", Esp0);
555 if (PsGetCurrentThread() != NULL)
556 {
557 DbgPrint("kernel stack base %x\n",
558 PsGetCurrentThread()->Tcb.StackLimit);
559
560 }
561 }
562
563 DbgPrint("ESP %x\n", Esp0);
564
565 if (PsGetCurrentThread() != NULL)
566 {
567 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
568 }
569 else
570 {
571 StackLimit = (ULONG)&init_stack_top;
572 }
573
574 /*
575 * Dump the stack frames
576 */
577 DbgPrint("Frames: ");
578 i = 1;
579 Frame = (PULONG)Tf->Ebp;
580 while (Frame != NULL)
581 {
582 print_address((PVOID)Frame[1]);
583 Frame = (PULONG)Frame[0];
584 i++;
585 }
586 if ((i % 8) != 0)
587 {
588 DbgPrint("\n");
589 }
590
591 for(;;);
592 }
593
594 VOID
595 KeDumpStackFrames(PULONG Frame)
596 {
597 ULONG i;
598
599 DbgPrint("Frames: ");
600 i = 1;
601 while (Frame != NULL)
602 {
603 print_address((PVOID)Frame[1]);
604 Frame = (PULONG)Frame[0];
605 i++;
606 }
607 if ((i % 8) != 0)
608 {
609 DbgPrint("\n");
610 }
611 }
612
613 static void set_system_call_gate(unsigned int sel, unsigned int func)
614 {
615 DPRINT("sel %x %d\n",sel,sel);
616 KiIdt[sel].a = (((int)func)&0xffff) +
617 (KERNEL_CS << 16);
618 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
619 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
620 }
621
622 static void set_interrupt_gate(unsigned int sel, unsigned int func)
623 {
624 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
625 KiIdt[sel].a = (((int)func)&0xffff) +
626 (KERNEL_CS << 16);
627 KiIdt[sel].b = 0x8f00 + (((int)func)&0xffff0000);
628 }
629
630 static void
631 set_task_gate(unsigned int sel, unsigned task_sel)
632 {
633 KiIdt[sel].a = task_sel << 16;
634 KiIdt[sel].b = 0x8500;
635 }
636
637 VOID
638 KeInitExceptions(VOID)
639 /*
640 * FUNCTION: Initalize CPU exception handling
641 */
642 {
643 int i;
644
645 DPRINT("KeInitExceptions()\n");
646
647 /*
648 * Set up the other gates
649 */
650 set_interrupt_gate(0, (ULONG)KiTrap0);
651 set_interrupt_gate(1, (ULONG)KiTrap1);
652 set_interrupt_gate(2, (ULONG)KiTrap2);
653 set_interrupt_gate(3, (ULONG)KiTrap3);
654 set_interrupt_gate(4, (ULONG)KiTrap4);
655 set_interrupt_gate(5, (ULONG)KiTrap5);
656 set_interrupt_gate(6, (ULONG)KiTrap6);
657 set_interrupt_gate(7, (ULONG)KiTrap7);
658 set_task_gate(8, TRAP_TSS_SELECTOR);
659 set_interrupt_gate(9, (ULONG)KiTrap9);
660 set_interrupt_gate(10, (ULONG)KiTrap10);
661 set_interrupt_gate(11, (ULONG)KiTrap11);
662 set_interrupt_gate(12, (ULONG)KiTrap12);
663 set_interrupt_gate(13, (ULONG)KiTrap13);
664 set_interrupt_gate(14, (ULONG)KiTrap14);
665 set_interrupt_gate(15, (ULONG)KiTrap15);
666 set_interrupt_gate(16, (ULONG)KiTrap16);
667
668 for (i=17;i<256;i++)
669 {
670 set_interrupt_gate(i,(int)KiTrapUnknown);
671 }
672
673 set_system_call_gate(0x2d,(int)interrupt_handler2d);
674 set_system_call_gate(0x2e,(int)interrupt_handler2e);
675 }