FreeLdr Patch. Now fully loads ntoskrnl using a PE Loader, supports /3gb dynamically...
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/i386/exp.c
5 * PURPOSE: Handling exceptions
6 *
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
8 * Skywing (skywing@valhallalegends.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* GLOBALS *****************************************************************/
19
20 #define FLAG_IF (1<<9)
21
22 #define _STR(x) #x
23 #define STR(x) _STR(x)
24
25 #ifndef ARRAY_SIZE
26 # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
27 #endif
28
29 extern void KiSystemService(void);
30 extern void interrupt_handler2d(void);
31
32 extern VOID KiTrap0(VOID);
33 extern VOID KiTrap1(VOID);
34 extern VOID KiTrap2(VOID);
35 extern VOID KiTrap3(VOID);
36 extern VOID KiTrap4(VOID);
37 extern VOID KiTrap5(VOID);
38 extern VOID KiTrap6(VOID);
39 extern VOID KiTrap7(VOID);
40 extern VOID KiTrap8(VOID);
41 extern VOID KiTrap9(VOID);
42 extern VOID KiTrap10(VOID);
43 extern VOID KiTrap11(VOID);
44 extern VOID KiTrap12(VOID);
45 extern VOID KiTrap13(VOID);
46 extern VOID KiTrap14(VOID);
47 extern VOID KiTrap15(VOID);
48 extern VOID KiTrap16(VOID);
49 extern VOID KiTrap17(VOID);
50 extern VOID KiTrap18(VOID);
51 extern VOID KiTrap19(VOID);
52 extern VOID KiTrapUnknown(VOID);
53
54 extern ULONG init_stack;
55 extern ULONG init_stack_top;
56
57 extern BOOLEAN Ke386NoExecute;
58
59 static char *ExceptionTypeStrings[] =
60 {
61 "Divide Error",
62 "Debug Trap",
63 "NMI",
64 "Breakpoint",
65 "Overflow",
66 "BOUND range exceeded",
67 "Invalid Opcode",
68 "No Math Coprocessor",
69 "Double Fault",
70 "Unknown(9)",
71 "Invalid TSS",
72 "Segment Not Present",
73 "Stack Segment Fault",
74 "General Protection",
75 "Page Fault",
76 "Reserved(15)",
77 "Math Fault",
78 "Alignment Check",
79 "Machine Check",
80 "SIMD Fault"
81 };
82
83 NTSTATUS ExceptionToNtStatus[] =
84 {
85 STATUS_INTEGER_DIVIDE_BY_ZERO,
86 STATUS_SINGLE_STEP,
87 STATUS_ACCESS_VIOLATION,
88 STATUS_BREAKPOINT,
89 STATUS_INTEGER_OVERFLOW,
90 STATUS_ARRAY_BOUNDS_EXCEEDED,
91 STATUS_ILLEGAL_INSTRUCTION,
92 STATUS_FLOAT_INVALID_OPERATION,
93 STATUS_ACCESS_VIOLATION,
94 STATUS_ACCESS_VIOLATION,
95 STATUS_ACCESS_VIOLATION,
96 STATUS_ACCESS_VIOLATION,
97 STATUS_STACK_OVERFLOW,
98 STATUS_ACCESS_VIOLATION,
99 STATUS_ACCESS_VIOLATION,
100 STATUS_ACCESS_VIOLATION, /* RESERVED */
101 STATUS_FLOAT_INVALID_OPERATION, /* Should not be used, the FPU can give more specific info */
102 STATUS_DATATYPE_MISALIGNMENT,
103 STATUS_ACCESS_VIOLATION,
104 STATUS_FLOAT_MULTIPLE_TRAPS,
105 };
106
107 /* FUNCTIONS ****************************************************************/
108
109 #if defined(DBG) || defined(KDBG)
110 BOOLEAN STDCALL
111 KeRosPrintAddress(PVOID address)
112 {
113 return KdbSymPrintAddress(address);
114 }
115 #else /* KDBG */
116 BOOLEAN STDCALL
117 KeRosPrintAddress(PVOID address)
118 {
119 PLIST_ENTRY current_entry;
120 MODULE_TEXT_SECTION* current;
121 extern LIST_ENTRY ModuleTextListHead;
122 ULONG_PTR RelativeAddress;
123
124 current_entry = ModuleTextListHead.Flink;
125
126 while (current_entry != &ModuleTextListHead &&
127 current_entry != NULL)
128 {
129 current =
130 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
131
132 if (address >= (PVOID)current->Base &&
133 address < (PVOID)(current->Base + current->Length))
134 {
135 RelativeAddress = (ULONG_PTR) address - current->Base;
136 DbgPrint("<%ws: %x>", current->Name, RelativeAddress);
137 return(TRUE);
138 }
139 current_entry = current_entry->Flink;
140 }
141 return(FALSE);
142 }
143 #endif /* KDBG */
144
145 ULONG
146 KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
147 {
148 EXCEPTION_RECORD Er;
149
150 Er.ExceptionFlags = 0;
151 Er.ExceptionRecord = NULL;
152 Er.ExceptionAddress = (PVOID)Tf->Eip;
153
154 if (ExceptionNr == 14)
155 {
156 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
157 Er.NumberParameters = 2;
158 Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
159 Er.ExceptionInformation[1] = (ULONG)Cr2;
160 }
161 else
162 {
163 if (ExceptionNr < ARRAY_SIZE(ExceptionToNtStatus))
164 {
165 Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
166 }
167 else
168 {
169 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
170 }
171 Er.NumberParameters = 0;
172 }
173
174 /* FIXME: Which exceptions are noncontinuable? */
175 Er.ExceptionFlags = 0;
176
177 KiDispatchException(&Er, 0, Tf, KernelMode, TRUE);
178
179 return(0);
180 }
181
182 ULONG
183 KiDoubleFaultHandler(VOID)
184 {
185 unsigned int cr2;
186 ULONG StackLimit;
187 ULONG StackBase;
188 ULONG Esp0;
189 ULONG ExceptionNr = 8;
190 KTSS* OldTss;
191 PULONG Frame;
192 ULONG OldCr3;
193 #if 0
194 ULONG i, j;
195 static PVOID StackTrace[MM_STACK_SIZE / sizeof(PVOID)];
196 static ULONG StackRepeatCount[MM_STACK_SIZE / sizeof(PVOID)];
197 static ULONG StackRepeatLength[MM_STACK_SIZE / sizeof(PVOID)];
198 ULONG TraceLength;
199 BOOLEAN FoundRepeat;
200 #endif
201
202 OldTss = KeGetCurrentKPCR()->TSS;
203 Esp0 = OldTss->Esp;
204
205 /* Get CR2 */
206 cr2 = Ke386GetCr2();
207 if (PsGetCurrentThread() != NULL &&
208 PsGetCurrentThread()->ThreadsProcess != NULL)
209 {
210 OldCr3 = (ULONG)
211 PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart;
212 }
213 else
214 {
215 OldCr3 = 0xBEADF0AL;
216 }
217
218 /*
219 * Check for stack underflow
220 */
221 if (PsGetCurrentThread() != NULL &&
222 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
223 {
224 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
225 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
226 ExceptionNr = 12;
227 }
228
229 /*
230 * Print out the CPU registers
231 */
232 if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
233 {
234 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
235 ExceptionNr, 0);
236 }
237 else
238 {
239 DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
240 }
241 DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
242 KeRosPrintAddress((PVOID)OldTss->Eip);
243 DbgPrint("\n");
244 DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
245 DbgPrint("Proc: %x ",PsGetCurrentProcess());
246 if (PsGetCurrentProcess() != NULL)
247 {
248 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
249 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
250 }
251 if (PsGetCurrentThread() != NULL)
252 {
253 DbgPrint("Thrd: %x Tid: %x",
254 PsGetCurrentThread(),
255 PsGetCurrentThread()->Cid.UniqueThread);
256 }
257 DbgPrint("\n");
258 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es,
259 OldTss->Fs, OldTss->Gs);
260 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
261 OldTss->Ecx);
262 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n ESP: %.8x", OldTss->Edx,
263 OldTss->Ebp, OldTss->Esi, Esp0);
264 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
265 if (OldTss->Cs == KERNEL_CS)
266 {
267 DbgPrint("kESP %.8x ", Esp0);
268 if (PsGetCurrentThread() != NULL)
269 {
270 DbgPrint("kernel stack base %x\n",
271 PsGetCurrentThread()->Tcb.StackLimit);
272
273 }
274 }
275 else
276 {
277 DbgPrint("User ESP %.8x\n", OldTss->Esp);
278 }
279 if ((OldTss->Cs & 0xffff) == KERNEL_CS)
280 {
281 if (PsGetCurrentThread() != NULL)
282 {
283 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
284 StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit;
285 }
286 else
287 {
288 StackLimit = (ULONG)init_stack_top;
289 StackBase = (ULONG)init_stack;
290 }
291
292 /*
293 Change to an #if 0 to reduce the amount of information printed on
294 a recursive stack trace.
295 */
296 #if 1
297 DbgPrint("Frames: ");
298 Frame = (PULONG)OldTss->Ebp;
299 while (Frame != NULL && (ULONG)Frame >= StackBase)
300 {
301 KeRosPrintAddress((PVOID)Frame[1]);
302 Frame = (PULONG)Frame[0];
303 DbgPrint("\n");
304 }
305 #else
306 DbgPrint("Frames: ");
307 i = 0;
308 Frame = (PULONG)OldTss->Ebp;
309 while (Frame != NULL && (ULONG)Frame >= StackBase)
310 {
311 StackTrace[i] = (PVOID)Frame[1];
312 Frame = (PULONG)Frame[0];
313 i++;
314 }
315 TraceLength = i;
316
317 i = 0;
318 while (i < TraceLength)
319 {
320 StackRepeatCount[i] = 0;
321 j = i + 1;
322 FoundRepeat = FALSE;
323 while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE)
324 {
325 if (memcmp(&StackTrace[i], &StackTrace[j],
326 (j - i) * sizeof(PVOID)) == 0)
327 {
328 StackRepeatCount[i] = 2;
329 StackRepeatLength[i] = j - i;
330 FoundRepeat = TRUE;
331 }
332 else
333 {
334 j++;
335 }
336 }
337 if (FoundRepeat == FALSE)
338 {
339 i++;
340 continue;
341 }
342 j = j + StackRepeatLength[i];
343 while ((TraceLength - j) >= StackRepeatLength[i] &&
344 FoundRepeat == TRUE)
345 {
346 if (memcmp(&StackTrace[i], &StackTrace[j],
347 StackRepeatLength[i] * sizeof(PVOID)) == 0)
348 {
349 StackRepeatCount[i]++;
350 j = j + StackRepeatLength[i];
351 }
352 else
353 {
354 FoundRepeat = FALSE;
355 }
356 }
357 i = j;
358 }
359
360 i = 0;
361 while (i < TraceLength)
362 {
363 if (StackRepeatCount[i] == 0)
364 {
365 KeRosPrintAddress(StackTrace[i]);
366 i++;
367 }
368 else
369 {
370 DbgPrint("{");
371 if (StackRepeatLength[i] == 0)
372 {
373 for(;;);
374 }
375 for (j = 0; j < StackRepeatLength[i]; j++)
376 {
377 KeRosPrintAddress(StackTrace[i + j]);
378 }
379 DbgPrint("}*%d", StackRepeatCount[i]);
380 i = i + StackRepeatLength[i] * StackRepeatCount[i];
381 }
382 }
383 #endif
384 }
385
386 DbgPrint("\n");
387 for(;;);
388 return 0;
389 }
390
391 VOID
392 KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
393 {
394 ULONG cr3_;
395 ULONG StackLimit;
396 ULONG Esp0;
397 ULONG ExceptionNr = (ULONG)Tf->DebugArgMark;
398 ULONG cr2 = (ULONG)Tf->DebugPointer;
399
400 Esp0 = (ULONG)Tf;
401
402 /*
403 * Print out the CPU registers
404 */
405 if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
406 {
407 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
408 ExceptionNr, Tf->ErrorCode&0xffff);
409 }
410 else
411 {
412 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
413 }
414 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
415 Tf->Cs&0xffff, Tf->Eip);
416 KeRosPrintAddress((PVOID)Tf->Eip);
417 DbgPrint("\n");
418 Ke386GetPageTableDirectory(cr3_);
419 DbgPrint("cr2 %x cr3 %x ", cr2, cr3_);
420 DbgPrint("Proc: %x ",PsGetCurrentProcess());
421 if (PsGetCurrentProcess() != NULL)
422 {
423 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
424 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
425 }
426 if (PsGetCurrentThread() != NULL)
427 {
428 DbgPrint("Thrd: %x Tid: %x",
429 PsGetCurrentThread(),
430 PsGetCurrentThread()->Cid.UniqueThread);
431 }
432 DbgPrint("\n");
433 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
434 Tf->Fs&0xffff, Tf->Gs&0xfff);
435 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
436 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf->Edx,
437 Tf->Ebp, Tf->Esi, Esp0);
438 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
439 if ((Tf->Cs&0xffff) == KERNEL_CS)
440 {
441 DbgPrint("kESP %.8x ", Esp0);
442 if (PsGetCurrentThread() != NULL)
443 {
444 DbgPrint("kernel stack base %x\n",
445 PsGetCurrentThread()->Tcb.StackLimit);
446
447 }
448 }
449
450 if (PsGetCurrentThread() != NULL)
451 {
452 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
453 }
454 else
455 {
456 StackLimit = (ULONG)init_stack_top;
457 }
458
459 /*
460 * Dump the stack frames
461 */
462 KeDumpStackFrames((PULONG)Tf->Ebp);
463 }
464
465 ULONG
466 KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
467 /*
468 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
469 * message and halt the computer
470 * ARGUMENTS:
471 * Complete CPU context
472 */
473 {
474 unsigned int cr2;
475 NTSTATUS Status;
476 ULONG Esp0;
477
478 /* Store the exception number in an unused field in the trap frame. */
479 Tf->DebugArgMark = (PVOID)ExceptionNr;
480
481 /* Use the address of the trap frame as approximation to the ring0 esp */
482 Esp0 = (ULONG)&Tf->Eip;
483
484 /* Get CR2 */
485 cr2 = Ke386GetCr2();
486 Tf->DebugPointer = (PVOID)cr2;
487
488 if (ExceptionNr == 14 && Tf->Eflags & FLAG_IF)
489 {
490 Ke386EnableInterrupts();
491 }
492
493 /*
494 * If this was a V86 mode exception then handle it specially
495 */
496 if (Tf->Eflags & (1 << 17))
497 {
498 return(KeV86Exception(ExceptionNr, Tf, cr2));
499 }
500
501 /*
502 * Check for stack underflow, this may be obsolete
503 */
504 if (PsGetCurrentThread() != NULL &&
505 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
506 {
507 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
508 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
509 ExceptionNr = 12;
510 }
511
512 /*
513 * Maybe handle the page fault and return
514 */
515 if (ExceptionNr == 14)
516 {
517 if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2 >= KERNEL_BASE)
518 {
519 KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
520 }
521 Status = MmPageFault(Tf->Cs&0xffff,
522 &Tf->Eip,
523 &Tf->Eax,
524 cr2,
525 Tf->ErrorCode);
526 if (NT_SUCCESS(Status))
527 {
528 return(0);
529 }
530 }
531
532 /*
533 * Check for a breakpoint that was only for the attention of the debugger.
534 */
535 if (ExceptionNr == 3 && Tf->Eip == ((ULONG)DbgBreakPointNoBugCheck) + 1)
536 {
537 /*
538 EIP is already adjusted by the processor to point to the instruction
539 after the breakpoint.
540 */
541 return(0);
542 }
543
544 /*
545 * Try to handle device-not-present, math-fault and xmm-fault exceptions.
546 */
547 if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
548 {
549 Status = KiHandleFpuFault(Tf, ExceptionNr);
550 if (NT_SUCCESS(Status))
551 {
552 return(0);
553 }
554 }
555
556 /*
557 * Handle user exceptions differently
558 */
559 if ((Tf->Cs & 0xFFFF) == USER_CS)
560 {
561 return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
562 }
563 else
564 {
565 return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
566 }
567 }
568
569 VOID
570 KeDumpStackFrames(PULONG Frame)
571 {
572 PULONG StackBase, StackEnd;
573 MEMORY_BASIC_INFORMATION mbi;
574 ULONG ResultLength = sizeof(mbi);
575 NTSTATUS Status;
576
577 DbgPrint("Frames:\n");
578 _SEH_TRY
579 {
580 Status = MiQueryVirtualMemory (
581 (HANDLE)-1,
582 Frame,
583 MemoryBasicInformation,
584 &mbi,
585 sizeof(mbi),
586 &ResultLength );
587 if ( !NT_SUCCESS(Status) )
588 {
589 DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
590 return;
591 }
592
593 StackBase = Frame;
594 StackEnd = mbi.BaseAddress + mbi.RegionSize;
595
596 while ( Frame >= StackBase && Frame < StackEnd )
597 {
598 ULONG Addr = Frame[1];
599 if (!KeRosPrintAddress((PVOID)Addr))
600 DbgPrint("<%X>", Addr);
601 if ( Addr == 0 || Addr == 0xDEADBEEF )
602 break;
603 StackBase = Frame;
604 Frame = (PULONG)Frame[0];
605 DbgPrint("\n");
606 }
607 }
608 _SEH_HANDLE
609 {
610 }
611 _SEH_END;
612 DbgPrint("\n");
613 }
614
615 VOID STDCALL
616 KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
617 {
618 ULONG i=0;
619 PULONG StackBase, StackEnd;
620 MEMORY_BASIC_INFORMATION mbi;
621 ULONG ResultLength = sizeof(mbi);
622 NTSTATUS Status;
623
624 DbgPrint("Frames: ");
625 _SEH_TRY
626 {
627 if ( !Frame )
628 {
629 #if defined __GNUC__
630 __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
631 #elif defined(_MSC_VER)
632 __asm mov [Frame], ebp
633 #endif
634 //Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
635 }
636
637 Status = MiQueryVirtualMemory (
638 (HANDLE)-1,
639 Frame,
640 MemoryBasicInformation,
641 &mbi,
642 sizeof(mbi),
643 &ResultLength );
644 if ( !NT_SUCCESS(Status) )
645 {
646 DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
647 return;
648 }
649
650 StackBase = Frame;
651 StackEnd = mbi.BaseAddress + mbi.RegionSize;
652
653 while ( Frame >= StackBase && Frame < StackEnd && i++ < FrameCount )
654 {
655 ULONG Addr = Frame[1];
656 if (!KeRosPrintAddress((PVOID)Addr))
657 DbgPrint("<%X>", Addr);
658 if ( Addr == 0 || Addr == 0xDEADBEEF )
659 break;
660 StackBase = Frame;
661 Frame = (PULONG)Frame[0];
662 DbgPrint(" ");
663 }
664 }
665 _SEH_HANDLE
666 {
667 }
668 _SEH_END;
669 DbgPrint("\n");
670 }
671
672 ULONG STDCALL
673 KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
674 {
675 ULONG Count = 0;
676 PULONG StackBase, StackEnd, Frame;
677 MEMORY_BASIC_INFORMATION mbi;
678 ULONG ResultLength = sizeof(mbi);
679 NTSTATUS Status;
680
681 _SEH_TRY
682 {
683 #if defined __GNUC__
684 __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
685 #elif defined(_MSC_VER)
686 __asm mov [Frame], ebp
687 #endif
688
689 Status = MiQueryVirtualMemory (
690 (HANDLE)-1,
691 Frame,
692 MemoryBasicInformation,
693 &mbi,
694 sizeof(mbi),
695 &ResultLength );
696 if ( !NT_SUCCESS(Status) )
697 {
698 DPRINT1("Can't get stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
699 return 0;
700 }
701
702 StackBase = Frame;
703 StackEnd = mbi.BaseAddress + mbi.RegionSize;
704
705 while ( Count < FrameCount && Frame >= StackBase && Frame < StackEnd )
706 {
707 Frames[Count++] = Frame[1];
708 StackBase = Frame;
709 Frame = (PULONG)Frame[0];
710 }
711 }
712 _SEH_HANDLE
713 {
714 }
715 _SEH_END;
716 return Count;
717 }
718
719 static void
720 set_system_call_gate(unsigned int sel, unsigned int func)
721 {
722 DPRINT("sel %x %d\n",sel,sel);
723 KiIdt[sel].a = (((int)func)&0xffff) +
724 (KERNEL_CS << 16);
725 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
726 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
727 }
728
729 static void set_interrupt_gate(unsigned int sel, unsigned int func)
730 {
731 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
732 KiIdt[sel].a = (((int)func)&0xffff) +
733 (KERNEL_CS << 16);
734 KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
735 }
736
737 static void set_trap_gate(unsigned int sel, unsigned int func, unsigned int dpl)
738 {
739 DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel, func, dpl);
740 ASSERT(dpl <= 3);
741 KiIdt[sel].a = (((int)func)&0xffff) +
742 (KERNEL_CS << 16);
743 KiIdt[sel].b = 0x8f00 + (dpl << 13) + (((int)func)&0xffff0000);
744 }
745
746 static void
747 set_task_gate(unsigned int sel, unsigned task_sel)
748 {
749 KiIdt[sel].a = task_sel << 16;
750 KiIdt[sel].b = 0x8500;
751 }
752
753 VOID INIT_FUNCTION
754 KeInitExceptions(VOID)
755 /*
756 * FUNCTION: Initalize CPU exception handling
757 */
758 {
759 int i;
760
761 DPRINT("KeInitExceptions()\n");
762
763 /*
764 * Set up the other gates
765 */
766 set_trap_gate(0, (ULONG)KiTrap0, 0);
767 set_trap_gate(1, (ULONG)KiTrap1, 0);
768 set_trap_gate(2, (ULONG)KiTrap2, 0);
769 set_trap_gate(3, (ULONG)KiTrap3, 3);
770 set_trap_gate(4, (ULONG)KiTrap4, 0);
771 set_trap_gate(5, (ULONG)KiTrap5, 0);
772 set_trap_gate(6, (ULONG)KiTrap6, 0);
773 set_trap_gate(7, (ULONG)KiTrap7, 0);
774 set_task_gate(8, TRAP_TSS_SELECTOR);
775 set_trap_gate(9, (ULONG)KiTrap9, 0);
776 set_trap_gate(10, (ULONG)KiTrap10, 0);
777 set_trap_gate(11, (ULONG)KiTrap11, 0);
778 set_trap_gate(12, (ULONG)KiTrap12, 0);
779 set_trap_gate(13, (ULONG)KiTrap13, 0);
780 set_interrupt_gate(14, (ULONG)KiTrap14);
781 set_trap_gate(15, (ULONG)KiTrap15, 0);
782 set_trap_gate(16, (ULONG)KiTrap16, 0);
783 set_trap_gate(17, (ULONG)KiTrap17, 0);
784 set_trap_gate(18, (ULONG)KiTrap18, 0);
785 set_trap_gate(19, (ULONG)KiTrap19, 0);
786
787 for (i = 20; i < 256; i++)
788 {
789 set_trap_gate(i,(int)KiTrapUnknown, 0);
790 }
791
792 set_system_call_gate(0x2d,(int)interrupt_handler2d);
793 set_system_call_gate(0x2e,(int)KiSystemService);
794 }
795
796 /*
797 * @implemented
798 */
799 NTSTATUS STDCALL
800 KeRaiseUserException(IN NTSTATUS ExceptionCode)
801 {
802 ULONG OldEip;
803 PKTHREAD Thread = KeGetCurrentThread();
804
805 _SEH_TRY {
806 Thread->Teb->ExceptionCode = ExceptionCode;
807 } _SEH_HANDLE {
808 return(ExceptionCode);
809 } _SEH_END;
810
811 OldEip = Thread->TrapFrame->Eip;
812 Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
813 return((NTSTATUS)OldEip);
814 }
815
816 /*
817 * @implemented
818 */
819 NTSTATUS
820 STDCALL
821 NtRaiseException (
822 IN PEXCEPTION_RECORD ExceptionRecord,
823 IN PCONTEXT Context,
824 IN BOOLEAN SearchFrames)
825 {
826 PKTHREAD Thread = KeGetCurrentThread();
827 PKTRAP_FRAME TrapFrame = Thread->TrapFrame;
828 PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
829
830 KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList;
831
832 KiDispatchException(ExceptionRecord,
833 Context,
834 TrapFrame,
835 KeGetPreviousMode(),
836 SearchFrames);
837
838 /* Restore the user context */
839 Thread->TrapFrame = PrevTrapFrame;
840 __asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame));
841
842 /* We never get here */
843 return(STATUS_SUCCESS);
844 }