fix infinite loop 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 <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 if (!KeRosPrintAddress((PVOID)Frame[1]))
636 {
637 DbgPrint("<%X>", (PVOID)Frame[1]);
638 }
639 Frame = (PULONG)Frame[0];
640 DbgPrint(" ");
641 }
642 DbgPrint("\n");
643 }
644
645 VOID STDCALL
646 KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
647 {
648 ULONG i=0;
649
650 DbgPrint("Frames: ");
651 if ( !Frame )
652 {
653 #if defined __GNUC__
654 __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
655 #elif defined(_MSC_VER)
656 __asm mov [Frame], ebp
657 #endif
658 Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
659 }
660 while ( MmIsAddressValid(Frame) && i++ < FrameCount )
661 {
662 ULONG Addr = Frame[1];
663 if (!KeRosPrintAddress((PVOID)Addr))
664 {
665 DbgPrint("<%X>", Addr);
666 }
667 if ( Addr == 0 || Addr == 0xDEADBEEF )
668 {
669 break;
670 }
671 Frame = (PULONG)Frame[0];
672 DbgPrint(" ");
673 }
674 DbgPrint("\n");
675 }
676
677 static void set_system_call_gate(unsigned int sel, unsigned int func)
678 {
679 DPRINT("sel %x %d\n",sel,sel);
680 KiIdt[sel].a = (((int)func)&0xffff) +
681 (KERNEL_CS << 16);
682 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
683 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
684 }
685
686 static void set_interrupt_gate(unsigned int sel, unsigned int func)
687 {
688 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
689 KiIdt[sel].a = (((int)func)&0xffff) +
690 (KERNEL_CS << 16);
691 KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
692 }
693
694 static void set_trap_gate(unsigned int sel, unsigned int func, unsigned int dpl)
695 {
696 DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel, func, dpl);
697 ASSERT(dpl <= 3);
698 KiIdt[sel].a = (((int)func)&0xffff) +
699 (KERNEL_CS << 16);
700 KiIdt[sel].b = 0x8f00 + (dpl << 13) + (((int)func)&0xffff0000);
701 }
702
703 static void
704 set_task_gate(unsigned int sel, unsigned task_sel)
705 {
706 KiIdt[sel].a = task_sel << 16;
707 KiIdt[sel].b = 0x8500;
708 }
709
710 VOID INIT_FUNCTION
711 KeInitExceptions(VOID)
712 /*
713 * FUNCTION: Initalize CPU exception handling
714 */
715 {
716 int i;
717
718 DPRINT("KeInitExceptions()\n");
719
720 /*
721 * Set up the other gates
722 */
723 set_trap_gate(0, (ULONG)KiTrap0, 0);
724 set_trap_gate(1, (ULONG)KiTrap1, 0);
725 set_trap_gate(2, (ULONG)KiTrap2, 0);
726 set_trap_gate(3, (ULONG)KiTrap3, 3);
727 set_trap_gate(4, (ULONG)KiTrap4, 0);
728 set_trap_gate(5, (ULONG)KiTrap5, 0);
729 set_trap_gate(6, (ULONG)KiTrap6, 0);
730 set_trap_gate(7, (ULONG)KiTrap7, 0);
731 set_task_gate(8, TRAP_TSS_SELECTOR);
732 set_trap_gate(9, (ULONG)KiTrap9, 0);
733 set_trap_gate(10, (ULONG)KiTrap10, 0);
734 set_trap_gate(11, (ULONG)KiTrap11, 0);
735 set_trap_gate(12, (ULONG)KiTrap12, 0);
736 set_trap_gate(13, (ULONG)KiTrap13, 0);
737 set_interrupt_gate(14, (ULONG)KiTrap14);
738 set_trap_gate(15, (ULONG)KiTrap15, 0);
739 set_trap_gate(16, (ULONG)KiTrap16, 0);
740 set_trap_gate(17, (ULONG)KiTrap17, 0);
741 set_trap_gate(18, (ULONG)KiTrap18, 0);
742 set_trap_gate(19, (ULONG)KiTrap19, 0);
743
744 for (i = 20; i < 256; i++)
745 {
746 set_trap_gate(i,(int)KiTrapUnknown, 0);
747 }
748
749 set_system_call_gate(0x2d,(int)interrupt_handler2d);
750 set_system_call_gate(0x2e,(int)interrupt_handler2e);
751 }
752
753 /*
754 * @implemented
755 */
756
757 NTSTATUS STDCALL
758 KeRaiseUserException(IN NTSTATUS ExceptionCode)
759 {
760 /* FIXME: This needs SEH */
761 ULONG OldEip;
762 PKTHREAD Thread = KeGetCurrentThread();
763
764 ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */
765 OldEip = Thread->TrapFrame->Eip;
766 Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
767 Thread->Teb->ExceptionCode = ExceptionCode;
768 return((NTSTATUS)OldEip);
769 }
770
771 VOID
772 FASTCALL
773 KeRosTrapReturn ( PKTRAP_FRAME TrapFrame, PKTRAP_FRAME PrevTrapFrame );
774
775 /*
776 * @implemented
777 */
778 NTSTATUS STDCALL
779 NtRaiseException (
780 IN PEXCEPTION_RECORD ExceptionRecord,
781 IN PCONTEXT Context,
782 IN BOOLEAN SearchFrames)
783 {
784 PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame;
785 PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
786
787 KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList;
788
789 KiDispatchException(ExceptionRecord,
790 Context,
791 PsGetCurrentThread()->Tcb.TrapFrame,
792 (KPROCESSOR_MODE)ExGetPreviousMode(),
793 SearchFrames);
794
795 KeRosTrapReturn ( TrapFrame, PrevTrapFrame );
796 return(STATUS_SUCCESS);
797 }