Copy wininet to branch
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/i386/exp.c
5 * PURPOSE: Handling exceptions
6 *
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
8 * Skywing (skywing@valhallalegends.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 /* GLOBALS *****************************************************************/
19
20 #define FLAG_IF (1<<9)
21
22 #define _STR(x) #x
23 #define STR(x) _STR(x)
24
25 #ifndef ARRAY_SIZE
26 # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
27 #endif
28
29 extern void KiSystemService(void);
30 extern void interrupt_handler2d(void);
31
32 extern VOID KiTrap0(VOID);
33 extern VOID KiTrap1(VOID);
34 extern VOID KiTrap2(VOID);
35 extern VOID KiTrap3(VOID);
36 extern VOID KiTrap4(VOID);
37 extern VOID KiTrap5(VOID);
38 extern VOID KiTrap6(VOID);
39 extern VOID KiTrap7(VOID);
40 extern VOID KiTrap8(VOID);
41 extern VOID KiTrap9(VOID);
42 extern VOID KiTrap10(VOID);
43 extern VOID KiTrap11(VOID);
44 extern VOID KiTrap12(VOID);
45 extern VOID KiTrap13(VOID);
46 extern VOID KiTrap14(VOID);
47 extern VOID KiTrap15(VOID);
48 extern VOID KiTrap16(VOID);
49 extern VOID KiTrap17(VOID);
50 extern VOID KiTrap18(VOID);
51 extern VOID KiTrap19(VOID);
52 extern VOID KiTrapUnknown(VOID);
53
54 extern ULONG init_stack;
55 extern ULONG init_stack_top;
56
57 extern BOOLEAN Ke386NoExecute;
58
59 static char *ExceptionTypeStrings[] =
60 {
61 "Divide Error",
62 "Debug Trap",
63 "NMI",
64 "Breakpoint",
65 "Overflow",
66 "BOUND range exceeded",
67 "Invalid Opcode",
68 "No Math Coprocessor",
69 "Double Fault",
70 "Unknown(9)",
71 "Invalid TSS",
72 "Segment Not Present",
73 "Stack Segment Fault",
74 "General Protection",
75 "Page Fault",
76 "Reserved(15)",
77 "Math Fault",
78 "Alignment Check",
79 "Machine Check",
80 "SIMD Fault"
81 };
82
83 NTSTATUS ExceptionToNtStatus[] =
84 {
85 STATUS_INTEGER_DIVIDE_BY_ZERO,
86 STATUS_SINGLE_STEP,
87 STATUS_ACCESS_VIOLATION,
88 STATUS_BREAKPOINT,
89 STATUS_INTEGER_OVERFLOW,
90 STATUS_ARRAY_BOUNDS_EXCEEDED,
91 STATUS_ILLEGAL_INSTRUCTION,
92 STATUS_FLOAT_INVALID_OPERATION,
93 STATUS_ACCESS_VIOLATION,
94 STATUS_ACCESS_VIOLATION,
95 STATUS_ACCESS_VIOLATION,
96 STATUS_ACCESS_VIOLATION,
97 STATUS_STACK_OVERFLOW,
98 STATUS_ACCESS_VIOLATION,
99 STATUS_ACCESS_VIOLATION,
100 STATUS_ACCESS_VIOLATION, /* RESERVED */
101 STATUS_FLOAT_INVALID_OPERATION, /* Should not be used, the FPU can give more specific info */
102 STATUS_DATATYPE_MISALIGNMENT,
103 STATUS_ACCESS_VIOLATION,
104 STATUS_FLOAT_MULTIPLE_TRAPS,
105 };
106
107 /* FUNCTIONS ****************************************************************/
108
109 #if defined(DBG) || defined(KDBG)
110 BOOLEAN STDCALL
111 KeRosPrintAddress(PVOID address)
112 {
113 return KdbSymPrintAddress(address);
114 }
115 #else /* KDBG */
116 BOOLEAN STDCALL
117 KeRosPrintAddress(PVOID address)
118 {
119 PLIST_ENTRY current_entry;
120 MODULE_TEXT_SECTION* current;
121 extern LIST_ENTRY ModuleTextListHead;
122 ULONG_PTR RelativeAddress;
123 ULONG i = 0;
124
125 do
126 {
127 current_entry = ModuleTextListHead.Flink;
128
129 while (current_entry != &ModuleTextListHead &&
130 current_entry != NULL)
131 {
132 current =
133 CONTAINING_RECORD(current_entry, MODULE_TEXT_SECTION, ListEntry);
134
135 if (address >= (PVOID)current->Base &&
136 address < (PVOID)(current->Base + current->Length))
137 {
138 RelativeAddress = (ULONG_PTR) address - current->Base;
139 DbgPrint("<%ws: %x>", current->Name, RelativeAddress);
140 return(TRUE);
141 }
142 current_entry = current_entry->Flink;
143 }
144
145 address = (PVOID)((ULONG_PTR)address & ~0xC0000000);
146 } while(++i <= 1);
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 < ARRAY_SIZE(ExceptionToNtStatus))
171 {
172 Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
173 }
174 else
175 {
176 Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
177 }
178 Er.NumberParameters = 0;
179 }
180
181 /* FIXME: Which exceptions are noncontinuable? */
182 Er.ExceptionFlags = 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 cr2 = Ke386GetCr2();
214 if (PsGetCurrentThread() != NULL &&
215 PsGetCurrentThread()->ThreadsProcess != NULL)
216 {
217 OldCr3 = (ULONG)
218 PsGetCurrentThread()->ThreadsProcess->Pcb.DirectoryTableBase.QuadPart;
219 }
220 else
221 {
222 OldCr3 = 0xBEADF0AL;
223 }
224
225 /*
226 * Check for stack underflow
227 */
228 if (PsGetCurrentThread() != NULL &&
229 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
230 {
231 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
232 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
233 ExceptionNr = 12;
234 }
235
236 /*
237 * Print out the CPU registers
238 */
239 if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
240 {
241 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
242 ExceptionNr, 0);
243 }
244 else
245 {
246 DbgPrint("Exception: %d(%x)\n", ExceptionNr, 0);
247 }
248 DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
249 KeRosPrintAddress((PVOID)OldTss->Eip);
250 DbgPrint("\n");
251 DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
252 DbgPrint("Proc: %x ",PsGetCurrentProcess());
253 if (PsGetCurrentProcess() != NULL)
254 {
255 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
256 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
257 }
258 if (PsGetCurrentThread() != NULL)
259 {
260 DbgPrint("Thrd: %x Tid: %x",
261 PsGetCurrentThread(),
262 PsGetCurrentThread()->Cid.UniqueThread);
263 }
264 DbgPrint("\n");
265 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss->Ds, OldTss->Es,
266 OldTss->Fs, OldTss->Gs);
267 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss->Eax, OldTss->Ebx,
268 OldTss->Ecx);
269 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n ESP: %.8x", OldTss->Edx,
270 OldTss->Ebp, OldTss->Esi, Esp0);
271 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
272 if (OldTss->Cs == KERNEL_CS)
273 {
274 DbgPrint("kESP %.8x ", Esp0);
275 if (PsGetCurrentThread() != NULL)
276 {
277 DbgPrint("kernel stack base %x\n",
278 PsGetCurrentThread()->Tcb.StackLimit);
279
280 }
281 }
282 else
283 {
284 DbgPrint("User ESP %.8x\n", OldTss->Esp);
285 }
286 if ((OldTss->Cs & 0xffff) == KERNEL_CS)
287 {
288 if (PsGetCurrentThread() != NULL)
289 {
290 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
291 StackBase = (ULONG)PsGetCurrentThread()->Tcb.StackLimit;
292 }
293 else
294 {
295 StackLimit = (ULONG)init_stack_top;
296 StackBase = (ULONG)init_stack;
297 }
298
299 /*
300 Change to an #if 0 to reduce the amount of information printed on
301 a recursive stack trace.
302 */
303 #if 1
304 DbgPrint("Frames: ");
305 Frame = (PULONG)OldTss->Ebp;
306 while (Frame != NULL && (ULONG)Frame >= StackBase)
307 {
308 KeRosPrintAddress((PVOID)Frame[1]);
309 Frame = (PULONG)Frame[0];
310 DbgPrint("\n");
311 }
312 #else
313 DbgPrint("Frames: ");
314 i = 0;
315 Frame = (PULONG)OldTss->Ebp;
316 while (Frame != NULL && (ULONG)Frame >= StackBase)
317 {
318 StackTrace[i] = (PVOID)Frame[1];
319 Frame = (PULONG)Frame[0];
320 i++;
321 }
322 TraceLength = i;
323
324 i = 0;
325 while (i < TraceLength)
326 {
327 StackRepeatCount[i] = 0;
328 j = i + 1;
329 FoundRepeat = FALSE;
330 while ((j - i) <= (TraceLength - j) && FoundRepeat == FALSE)
331 {
332 if (memcmp(&StackTrace[i], &StackTrace[j],
333 (j - i) * sizeof(PVOID)) == 0)
334 {
335 StackRepeatCount[i] = 2;
336 StackRepeatLength[i] = j - i;
337 FoundRepeat = TRUE;
338 }
339 else
340 {
341 j++;
342 }
343 }
344 if (FoundRepeat == FALSE)
345 {
346 i++;
347 continue;
348 }
349 j = j + StackRepeatLength[i];
350 while ((TraceLength - j) >= StackRepeatLength[i] &&
351 FoundRepeat == TRUE)
352 {
353 if (memcmp(&StackTrace[i], &StackTrace[j],
354 StackRepeatLength[i] * sizeof(PVOID)) == 0)
355 {
356 StackRepeatCount[i]++;
357 j = j + StackRepeatLength[i];
358 }
359 else
360 {
361 FoundRepeat = FALSE;
362 }
363 }
364 i = j;
365 }
366
367 i = 0;
368 while (i < TraceLength)
369 {
370 if (StackRepeatCount[i] == 0)
371 {
372 KeRosPrintAddress(StackTrace[i]);
373 i++;
374 }
375 else
376 {
377 DbgPrint("{");
378 if (StackRepeatLength[i] == 0)
379 {
380 for(;;);
381 }
382 for (j = 0; j < StackRepeatLength[i]; j++)
383 {
384 KeRosPrintAddress(StackTrace[i + j]);
385 }
386 DbgPrint("}*%d", StackRepeatCount[i]);
387 i = i + StackRepeatLength[i] * StackRepeatCount[i];
388 }
389 }
390 #endif
391 }
392
393 DbgPrint("\n");
394 for(;;);
395 return 0;
396 }
397
398 VOID
399 KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
400 {
401 ULONG cr3_;
402 ULONG StackLimit;
403 ULONG Esp0;
404 ULONG ExceptionNr = (ULONG)Tf->DebugArgMark;
405 ULONG cr2 = (ULONG)Tf->DebugPointer;
406
407 Esp0 = (ULONG)Tf;
408
409 /*
410 * Print out the CPU registers
411 */
412 if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
413 {
414 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
415 ExceptionNr, Tf->ErrorCode&0xffff);
416 }
417 else
418 {
419 DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
420 }
421 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
422 Tf->Cs&0xffff, Tf->Eip);
423 KeRosPrintAddress((PVOID)Tf->Eip);
424 DbgPrint("\n");
425 Ke386GetPageTableDirectory(cr3_);
426 DbgPrint("cr2 %x cr3 %x ", cr2, cr3_);
427 DbgPrint("Proc: %x ",PsGetCurrentProcess());
428 if (PsGetCurrentProcess() != NULL)
429 {
430 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
431 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
432 }
433 if (PsGetCurrentThread() != NULL)
434 {
435 DbgPrint("Thrd: %x Tid: %x",
436 PsGetCurrentThread(),
437 PsGetCurrentThread()->Cid.UniqueThread);
438 }
439 DbgPrint("\n");
440 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
441 Tf->Fs&0xffff, Tf->Gs&0xfff);
442 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
443 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf->Edx,
444 Tf->Ebp, Tf->Esi, Esp0);
445 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
446 if ((Tf->Cs&0xffff) == KERNEL_CS)
447 {
448 DbgPrint("kESP %.8x ", Esp0);
449 if (PsGetCurrentThread() != NULL)
450 {
451 DbgPrint("kernel stack base %x\n",
452 PsGetCurrentThread()->Tcb.StackLimit);
453
454 }
455 }
456
457 if (PsGetCurrentThread() != NULL)
458 {
459 StackLimit = (ULONG)PsGetCurrentThread()->Tcb.StackBase;
460 }
461 else
462 {
463 StackLimit = (ULONG)init_stack_top;
464 }
465
466 /*
467 * Dump the stack frames
468 */
469 KeDumpStackFrames((PULONG)Tf->Ebp);
470 }
471
472 ULONG
473 KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
474 /*
475 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
476 * message and halt the computer
477 * ARGUMENTS:
478 * Complete CPU context
479 */
480 {
481 unsigned int cr2;
482 NTSTATUS Status;
483 ULONG Esp0;
484
485 /* Store the exception number in an unused field in the trap frame. */
486 Tf->DebugArgMark = (PVOID)ExceptionNr;
487
488 /* Use the address of the trap frame as approximation to the ring0 esp */
489 Esp0 = (ULONG)&Tf->Eip;
490
491 /* Get CR2 */
492 cr2 = Ke386GetCr2();
493 Tf->DebugPointer = (PVOID)cr2;
494
495 if (ExceptionNr == 14 && Tf->Eflags & FLAG_IF)
496 {
497 Ke386EnableInterrupts();
498 }
499
500 /*
501 * If this was a V86 mode exception then handle it specially
502 */
503 if (Tf->Eflags & (1 << 17))
504 {
505 return(KeV86Exception(ExceptionNr, Tf, cr2));
506 }
507
508 /*
509 * Check for stack underflow, this may be obsolete
510 */
511 if (PsGetCurrentThread() != NULL &&
512 Esp0 < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
513 {
514 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
515 Esp0, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
516 ExceptionNr = 12;
517 }
518
519 if (ExceptionNr == 15)
520 {
521 /*
522 * FIXME:
523 * This exception should never occur. The P6 has a bug, which does sometimes deliver
524 * the apic spurious interrupt as exception 15. On an athlon64, I get one exception
525 * in the early boot phase in apic mode (using the smp build). I've looked to the linux
526 * sources. Linux does ignore this exception.
527 *
528 * Hartmut Birr
529 */
530 DPRINT1("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
531 return(0);
532 }
533
534 /*
535 * Maybe handle the page fault and return
536 */
537 if (ExceptionNr == 14)
538 {
539 if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2 >= KERNEL_BASE)
540 {
541 KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
542 }
543 Status = MmPageFault(Tf->Cs&0xffff,
544 &Tf->Eip,
545 &Tf->Eax,
546 cr2,
547 Tf->ErrorCode);
548 if (NT_SUCCESS(Status))
549 {
550 return(0);
551 }
552 }
553
554 /*
555 * Check for a breakpoint that was only for the attention of the debugger.
556 */
557 if (ExceptionNr == 3 && Tf->Eip == ((ULONG)DbgBreakPointNoBugCheck) + 1)
558 {
559 /*
560 EIP is already adjusted by the processor to point to the instruction
561 after the breakpoint.
562 */
563 return(0);
564 }
565
566 /*
567 * Try to handle device-not-present, math-fault and xmm-fault exceptions.
568 */
569 if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
570 {
571 Status = KiHandleFpuFault(Tf, ExceptionNr);
572 if (NT_SUCCESS(Status))
573 {
574 return(0);
575 }
576 }
577
578 /*
579 * Handle user exceptions differently
580 */
581 if ((Tf->Cs & 0xFFFF) == USER_CS)
582 {
583 return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
584 }
585 else
586 {
587 return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
588 }
589 }
590
591 VOID
592 KeContextToTrapFrame(PCONTEXT Context,
593 PKTRAP_FRAME TrapFrame)
594 {
595 if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
596 {
597 TrapFrame->Esp = Context->Esp;
598 TrapFrame->Ss = Context->SegSs;
599 TrapFrame->Cs = Context->SegCs;
600 TrapFrame->Eip = Context->Eip;
601 TrapFrame->Eflags = Context->EFlags;
602 TrapFrame->Ebp = Context->Ebp;
603 }
604 if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
605 {
606 TrapFrame->Eax = Context->Eax;
607 TrapFrame->Ebx = Context->Ebx;
608 TrapFrame->Ecx = Context->Ecx;
609 TrapFrame->Edx = Context->Edx;
610 TrapFrame->Esi = Context->Esi;
611 TrapFrame->Edi = Context->Edi;
612 }
613 if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
614 {
615 TrapFrame->Ds = Context->SegDs;
616 TrapFrame->Es = Context->SegEs;
617 TrapFrame->Fs = Context->SegFs;
618 TrapFrame->Gs = Context->SegGs;
619 }
620 if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
621 {
622 /*
623 * Not handled
624 *
625 * This should be handled separately I think.
626 * - blight
627 */
628 }
629 if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
630 {
631 /*
632 * Not handled
633 */
634 }
635 }
636
637 VOID
638 KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
639 PCONTEXT Context)
640 {
641 if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
642 {
643 Context->SegSs = TrapFrame->Ss;
644 Context->Esp = TrapFrame->Esp;
645 Context->SegCs = TrapFrame->Cs;
646 Context->Eip = TrapFrame->Eip;
647 Context->EFlags = TrapFrame->Eflags;
648 Context->Ebp = TrapFrame->Ebp;
649 }
650 if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
651 {
652 Context->Eax = TrapFrame->Eax;
653 Context->Ebx = TrapFrame->Ebx;
654 Context->Ecx = TrapFrame->Ecx;
655 /*
656 * NOTE: In the trap frame which is built on entry to a system
657 * call TrapFrame->Edx will actually hold the address of the
658 * previous TrapFrame. I don't believe leaking this information
659 * has security implications. Also EDX holds the address of the
660 * arguments to the system call in progress so it isn't of much
661 * interest to the debugger.
662 */
663 Context->Edx = TrapFrame->Edx;
664 Context->Esi = TrapFrame->Esi;
665 Context->Edi = TrapFrame->Edi;
666 }
667 if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
668 {
669 Context->SegDs = TrapFrame->Ds;
670 Context->SegEs = TrapFrame->Es;
671 Context->SegFs = TrapFrame->Fs;
672 Context->SegGs = TrapFrame->Gs;
673 }
674 if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
675 {
676 /*
677 * FIXME: Implement this case
678 */
679 Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
680 }
681 if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
682 {
683 /*
684 * FIXME: Implement this case
685 *
686 * I think this should only be filled for FPU exceptions, otherwise I
687 * would not know where to get it from as it can be the current state
688 * of the FPU or already saved in the thread's FPU save area.
689 * -blight
690 */
691 Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
692 }
693 #if 0
694 if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
695 {
696 /*
697 * FIXME: Investigate this
698 *
699 * This is the XMM state (first 512 bytes of FXSAVE_FORMAT/FX_SAVE_AREA)
700 * This should only be filled in case of a SIMD exception I think, so
701 * this is not the right place (like for FPU the state could already be
702 * saved in the thread's FX_SAVE_AREA or still be in the CPU)
703 * -blight
704 */
705 Context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS;
706 }
707 #endif
708 }
709
710 VOID
711 KeDumpStackFrames(PULONG Frame)
712 {
713 PULONG StackBase, StackEnd;
714 MEMORY_BASIC_INFORMATION mbi;
715 ULONG ResultLength = sizeof(mbi);
716 NTSTATUS Status;
717
718 DbgPrint("Frames:\n");
719 _SEH_TRY
720 {
721 Status = MiQueryVirtualMemory (
722 (HANDLE)-1,
723 Frame,
724 MemoryBasicInformation,
725 &mbi,
726 sizeof(mbi),
727 &ResultLength );
728 if ( !NT_SUCCESS(Status) )
729 {
730 DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
731 return;
732 }
733
734 StackBase = Frame;
735 StackEnd = mbi.BaseAddress + mbi.RegionSize;
736
737 while ( Frame >= StackBase && Frame < StackEnd )
738 {
739 ULONG Addr = Frame[1];
740 if (!KeRosPrintAddress((PVOID)Addr))
741 DbgPrint("<%X>", Addr);
742 if ( Addr == 0 || Addr == 0xDEADBEEF )
743 break;
744 StackBase = Frame;
745 Frame = (PULONG)Frame[0];
746 DbgPrint("\n");
747 }
748 }
749 _SEH_HANDLE
750 {
751 }
752 _SEH_END;
753 DbgPrint("\n");
754 }
755
756 VOID STDCALL
757 KeRosDumpStackFrames ( PULONG Frame, ULONG FrameCount )
758 {
759 ULONG i=0;
760 PULONG StackBase, StackEnd;
761 MEMORY_BASIC_INFORMATION mbi;
762 ULONG ResultLength = sizeof(mbi);
763 NTSTATUS Status;
764
765 DbgPrint("Frames: ");
766 _SEH_TRY
767 {
768 if ( !Frame )
769 {
770 #if defined __GNUC__
771 __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
772 #elif defined(_MSC_VER)
773 __asm mov [Frame], ebp
774 #endif
775 //Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
776 }
777
778 Status = MiQueryVirtualMemory (
779 (HANDLE)-1,
780 Frame,
781 MemoryBasicInformation,
782 &mbi,
783 sizeof(mbi),
784 &ResultLength );
785 if ( !NT_SUCCESS(Status) )
786 {
787 DPRINT1("Can't dump stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
788 return;
789 }
790
791 StackBase = Frame;
792 StackEnd = mbi.BaseAddress + mbi.RegionSize;
793
794 while ( Frame >= StackBase && Frame < StackEnd && i++ < FrameCount )
795 {
796 ULONG Addr = Frame[1];
797 if (!KeRosPrintAddress((PVOID)Addr))
798 DbgPrint("<%X>", Addr);
799 if ( Addr == 0 || Addr == 0xDEADBEEF )
800 break;
801 StackBase = Frame;
802 Frame = (PULONG)Frame[0];
803 DbgPrint(" ");
804 }
805 }
806 _SEH_HANDLE
807 {
808 }
809 _SEH_END;
810 DbgPrint("\n");
811 }
812
813 ULONG STDCALL
814 KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount )
815 {
816 ULONG Count = 0;
817 PULONG StackBase, StackEnd, Frame;
818 MEMORY_BASIC_INFORMATION mbi;
819 ULONG ResultLength = sizeof(mbi);
820 NTSTATUS Status;
821
822 _SEH_TRY
823 {
824 #if defined __GNUC__
825 __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
826 #elif defined(_MSC_VER)
827 __asm mov [Frame], ebp
828 #endif
829
830 Status = MiQueryVirtualMemory (
831 (HANDLE)-1,
832 Frame,
833 MemoryBasicInformation,
834 &mbi,
835 sizeof(mbi),
836 &ResultLength );
837 if ( !NT_SUCCESS(Status) )
838 {
839 DPRINT1("Can't get stack frames: NtQueryVirtualMemory() failed: %x\n", Status );
840 return 0;
841 }
842
843 StackBase = Frame;
844 StackEnd = mbi.BaseAddress + mbi.RegionSize;
845
846 while ( Count < FrameCount && Frame >= StackBase && Frame < StackEnd )
847 {
848 Frames[Count++] = Frame[1];
849 StackBase = Frame;
850 Frame = (PULONG)Frame[0];
851 }
852 }
853 _SEH_HANDLE
854 {
855 }
856 _SEH_END;
857 return Count;
858 }
859
860 static void
861 set_system_call_gate(unsigned int sel, unsigned int func)
862 {
863 DPRINT("sel %x %d\n",sel,sel);
864 KiIdt[sel].a = (((int)func)&0xffff) +
865 (KERNEL_CS << 16);
866 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
867 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
868 }
869
870 static void set_interrupt_gate(unsigned int sel, unsigned int func)
871 {
872 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
873 KiIdt[sel].a = (((int)func)&0xffff) +
874 (KERNEL_CS << 16);
875 KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
876 }
877
878 static void set_trap_gate(unsigned int sel, unsigned int func, unsigned int dpl)
879 {
880 DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel, func, dpl);
881 ASSERT(dpl <= 3);
882 KiIdt[sel].a = (((int)func)&0xffff) +
883 (KERNEL_CS << 16);
884 KiIdt[sel].b = 0x8f00 + (dpl << 13) + (((int)func)&0xffff0000);
885 }
886
887 static void
888 set_task_gate(unsigned int sel, unsigned task_sel)
889 {
890 KiIdt[sel].a = task_sel << 16;
891 KiIdt[sel].b = 0x8500;
892 }
893
894 VOID INIT_FUNCTION
895 KeInitExceptions(VOID)
896 /*
897 * FUNCTION: Initalize CPU exception handling
898 */
899 {
900 int i;
901
902 DPRINT("KeInitExceptions()\n");
903
904 /*
905 * Set up the other gates
906 */
907 set_trap_gate(0, (ULONG)KiTrap0, 0);
908 set_trap_gate(1, (ULONG)KiTrap1, 0);
909 set_trap_gate(2, (ULONG)KiTrap2, 0);
910 set_trap_gate(3, (ULONG)KiTrap3, 3);
911 set_trap_gate(4, (ULONG)KiTrap4, 0);
912 set_trap_gate(5, (ULONG)KiTrap5, 0);
913 set_trap_gate(6, (ULONG)KiTrap6, 0);
914 set_trap_gate(7, (ULONG)KiTrap7, 0);
915 set_task_gate(8, TRAP_TSS_SELECTOR);
916 set_trap_gate(9, (ULONG)KiTrap9, 0);
917 set_trap_gate(10, (ULONG)KiTrap10, 0);
918 set_trap_gate(11, (ULONG)KiTrap11, 0);
919 set_trap_gate(12, (ULONG)KiTrap12, 0);
920 set_trap_gate(13, (ULONG)KiTrap13, 0);
921 set_interrupt_gate(14, (ULONG)KiTrap14);
922 set_trap_gate(15, (ULONG)KiTrap15, 0);
923 set_trap_gate(16, (ULONG)KiTrap16, 0);
924 set_trap_gate(17, (ULONG)KiTrap17, 0);
925 set_trap_gate(18, (ULONG)KiTrap18, 0);
926 set_trap_gate(19, (ULONG)KiTrap19, 0);
927
928 for (i = 20; i < 256; i++)
929 {
930 set_trap_gate(i,(int)KiTrapUnknown, 0);
931 }
932
933 set_system_call_gate(0x2d,(int)interrupt_handler2d);
934 set_system_call_gate(0x2e,(int)KiSystemService);
935 }
936
937 /*
938 * @implemented
939 */
940 NTSTATUS STDCALL
941 KeRaiseUserException(IN NTSTATUS ExceptionCode)
942 {
943 ULONG OldEip;
944 PKTHREAD Thread = KeGetCurrentThread();
945
946 _SEH_TRY {
947 Thread->Teb->ExceptionCode = ExceptionCode;
948 } _SEH_HANDLE {
949 return(ExceptionCode);
950 } _SEH_END;
951
952 OldEip = Thread->TrapFrame->Eip;
953 Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
954 return((NTSTATUS)OldEip);
955 }
956
957 /*
958 * @implemented
959 */
960 NTSTATUS
961 STDCALL
962 NtRaiseException (
963 IN PEXCEPTION_RECORD ExceptionRecord,
964 IN PCONTEXT Context,
965 IN BOOLEAN SearchFrames)
966 {
967 PKTHREAD Thread = KeGetCurrentThread();
968 PKTRAP_FRAME TrapFrame = Thread->TrapFrame;
969 PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
970
971 KeGetCurrentKPCR()->Tib.ExceptionList = TrapFrame->ExceptionList;
972
973 KiDispatchException(ExceptionRecord,
974 Context,
975 TrapFrame,
976 KeGetPreviousMode(),
977 SearchFrames);
978
979 /* Restore the user context */
980 Thread->TrapFrame = PrevTrapFrame;
981 __asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame));
982
983 /* We never get here */
984 return(STATUS_SUCCESS);
985 }