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