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