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