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