2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/ke/i386/exp.c
5 * PURPOSE: Handling exceptions
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
8 * Skywing (skywing@valhallalegends.com)
11 /* INCLUDES *****************************************************************/
16 #include <internal/debug.h>
18 /* GLOBALS *****************************************************************/
20 #define FLAG_IF (1<<9)
23 #define STR(x) _STR(x)
26 # define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
29 extern void KiSystemService(void);
30 extern void KiDebugService(void);
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
);
54 extern ULONG init_stack
;
55 extern ULONG init_stack_top
;
57 extern BOOLEAN Ke386NoExecute
;
59 static char *ExceptionTypeStrings
[] =
66 "BOUND range exceeded",
68 "No Math Coprocessor",
72 "Segment Not Present",
73 "Stack Segment Fault",
83 NTSTATUS ExceptionToNtStatus
[] =
85 STATUS_INTEGER_DIVIDE_BY_ZERO
,
87 STATUS_ACCESS_VIOLATION
,
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
,
107 /* FUNCTIONS ****************************************************************/
110 KiRosPrintAddress(PVOID address
)
112 PLIST_ENTRY current_entry
;
113 MODULE_TEXT_SECTION
* current
;
114 extern LIST_ENTRY ModuleTextListHead
;
115 ULONG_PTR RelativeAddress
;
120 current_entry
= ModuleTextListHead
.Flink
;
122 while (current_entry
!= &ModuleTextListHead
&&
123 current_entry
!= NULL
)
126 CONTAINING_RECORD(current_entry
, MODULE_TEXT_SECTION
, ListEntry
);
128 if (address
>= (PVOID
)current
->Base
&&
129 address
< (PVOID
)(current
->Base
+ current
->Length
))
131 RelativeAddress
= (ULONG_PTR
) address
- current
->Base
;
132 DbgPrint("<%ws: %x>", current
->Name
, RelativeAddress
);
135 current_entry
= current_entry
->Flink
;
138 address
= (PVOID
)((ULONG_PTR
)address
& ~(ULONG_PTR
)MmSystemRangeStart
);
145 KiKernelTrapHandler(PKTRAP_FRAME Tf
, ULONG ExceptionNr
, PVOID Cr2
)
149 Er
.ExceptionFlags
= 0;
150 Er
.ExceptionRecord
= NULL
;
151 Er
.ExceptionAddress
= (PVOID
)Tf
->Eip
;
153 if (ExceptionNr
== 14)
155 Er
.ExceptionCode
= STATUS_ACCESS_VIOLATION
;
156 Er
.NumberParameters
= 2;
157 Er
.ExceptionInformation
[0] = Tf
->ErrorCode
& 0x1;
158 Er
.ExceptionInformation
[1] = (ULONG
)Cr2
;
162 if (ExceptionNr
< ARRAY_SIZE(ExceptionToNtStatus
))
164 Er
.ExceptionCode
= ExceptionToNtStatus
[ExceptionNr
];
168 Er
.ExceptionCode
= STATUS_ACCESS_VIOLATION
;
170 Er
.NumberParameters
= 0;
173 /* FIXME: Which exceptions are noncontinuable? */
174 Er
.ExceptionFlags
= 0;
176 KiDispatchException(&Er
, 0, Tf
, KernelMode
, TRUE
);
182 KiDoubleFaultHandler(VOID
)
188 ULONG ExceptionNr
= 8;
194 static PVOID StackTrace
[MM_STACK_SIZE
/ sizeof(PVOID
)];
195 static ULONG StackRepeatCount
[MM_STACK_SIZE
/ sizeof(PVOID
)];
196 static ULONG StackRepeatLength
[MM_STACK_SIZE
/ sizeof(PVOID
)];
201 OldTss
= KeGetCurrentKPCR()->TSS
;
206 if (PsGetCurrentThread() != NULL
&&
207 PsGetCurrentThread()->ThreadsProcess
!= NULL
)
210 PsGetCurrentThread()->ThreadsProcess
->Pcb
.DirectoryTableBase
.QuadPart
;
218 * Check for stack underflow
220 if (PsGetCurrentThread() != NULL
&&
221 Esp0
< (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
)
223 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
224 Esp0
, (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
);
229 * Print out the CPU registers
231 if (ExceptionNr
< ARRAY_SIZE(ExceptionTypeStrings
))
233 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings
[ExceptionNr
],
238 DbgPrint("Exception: %d(%x)\n", ExceptionNr
, 0);
240 DbgPrint("CS:EIP %x:%x ", OldTss
->Cs
, OldTss
->Eip
);
241 KeRosPrintAddress((PVOID
)OldTss
->Eip
);
243 DbgPrint("cr2 %x cr3 %x ", cr2
, OldCr3
);
244 DbgPrint("Proc: %x ",PsGetCurrentProcess());
245 if (PsGetCurrentProcess() != NULL
)
247 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId
);
248 DbgPrint("%.16s> ", PsGetCurrentProcess()->ImageFileName
);
250 if (PsGetCurrentThread() != NULL
)
252 DbgPrint("Thrd: %x Tid: %x",
253 PsGetCurrentThread(),
254 PsGetCurrentThread()->Cid
.UniqueThread
);
257 DbgPrint("DS %x ES %x FS %x GS %x\n", OldTss
->Ds
, OldTss
->Es
,
258 OldTss
->Fs
, OldTss
->Gs
);
259 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", OldTss
->Eax
, OldTss
->Ebx
,
261 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\nESP: %.8x ", OldTss
->Edx
,
262 OldTss
->Ebp
, OldTss
->Esi
, Esp0
);
263 DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss
->Edi
, OldTss
->Eflags
);
264 if (OldTss
->Cs
== KERNEL_CS
)
266 DbgPrint("kESP %.8x ", Esp0
);
267 if (PsGetCurrentThread() != NULL
)
269 DbgPrint("kernel stack base %x\n",
270 PsGetCurrentThread()->Tcb
.StackLimit
);
276 DbgPrint("User ESP %.8x\n", OldTss
->Esp
);
278 if ((OldTss
->Cs
& 0xffff) == KERNEL_CS
)
280 if (PsGetCurrentThread() != NULL
)
282 StackLimit
= (ULONG
)PsGetCurrentThread()->Tcb
.StackBase
;
283 StackBase
= (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
;
287 StackLimit
= (ULONG
)init_stack_top
;
288 StackBase
= (ULONG
)init_stack
;
292 Change to an #if 0 to reduce the amount of information printed on
293 a recursive stack trace.
296 DbgPrint("Frames: ");
297 Frame
= (PULONG
)OldTss
->Ebp
;
298 while (Frame
!= NULL
&& (ULONG
)Frame
>= StackBase
)
300 KeRosPrintAddress((PVOID
)Frame
[1]);
301 Frame
= (PULONG
)Frame
[0];
305 DbgPrint("Frames: ");
307 Frame
= (PULONG
)OldTss
->Ebp
;
308 while (Frame
!= NULL
&& (ULONG
)Frame
>= StackBase
)
310 StackTrace
[i
] = (PVOID
)Frame
[1];
311 Frame
= (PULONG
)Frame
[0];
317 while (i
< TraceLength
)
319 StackRepeatCount
[i
] = 0;
322 while ((j
- i
) <= (TraceLength
- j
) && FoundRepeat
== FALSE
)
324 if (memcmp(&StackTrace
[i
], &StackTrace
[j
],
325 (j
- i
) * sizeof(PVOID
)) == 0)
327 StackRepeatCount
[i
] = 2;
328 StackRepeatLength
[i
] = j
- i
;
336 if (FoundRepeat
== FALSE
)
341 j
= j
+ StackRepeatLength
[i
];
342 while ((TraceLength
- j
) >= StackRepeatLength
[i
] &&
345 if (memcmp(&StackTrace
[i
], &StackTrace
[j
],
346 StackRepeatLength
[i
] * sizeof(PVOID
)) == 0)
348 StackRepeatCount
[i
]++;
349 j
= j
+ StackRepeatLength
[i
];
360 while (i
< TraceLength
)
362 if (StackRepeatCount
[i
] == 0)
364 KeRosPrintAddress(StackTrace
[i
]);
370 if (StackRepeatLength
[i
] == 0)
374 for (j
= 0; j
< StackRepeatLength
[i
]; j
++)
376 KeRosPrintAddress(StackTrace
[i
+ j
]);
378 DbgPrint("}*%d", StackRepeatCount
[i
]);
379 i
= i
+ StackRepeatLength
[i
] * StackRepeatCount
[i
];
390 KiDumpTrapFrame(PKTRAP_FRAME Tf
, ULONG Parameter1
, ULONG Parameter2
)
395 ULONG ExceptionNr
= (ULONG
)Tf
->DebugArgMark
;
396 ULONG cr2
= (ULONG
)Tf
->DebugPointer
;
401 * Print out the CPU registers
403 if (ExceptionNr
< ARRAY_SIZE(ExceptionTypeStrings
))
405 DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings
[ExceptionNr
],
406 ExceptionNr
, Tf
->ErrorCode
&0xffff);
410 DbgPrint("Exception: %d(%x)\n", ExceptionNr
, Tf
->ErrorCode
&0xffff);
412 DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
413 Tf
->Cs
&0xffff, Tf
->Eip
);
414 KeRosPrintAddress((PVOID
)Tf
->Eip
);
416 Ke386GetPageTableDirectory(cr3_
);
417 DbgPrint("cr2 %x cr3 %x ", cr2
, cr3_
);
418 DbgPrint("Proc: %x ",PsGetCurrentProcess());
419 if (PsGetCurrentProcess() != NULL
)
421 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId
);
422 DbgPrint("%.16s> ", PsGetCurrentProcess()->ImageFileName
);
424 if (PsGetCurrentThread() != NULL
)
426 DbgPrint("Thrd: %x Tid: %x",
427 PsGetCurrentThread(),
428 PsGetCurrentThread()->Cid
.UniqueThread
);
431 DbgPrint("DS %x ES %x FS %x GS %x\n", Tf
->Ds
&0xffff, Tf
->Es
&0xffff,
432 Tf
->Fs
&0xffff, Tf
->Gs
&0xfff);
433 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf
->Eax
, Tf
->Ebx
, Tf
->Ecx
);
434 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf
->Edx
,
435 Tf
->Ebp
, Tf
->Esi
, Esp0
);
436 DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf
->Edi
, Tf
->Eflags
);
437 if ((Tf
->Cs
&0xffff) == KERNEL_CS
)
439 DbgPrint("kESP %.8x ", Esp0
);
440 if (PsGetCurrentThread() != NULL
)
442 DbgPrint("kernel stack base %x\n",
443 PsGetCurrentThread()->Tcb
.StackLimit
);
448 if (PsGetCurrentThread() != NULL
)
450 StackLimit
= (ULONG
)PsGetCurrentThread()->Tcb
.StackBase
;
454 StackLimit
= (ULONG
)init_stack_top
;
458 * Dump the stack frames
460 KeDumpStackFrames((PULONG
)Tf
->Ebp
);
464 KiTrapHandler(PKTRAP_FRAME Tf
, ULONG ExceptionNr
)
466 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
467 * message and halt the computer
469 * Complete CPU context
476 /* Store the exception number in an unused field in the trap frame. */
477 Tf
->DebugArgMark
= (PVOID
)ExceptionNr
;
479 /* Use the address of the trap frame as approximation to the ring0 esp */
480 Esp0
= (ULONG
)&Tf
->Eip
;
484 Tf
->DebugPointer
= (PVOID
)cr2
;
486 if (ExceptionNr
== 14 && Tf
->Eflags
& FLAG_IF
)
488 Ke386EnableInterrupts();
492 * If this was a V86 mode exception then handle it specially
494 if (Tf
->Eflags
& (1 << 17))
496 DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf
->Eflags
, Tf
->Eip
, ExceptionNr
);
497 return(KeV86Exception(ExceptionNr
, Tf
, cr2
));
501 * Check for stack underflow, this may be obsolete
503 if (PsGetCurrentThread() != NULL
&&
504 Esp0
< (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
)
506 DPRINT1("Stack underflow (tf->esp %x Limit %x Eip %x)\n",
507 Esp0
, (ULONG
)PsGetCurrentThread()->Tcb
.StackLimit
, Tf
->Eip
);
511 if (ExceptionNr
== 15)
515 * This exception should never occur. The P6 has a bug, which does sometimes deliver
516 * the apic spurious interrupt as exception 15. On an athlon64, I get one exception
517 * in the early boot phase in apic mode (using the smp build). I've looked to the linux
518 * sources. Linux does ignore this exception.
522 DPRINT1("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
527 * Maybe handle the page fault and return
529 if (ExceptionNr
== 14)
531 if (Ke386NoExecute
&& Tf
->ErrorCode
& 0x10 && cr2
>= KERNEL_BASE
)
533 KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY
, 0, 0, 0, 0, Tf
);
535 Status
= MmPageFault(Tf
->Cs
&0xffff,
540 if (NT_SUCCESS(Status
))
547 * Check for a breakpoint that was only for the attention of the debugger.
549 if (ExceptionNr
== 3 && Tf
->Eip
== ((ULONG
)DbgBreakPointNoBugCheck
) + 1)
552 EIP is already adjusted by the processor to point to the instruction
553 after the breakpoint.
559 * Try to handle device-not-present, math-fault and xmm-fault exceptions.
561 if (ExceptionNr
== 7 || ExceptionNr
== 16 || ExceptionNr
== 19)
563 Status
= KiHandleFpuFault(Tf
, ExceptionNr
);
564 if (NT_SUCCESS(Status
))
571 * Handle user exceptions differently
573 if ((Tf
->Cs
& 0xFFFF) == USER_CS
)
575 return(KiUserTrapHandler(Tf
, ExceptionNr
, (PVOID
)cr2
));
579 return(KiKernelTrapHandler(Tf
, ExceptionNr
, (PVOID
)cr2
));
585 KeContextToTrapFrame(PCONTEXT Context
,
586 PKTRAP_FRAME TrapFrame
)
588 /* Start with the basic Registers */
589 if ((Context
->ContextFlags
& CONTEXT_CONTROL
) == CONTEXT_CONTROL
)
591 TrapFrame
->Esp
= Context
->Esp
;
592 TrapFrame
->Ss
= Context
->SegSs
;
593 TrapFrame
->Cs
= Context
->SegCs
;
594 TrapFrame
->Eip
= Context
->Eip
;
595 TrapFrame
->Eflags
= Context
->EFlags
;
596 TrapFrame
->Ebp
= Context
->Ebp
;
599 /* Process the Integer Registers */
600 if ((Context
->ContextFlags
& CONTEXT_INTEGER
) == CONTEXT_INTEGER
)
602 TrapFrame
->Eax
= Context
->Eax
;
603 TrapFrame
->Ebx
= Context
->Ebx
;
604 TrapFrame
->Ecx
= Context
->Ecx
;
605 TrapFrame
->Edx
= Context
->Edx
;
606 TrapFrame
->Esi
= Context
->Esi
;
607 TrapFrame
->Edi
= Context
->Edi
;
610 /* Process the Context Segments */
611 if ((Context
->ContextFlags
& CONTEXT_SEGMENTS
) == CONTEXT_SEGMENTS
)
613 TrapFrame
->Ds
= Context
->SegDs
;
614 TrapFrame
->Es
= Context
->SegEs
;
615 TrapFrame
->Fs
= Context
->SegFs
;
616 TrapFrame
->Gs
= Context
->SegGs
;
619 /* Handle the Debug Registers */
620 if ((Context
->ContextFlags
& CONTEXT_DEBUG_REGISTERS
) == CONTEXT_DEBUG_REGISTERS
)
622 TrapFrame
->Dr0
= Context
->Dr0
;
623 TrapFrame
->Dr1
= Context
->Dr1
;
624 TrapFrame
->Dr2
= Context
->Dr2
;
625 TrapFrame
->Dr3
= Context
->Dr3
;
626 TrapFrame
->Dr6
= Context
->Dr6
;
627 TrapFrame
->Dr7
= Context
->Dr7
;
630 /* Handle FPU and Extended Registers */
631 return KiContextToFxSaveArea((PFX_SAVE_AREA
)(TrapFrame
+ 1), Context
);
635 KeTrapFrameToContext(PKTRAP_FRAME TrapFrame
,
638 if ((Context
->ContextFlags
& CONTEXT_CONTROL
) == CONTEXT_CONTROL
)
640 Context
->SegSs
= TrapFrame
->Ss
;
641 Context
->Esp
= TrapFrame
->Esp
;
642 Context
->SegCs
= TrapFrame
->Cs
;
643 Context
->Eip
= TrapFrame
->Eip
;
644 Context
->EFlags
= TrapFrame
->Eflags
;
645 Context
->Ebp
= TrapFrame
->Ebp
;
647 if ((Context
->ContextFlags
& CONTEXT_INTEGER
) == CONTEXT_INTEGER
)
649 Context
->Eax
= TrapFrame
->Eax
;
650 Context
->Ebx
= TrapFrame
->Ebx
;
651 Context
->Ecx
= TrapFrame
->Ecx
;
653 * NOTE: In the trap frame which is built on entry to a system
654 * call TrapFrame->Edx will actually hold the address of the
655 * previous TrapFrame. I don't believe leaking this information
656 * has security implications. Also EDX holds the address of the
657 * arguments to the system call in progress so it isn't of much
658 * interest to the debugger.
660 Context
->Edx
= TrapFrame
->Edx
;
661 Context
->Esi
= TrapFrame
->Esi
;
662 Context
->Edi
= TrapFrame
->Edi
;
664 if ((Context
->ContextFlags
& CONTEXT_SEGMENTS
) == CONTEXT_SEGMENTS
)
666 Context
->SegDs
= TrapFrame
->Ds
;
667 Context
->SegEs
= TrapFrame
->Es
;
668 Context
->SegFs
= TrapFrame
->Fs
;
669 Context
->SegGs
= TrapFrame
->Gs
;
671 if ((Context
->ContextFlags
& CONTEXT_DEBUG_REGISTERS
) == CONTEXT_DEBUG_REGISTERS
)
674 * FIXME: Implement this case
676 Context
->ContextFlags
&= (~CONTEXT_DEBUG_REGISTERS
) | CONTEXT_i386
;
678 if ((Context
->ContextFlags
& CONTEXT_FLOATING_POINT
) == CONTEXT_FLOATING_POINT
)
681 * FIXME: Implement this case
683 * I think this should only be filled for FPU exceptions, otherwise I
684 * would not know where to get it from as it can be the current state
685 * of the FPU or already saved in the thread's FPU save area.
688 Context
->ContextFlags
&= (~CONTEXT_FLOATING_POINT
) | CONTEXT_i386
;
691 if ((Context
->ContextFlags
& CONTEXT_EXTENDED_REGISTERS
) == CONTEXT_EXTENDED_REGISTERS
)
694 * FIXME: Investigate this
696 * This is the XMM state (first 512 bytes of FXSAVE_FORMAT/FX_SAVE_AREA)
697 * This should only be filled in case of a SIMD exception I think, so
698 * this is not the right place (like for FPU the state could already be
699 * saved in the thread's FX_SAVE_AREA or still be in the CPU)
702 Context
->ContextFlags
&= ~CONTEXT_EXTENDED_REGISTERS
;
708 KeDumpStackFrames(PULONG Frame
)
710 PULONG StackBase
, StackEnd
;
711 MEMORY_BASIC_INFORMATION mbi
;
712 ULONG ResultLength
= sizeof(mbi
);
715 DbgPrint("Frames:\n");
718 Status
= MiQueryVirtualMemory (
721 MemoryBasicInformation
,
725 if ( !NT_SUCCESS(Status
) )
727 DPRINT1("Can't dump stack frames: MiQueryVirtualMemory() failed: %x\n", Status
);
732 StackEnd
= (PULONG
)((ULONG_PTR
)mbi
.BaseAddress
+ mbi
.RegionSize
);
734 while ( Frame
>= StackBase
&& Frame
< StackEnd
)
736 ULONG Addr
= Frame
[1];
737 if (!KeRosPrintAddress((PVOID
)Addr
))
738 DbgPrint("<%X>", Addr
);
739 if ( Addr
== 0 || Addr
== 0xDEADBEEF )
742 Frame
= (PULONG
)Frame
[0];
754 KeRosDumpStackFrames ( PULONG Frame
, ULONG FrameCount
)
757 PULONG StackBase
, StackEnd
;
758 MEMORY_BASIC_INFORMATION mbi
;
759 ULONG ResultLength
= sizeof(mbi
);
762 DbgPrint("Frames: ");
768 __asm__("mov %%ebp, %%ebx" : "=b" (Frame
) : );
769 #elif defined(_MSC_VER)
770 __asm mov
[Frame
], ebp
772 //Frame = (PULONG)Frame[0]; // step out of KeRosDumpStackFrames
775 Status
= MiQueryVirtualMemory (
778 MemoryBasicInformation
,
782 if ( !NT_SUCCESS(Status
) )
784 DPRINT1("Can't dump stack frames: MiQueryVirtualMemory() failed: %x\n", Status
);
789 StackEnd
= (PULONG
)((ULONG_PTR
)mbi
.BaseAddress
+ mbi
.RegionSize
);
791 while ( Frame
>= StackBase
&& Frame
< StackEnd
&& i
++ < FrameCount
)
793 ULONG Addr
= Frame
[1];
794 if (!KeRosPrintAddress((PVOID
)Addr
))
795 DbgPrint("<%X>", Addr
);
796 if ( Addr
== 0 || Addr
== 0xDEADBEEF )
799 Frame
= (PULONG
)Frame
[0];
811 KeRosGetStackFrames ( PULONG Frames
, ULONG FrameCount
)
814 PULONG StackBase
, StackEnd
, Frame
;
815 MEMORY_BASIC_INFORMATION mbi
;
816 ULONG ResultLength
= sizeof(mbi
);
822 __asm__("mov %%ebp, %%ebx" : "=b" (Frame
) : );
823 #elif defined(_MSC_VER)
824 __asm mov
[Frame
], ebp
827 Status
= MiQueryVirtualMemory (
830 MemoryBasicInformation
,
834 if ( !NT_SUCCESS(Status
) )
836 DPRINT1("Can't get stack frames: MiQueryVirtualMemory() failed: %x\n", Status
);
841 StackEnd
= (PULONG
)((ULONG_PTR
)mbi
.BaseAddress
+ mbi
.RegionSize
);
843 while ( Count
< FrameCount
&& Frame
>= StackBase
&& Frame
< StackEnd
)
845 Frames
[Count
++] = Frame
[1];
847 Frame
= (PULONG
)Frame
[0];
858 set_system_call_gate(unsigned int sel
, unsigned int func
)
860 DPRINT("sel %x %d\n",sel
,sel
);
861 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
863 KiIdt
[sel
].b
= 0xef00 + (((int)func
)&0xffff0000);
864 DPRINT("idt[sel].b %x\n",KiIdt
[sel
].b
);
867 static void set_interrupt_gate(unsigned int sel
, unsigned int func
)
869 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel
,func
);
870 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
872 KiIdt
[sel
].b
= 0x8e00 + (((int)func
)&0xffff0000);
875 static void set_trap_gate(unsigned int sel
, unsigned int func
, unsigned int dpl
)
877 DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel
, func
, dpl
);
879 KiIdt
[sel
].a
= (((int)func
)&0xffff) +
881 KiIdt
[sel
].b
= 0x8f00 + (dpl
<< 13) + (((int)func
)&0xffff0000);
885 set_task_gate(unsigned int sel
, unsigned task_sel
)
887 KiIdt
[sel
].a
= task_sel
<< 16;
888 KiIdt
[sel
].b
= 0x8500;
892 KeInitExceptions(VOID
)
894 * FUNCTION: Initalize CPU exception handling
899 DPRINT("KeInitExceptions()\n");
902 * Set up the other gates
904 set_trap_gate(0, (ULONG
)KiTrap0
, 0);
905 set_trap_gate(1, (ULONG
)KiTrap1
, 0);
906 set_trap_gate(2, (ULONG
)KiTrap2
, 0);
907 set_trap_gate(3, (ULONG
)KiTrap3
, 3);
908 set_trap_gate(4, (ULONG
)KiTrap4
, 0);
909 set_trap_gate(5, (ULONG
)KiTrap5
, 0);
910 set_trap_gate(6, (ULONG
)KiTrap6
, 0);
911 set_trap_gate(7, (ULONG
)KiTrap7
, 0);
912 set_task_gate(8, TRAP_TSS_SELECTOR
);
913 set_trap_gate(9, (ULONG
)KiTrap9
, 0);
914 set_trap_gate(10, (ULONG
)KiTrap10
, 0);
915 set_trap_gate(11, (ULONG
)KiTrap11
, 0);
916 set_trap_gate(12, (ULONG
)KiTrap12
, 0);
917 set_trap_gate(13, (ULONG
)KiTrap13
, 0);
918 set_interrupt_gate(14, (ULONG
)KiTrap14
);
919 set_trap_gate(15, (ULONG
)KiTrap15
, 0);
920 set_trap_gate(16, (ULONG
)KiTrap16
, 0);
921 set_trap_gate(17, (ULONG
)KiTrap17
, 0);
922 set_trap_gate(18, (ULONG
)KiTrap18
, 0);
923 set_trap_gate(19, (ULONG
)KiTrap19
, 0);
925 for (i
= 20; i
< 256; i
++)
927 set_trap_gate(i
,(int)KiTrapUnknown
, 0);
930 set_system_call_gate(0x2d,(int)KiDebugService
);
931 set_system_call_gate(0x2e,(int)KiSystemService
);
938 KeRaiseUserException(IN NTSTATUS ExceptionCode
)
941 PKTHREAD Thread
= KeGetCurrentThread();
944 Thread
->Teb
->ExceptionCode
= ExceptionCode
;
946 return(ExceptionCode
);
949 OldEip
= Thread
->TrapFrame
->Eip
;
950 Thread
->TrapFrame
->Eip
= (ULONG_PTR
)LdrpGetSystemDllRaiseExceptionDispatcher();
951 return((NTSTATUS
)OldEip
);
960 IN PEXCEPTION_RECORD ExceptionRecord
,
962 IN BOOLEAN SearchFrames
)
964 PKTHREAD Thread
= KeGetCurrentThread();
965 PKTRAP_FRAME TrapFrame
= Thread
->TrapFrame
;
966 PKTRAP_FRAME PrevTrapFrame
= (PKTRAP_FRAME
)TrapFrame
->Edx
;
968 KeGetCurrentKPCR()->Tib
.ExceptionList
= TrapFrame
->ExceptionList
;
970 KiDispatchException(ExceptionRecord
,
976 /* Restore the user context */
977 Thread
->TrapFrame
= PrevTrapFrame
;
978 __asm__("mov %%ebx, %%esp;\n" "jmp _KiServiceExit": : "b" (TrapFrame
));
980 /* We never get here */
981 return(STATUS_SUCCESS
);