/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ke/i386/exp.c
- * PURPOSE: Handling exceptions
- *
- * PROGRAMMERS: David Welch (welch@cwcom.net)
+ * PURPOSE: Exception Support Code
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
+ * Gregor Anich
+ * David Welch (welch@cwcom.net)
* Skywing (skywing@valhallalegends.com)
*/
+/*
+ * FIXMES:
+ * - Clean up file (remove all stack functions and use RtlWalkFrameChain/RtlCaptureStackBacktrace)
+ * - Sanitize some context fields.
+ * - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
+ * - Forward exceptions to user-mode debugger.
+ */
+
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
-/*
- * FIXMES:
- * - Put back VEH.
- * - Clean up file.
- * - Sanitize some context fields.
- * - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
- * - Implement official stack trace functions (exported) and remove stuff here.
- * - Forward exceptions to user-mode debugger.
- */
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, KeInitExceptions)
+#endif
VOID
NTAPI
-Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
+Ki386AdjustEsp0(
+ IN PKTRAP_FRAME TrapFrame
+);
+
+extern KIDTENTRY KiIdt[];
/* GLOBALS *****************************************************************/
# define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
#endif
-extern void KiSystemService(void);
-extern void KiDebugService(void);
-
-extern VOID KiTrap0(VOID);
-extern VOID KiTrap1(VOID);
-extern VOID KiTrap2(VOID);
-extern VOID KiTrap3(VOID);
-extern VOID KiTrap4(VOID);
-extern VOID KiTrap5(VOID);
-extern VOID KiTrap6(VOID);
-extern VOID KiTrap7(VOID);
-extern VOID KiTrap8(VOID);
-extern VOID KiTrap9(VOID);
-extern VOID KiTrap10(VOID);
-extern VOID KiTrap11(VOID);
-extern VOID KiTrap12(VOID);
-extern VOID KiTrap13(VOID);
-extern VOID KiTrap14(VOID);
-extern VOID KiTrap15(VOID);
-extern VOID KiTrap16(VOID);
-extern VOID KiTrap17(VOID);
-extern VOID KiTrap18(VOID);
-extern VOID KiTrap19(VOID);
-extern VOID KiTrapUnknown(VOID);
-
extern ULONG init_stack;
extern ULONG init_stack_top;
while (current_entry != &ModuleListHead)
{
current =
- CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
+ CONTAINING_RECORD(current_entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
if (address >= (PVOID)current->DllBase &&
address < (PVOID)((ULONG_PTR)current->DllBase + current->SizeOfImage))
{
Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
Er.NumberParameters = 2;
- Er.ExceptionInformation[0] = Tf->ErrorCode & 0x1;
+ Er.ExceptionInformation[0] = Tf->ErrCode & 0x1;
Er.ExceptionInformation[1] = (ULONG)Cr2;
}
else
VOID
KiDoubleFaultHandler(VOID)
{
+#if 0
unsigned int cr2;
ULONG StackLimit;
ULONG StackBase;
#endif
OldTss = KeGetCurrentKPCR()->TSS;
- Esp0 = OldTss->Esp;
+ Esp0 = OldTss->Esp0;
/* Get CR2 */
cr2 = Ke386GetCr2();
DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\nESP: %.8x ", OldTss->Edx,
OldTss->Ebp, OldTss->Esi, Esp0);
DbgPrint("EDI: %.8x EFLAGS: %.8x ", OldTss->Edi, OldTss->Eflags);
- if (OldTss->Cs == KERNEL_CS)
+ if (OldTss->Cs == KGDT_R0_CODE)
{
DbgPrint("kESP %.8x ", Esp0);
if (PsGetCurrentThread() != NULL)
{
DbgPrint("User ESP %.8x\n", OldTss->Esp);
}
- if ((OldTss->Cs & 0xffff) == KERNEL_CS)
+ if ((OldTss->Cs & 0xffff) == KGDT_R0_CODE)
{
if (PsGetCurrentThread() != NULL)
{
DbgPrint("{");
if (StackRepeatLength[i] == 0)
{
- for(;;);
- }
+ for(;;);
+}
for (j = 0; j < StackRepeatLength[i]; j++)
{
KeRosPrintAddress(StackTrace[i + j]);
}
#endif
}
-
+#endif
DbgPrint("\n");
for(;;);
}
ULONG cr3_;
ULONG StackLimit;
ULONG Esp0;
- ULONG ExceptionNr = (ULONG)Tf->DebugArgMark;
- ULONG cr2 = (ULONG)Tf->DebugPointer;
+ ULONG ExceptionNr = (ULONG)Tf->DbgArgMark;
+ ULONG cr2 = (ULONG)Tf->DbgArgPointer;
Esp0 = (ULONG)Tf;
if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
{
DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
- ExceptionNr, Tf->ErrorCode&0xffff);
+ ExceptionNr, Tf->ErrCode&0xffff);
}
else
{
- DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrorCode&0xffff);
+ DbgPrint("Exception: %d(%x)\n", ExceptionNr, Tf->ErrCode&0xffff);
}
DbgPrint("Processor: %d CS:EIP %x:%x ", KeGetCurrentProcessorNumber(),
- Tf->Cs&0xffff, Tf->Eip);
+ Tf->SegCs&0xffff, Tf->Eip);
KeRosPrintAddress((PVOID)Tf->Eip);
DbgPrint("\n");
Ke386GetPageTableDirectory(cr3_);
PsGetCurrentThread()->Cid.UniqueThread);
}
DbgPrint("\n");
- DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->Ds&0xffff, Tf->Es&0xffff,
- Tf->Fs&0xffff, Tf->Gs&0xfff);
+ DbgPrint("DS %x ES %x FS %x GS %x\n", Tf->SegDs&0xffff, Tf->SegEs&0xffff,
+ Tf->SegFs&0xffff, Tf->SegGs&0xfff);
DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", Tf->Eax, Tf->Ebx, Tf->Ecx);
DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x ESP: %.8x\n", Tf->Edx,
Tf->Ebp, Tf->Esi, Esp0);
- DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->Eflags);
- if ((Tf->Cs&0xffff) == KERNEL_CS)
+ DbgPrint("EDI: %.8x EFLAGS: %.8x ", Tf->Edi, Tf->EFlags);
+ if ((Tf->SegCs&0xffff) == KGDT_R0_CODE)
{
DbgPrint("kESP %.8x ", Esp0);
if (PsGetCurrentThread() != NULL)
ASSERT(ExceptionNr != 14);
- /* Store the exception number in an unused field in the trap frame. */
- Tf->DebugArgMark = ExceptionNr;
-
/* Use the address of the trap frame as approximation to the ring0 esp */
Esp0 = (ULONG)&Tf->Eip;
/* Get CR2 */
cr2 = Ke386GetCr2();
- Tf->DebugPointer = cr2;
+ Tf->DbgArgPointer = cr2;
/*
* If this was a V86 mode exception then handle it specially
*/
- if (Tf->Eflags & (1 << 17))
+ if (Tf->EFlags & (1 << 17))
{
- DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->Eflags, Tf->Eip, ExceptionNr);
+ DPRINT("Tf->Eflags, %x, Tf->Eip %x, ExceptionNr: %d\n", Tf->EFlags, Tf->Eip, ExceptionNr);
return(KeV86Exception(ExceptionNr, Tf, cr2));
}
* in the early boot phase in apic mode (using the smp build). I've looked to the linux
* sources. Linux does ignore this exception.
*
- * Hartmut Birr
*/
DPRINT1("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
return(0);
/*
* Handle user exceptions differently
*/
- if ((Tf->Cs & 0xFFFF) == USER_CS)
+ if ((Tf->SegCs & 0xFFFF) == (KGDT_R3_CODE | RPL_MASK))
{
return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
}
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* Check if this is user-mode or V86 */
- if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+ if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & X86_EFLAGS_VM))
{
/* Return it directly */
- return TrapFrame->Esp;
+ return TrapFrame->HardwareEsp;
}
else
{
/* Edited frame */
- if (!(TrapFrame->Cs & FRAME_EDITED))
+ if (!(TrapFrame->SegCs & FRAME_EDITED))
{
/* Return edited value */
return TrapFrame->TempEsp;
else
{
/* Virgin frame, calculate */
- return (ULONG)&TrapFrame->Esp;
+ return (ULONG)&TrapFrame->HardwareEsp;
}
}
}
ULONG Previous = KiEspFromTrapFrame(TrapFrame);
/* Check if this is user-mode or V86 */
- if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
+ if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & X86_EFLAGS_VM))
{
/* Write it directly */
- TrapFrame->Esp = Esp;
+ TrapFrame->HardwareEsp = Esp;
}
else
{
}
/* Create an edit frame, check if it was alrady */
- if (!(TrapFrame->Cs & FRAME_EDITED))
+ if (!(TrapFrame->SegCs & FRAME_EDITED))
{
/* Update the value */
TrapFrame->TempEsp = Esp;
if (Previous != Esp)
{
/* Save CS */
- TrapFrame->TempCs = TrapFrame->Cs;
- TrapFrame->Cs &= ~FRAME_EDITED;
+ TrapFrame->TempSegCs = TrapFrame->SegCs;
+ TrapFrame->SegCs &= ~FRAME_EDITED;
/* Save ESP */
TrapFrame->TempEsp = Esp;
KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* If this was V86 Mode */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* Just return it */
- return TrapFrame->Ss;
+ return TrapFrame->HardwareSegSs;
}
- else if (TrapFrame->Cs & 1)
+ else if (TrapFrame->SegCs & MODE_MASK)
{
/* Usermode, return the User SS */
- return TrapFrame->Ss | 3;
+ return TrapFrame->HardwareSegSs | RPL_MASK;
}
else
{
/* Kernel mode */
- return KERNEL_DS;
+ return KGDT_R0_DATA;
}
}
Ss &= 0xFFFF;
/* If this was V86 Mode */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* Just write it */
- TrapFrame->Ss = Ss;
+ TrapFrame->HardwareSegSs = Ss;
}
- else if (TrapFrame->Cs & 1)
+ else if (TrapFrame->SegCs & MODE_MASK)
{
/* Usermode, save the User SS */
- TrapFrame->Ss = Ss | 3;
+ TrapFrame->HardwareSegSs = Ss | RPL_MASK;
}
}
-BOOLEAN
+VOID
NTAPI
KeContextToTrapFrame(IN PCONTEXT Context,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PKTRAP_FRAME TrapFrame,
+ IN ULONG ContextFlags,
IN KPROCESSOR_MODE PreviousMode)
{
+ PFX_SAVE_AREA FxSaveArea;
+ //ULONG i; Future Use
BOOLEAN V86Switch = FALSE;
/* Start with the basic Registers */
- if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
+ if ((ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
/* Check if we went through a V86 switch */
if ((Context->EFlags & X86_EFLAGS_VM) !=
- (TrapFrame->Eflags & X86_EFLAGS_VM))
+ (TrapFrame->EFlags & X86_EFLAGS_VM))
{
/* We did, remember this for later */
V86Switch = TRUE;
}
/* Copy EFLAGS. FIXME: Needs to be sanitized */
- TrapFrame->Eflags = Context->EFlags;
+ TrapFrame->EFlags = Context->EFlags;
/* Copy EBP and EIP */
TrapFrame->Ebp = Context->Ebp;
TrapFrame->Eip = Context->Eip;
/* Check if we were in V86 Mode */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* Simply copy the CS value */
- TrapFrame->Cs = Context->SegCs;
+ TrapFrame->SegCs = Context->SegCs;
}
else
{
/* We weren't in V86, so sanitize the CS (FIXME!) */
- TrapFrame->Cs = Context->SegCs;
+ TrapFrame->SegCs = Context->SegCs;
/* Don't let it under 8, that's invalid */
- if ((PreviousMode !=KernelMode) && (TrapFrame->Cs < 8))
+ if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8))
{
/* Force it to User CS */
- TrapFrame->Cs = USER_CS;
+ TrapFrame->SegCs = (KGDT_R3_CODE | RPL_MASK);
}
}
}
/* Process the Integer Registers */
- if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
+ if ((ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
{
TrapFrame->Eax = Context->Eax;
TrapFrame->Ebx = Context->Ebx;
}
/* Process the Context Segments */
- if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
+ if ((ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
/* Check if we were in V86 Mode */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* Copy the V86 Segments directlry */
- TrapFrame->V86_Ds = Context->SegDs;
- TrapFrame->V86_Es = Context->SegEs;
- TrapFrame->V86_Fs = Context->SegFs;
- TrapFrame->V86_Gs = Context->SegGs;
+ TrapFrame->V86Ds = Context->SegDs;
+ TrapFrame->V86Es = Context->SegEs;
+ TrapFrame->V86Fs = Context->SegFs;
+ TrapFrame->V86Gs = Context->SegGs;
}
- else if (!(TrapFrame->Cs & 1))
+ else if (!(TrapFrame->SegCs & MODE_MASK))
{
- /* For user mode, write the values directly */
- TrapFrame->Ds = USER_DS;
- TrapFrame->Es = USER_DS;
- TrapFrame->Fs = Context->SegFs;
- TrapFrame->Gs = 0;
+ /* For kernel mode, write the standard values */
+ TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
+ TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
+ TrapFrame->SegFs = Context->SegFs;
+ TrapFrame->SegGs = 0;
}
else
{
- /* For kernel-mode, return the values */
- TrapFrame->Ds = Context->SegDs;
- TrapFrame->Es = Context->SegEs;
- TrapFrame->Fs = Context->SegFs;
+ /* For user mode, return the values directlry */
+ TrapFrame->SegDs = Context->SegDs;
+ TrapFrame->SegEs = Context->SegEs;
+ TrapFrame->SegFs = Context->SegFs;
/* Handle GS specially */
- if (TrapFrame->Cs == USER_CS)
+ if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK))
{
/* Don't use it, if user */
- TrapFrame->Gs = 0;
+ TrapFrame->SegGs = 0;
}
else
{
/* Copy it if kernel */
- TrapFrame->Gs = Context->SegGs;
+ TrapFrame->SegGs = Context->SegGs;
}
}
}
+ /* Handle the extended registers */
+ if (((ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
+ CONTEXT_EXTENDED_REGISTERS) &&
+ ((TrapFrame->SegCs & MODE_MASK) == UserMode))
+ {
+ /* Get the FX Area */
+ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+ /* Check if NPX is present */
+ if (KeI386NpxPresent)
+ {
+ /* Future use */
+ }
+ }
+
+ /* Handle the floating point state */
+ if (((ContextFlags & CONTEXT_FLOATING_POINT) ==
+ CONTEXT_FLOATING_POINT) &&
+ ((TrapFrame->SegCs & MODE_MASK) == UserMode))
+ {
+ /* Get the FX Area */
+ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+ /* Check if NPX is present */
+ if (KeI386NpxPresent)
+ {
+ /* Future use */
+ }
+ else
+ {
+ /* Future use */
+ }
+ }
+
/* Handle the Debug Registers */
- if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
+ if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
{
/* FIXME: All these should be sanitized */
TrapFrame->Dr0 = Context->Dr0;
if (PreviousMode != KernelMode)
{
/* Set the Debug Flag */
- KeGetCurrentThread()->DebugActive = (Context->Dr7 & DR7_ACTIVE);
+ KeGetCurrentThread()->DispatcherHeader.DebugActive =
+ (Context->Dr7 & DR7_ACTIVE);
}
}
/* Handle FPU and Extended Registers */
- return KiContextToFxSaveArea((PFX_SAVE_AREA)(TrapFrame + 1), Context);
+ KiContextToFxSaveArea((PFX_SAVE_AREA)(TrapFrame + 1), Context);
}
VOID
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT Context)
{
+ PFX_SAVE_AREA FxSaveArea = NULL;
+
/* Start with the Control flags */
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
/* EBP, EIP and EFLAGS */
Context->Ebp = TrapFrame->Ebp;
Context->Eip = TrapFrame->Eip;
- Context->EFlags = TrapFrame->Eflags;
+ Context->EFlags = TrapFrame->EFlags;
/* Return the correct CS */
- if (!(TrapFrame->Cs & FRAME_EDITED) &&
- !(TrapFrame->Eflags & X86_EFLAGS_VM))
+ if (!(TrapFrame->SegCs & FRAME_EDITED) &&
+ !(TrapFrame->EFlags & X86_EFLAGS_VM))
{
/* Get it from the Temp location */
- Context->SegCs = TrapFrame->TempCs & 0xFFFF;
+ Context->SegCs = TrapFrame->TempSegCs & 0xFFFF;
}
else
{
/* Return it directly */
- Context->SegCs = TrapFrame->Cs & 0xFFFF;
+ Context->SegCs = TrapFrame->SegCs & 0xFFFF;
}
/* Get the Ss and ESP */
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
/* Do V86 Mode first */
- if (TrapFrame->Eflags & X86_EFLAGS_VM)
+ if (TrapFrame->EFlags & X86_EFLAGS_VM)
{
/* Return from the V86 location */
- Context->SegGs = TrapFrame->V86_Gs & 0xFFFF;
- Context->SegFs = TrapFrame->V86_Fs & 0xFFFF;
- Context->SegEs = TrapFrame->V86_Es & 0xFFFF;
- Context->SegDs = TrapFrame->V86_Ds & 0xFFFF;
+ Context->SegGs = TrapFrame->V86Gs & 0xFFFF;
+ Context->SegFs = TrapFrame->V86Fs & 0xFFFF;
+ Context->SegEs = TrapFrame->V86Es & 0xFFFF;
+ Context->SegDs = TrapFrame->V86Ds & 0xFFFF;
}
else
{
/* Check if this was a Kernel Trap */
- if (TrapFrame->Cs == KERNEL_CS)
+ if (TrapFrame->SegCs == KGDT_R0_CODE)
{
/* Set valid selectors */
- TrapFrame->Gs = 0;
- TrapFrame->Fs = PCR_SELECTOR;
- TrapFrame->Es = USER_DS;
- TrapFrame->Ds = USER_DS;
+ TrapFrame->SegGs = 0;
+ TrapFrame->SegFs = KGDT_R0_PCR;
+ TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
+ TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
}
/* Return the segments */
- Context->SegGs = TrapFrame->Gs & 0xFFFF;
- Context->SegFs = TrapFrame->Fs & 0xFFFF;
- Context->SegEs = TrapFrame->Es & 0xFFFF;
- Context->SegDs = TrapFrame->Ds & 0xFFFF;
+ Context->SegGs = TrapFrame->SegGs & 0xFFFF;
+ Context->SegFs = TrapFrame->SegFs & 0xFFFF;
+ Context->SegEs = TrapFrame->SegEs & 0xFFFF;
+ Context->SegDs = TrapFrame->SegDs & 0xFFFF;
}
}
Context->Edi = TrapFrame->Edi;
}
- if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
- {
- /*
- * FIXME: Implement this case
- */
- Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
- }
- if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
- {
- /*
- * FIXME: Implement this case
- *
- * I think this should only be filled for FPU exceptions, otherwise I
- * would not know where to get it from as it can be the current state
- * of the FPU or already saved in the thread's FPU save area.
- * -blight
- */
- Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
- }
-#if 0
- if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
- {
- /*
- * FIXME: Investigate this
- *
- * This is the XMM state (first 512 bytes of FXSAVE_FORMAT/FX_SAVE_AREA)
- * This should only be filled in case of a SIMD exception I think, so
- * this is not the right place (like for FPU the state could already be
- * saved in the thread's FX_SAVE_AREA or still be in the CPU)
- * -blight
- */
- Context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS;
- }
-#endif
+ /* Handle extended registers */
+ if (((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
+ CONTEXT_EXTENDED_REGISTERS) &&
+ ((TrapFrame->SegCs & MODE_MASK) == UserMode))
+ {
+ /* Get the FX Save Area */
+ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+ /* Make sure NPX is present */
+ if (KeI386NpxPresent)
+ {
+ /* Future use */
+ }
+
+ /* Old code */
+ FxSaveArea = KiGetFpuState(KeGetCurrentThread());
+ if (FxSaveArea != NULL)
+ {
+ memcpy(Context->ExtendedRegisters, &FxSaveArea->U.FxArea,
+ min(sizeof (Context->ExtendedRegisters), sizeof (FxSaveArea->U.FxArea)) );
+ }
+ else
+ {
+ Context->ContextFlags &= (~CONTEXT_EXTENDED_REGISTERS) | CONTEXT_i386;
+ }
+ }
+
+ /* Handle Floating Point */
+ if (((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
+ CONTEXT_FLOATING_POINT) &&
+ ((TrapFrame->SegCs & MODE_MASK) == UserMode))
+ {
+ /* Get the FX Save Area */
+ FxSaveArea = (PFX_SAVE_AREA)(TrapFrame + 1);
+
+ /* Make sure we have an NPX */
+ if (KeI386NpxPresent)
+ {
+ /* Future use */
+ }
+ else
+ {
+ /* Future Use */
+ }
+
+ /* Old code */
+ FxSaveArea = KiGetFpuState(KeGetCurrentThread());
+ if (FxSaveArea != NULL)
+ {
+ KiFxSaveAreaToFloatingSaveArea(&Context->FloatSave, FxSaveArea);
+ }
+ else
+ {
+ Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
+ }
+ }
+
+ /* Handle debug registers */
+ if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
+ CONTEXT_DEBUG_REGISTERS)
+ {
+ /* Copy the debug registers */
+ Context->Dr0 = TrapFrame->Dr0;
+ Context->Dr1 = TrapFrame->Dr1;
+ Context->Dr2 = TrapFrame->Dr2;
+ Context->Dr3 = TrapFrame->Dr3;
+ Context->Dr6 = TrapFrame->Dr6;
+
+ /* For user-mode, only set DR7 if a debugger is active */
+ if (((TrapFrame->SegCs & MODE_MASK) ||
+ (TrapFrame->EFlags & EFLAGS_V86_MASK)) &&
+ (KeGetCurrentThread()->DispatcherHeader.DebugActive))
+ {
+ /* Copy it over */
+ Context->Dr7 = TrapFrame->Dr7;
+ }
+ else
+ {
+ /* Clear it */
+ Context->Dr7 = 0;
+ }
+ }
}
VOID
if ( !Frame )
{
#if defined __GNUC__
- __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
+ __asm__("mov %%ebp, %0" : "=r" (Frame) : );
#elif defined(_MSC_VER)
__asm mov [Frame], ebp
#endif
_SEH_TRY
{
#if defined __GNUC__
- __asm__("mov %%ebp, %%ebx" : "=b" (Frame) : );
+ __asm__("mov %%ebp, %0" : "=r" (Frame) : );
#elif defined(_MSC_VER)
__asm mov [Frame], ebp
#endif
return Count;
}
-static void
-set_system_call_gate(unsigned int sel, unsigned int func)
-{
- DPRINT("sel %x %d\n",sel,sel);
- KiIdt[sel].a = (((int)func)&0xffff) +
- (KERNEL_CS << 16);
- KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
- DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
-}
-
-static void set_interrupt_gate(unsigned int sel, unsigned int func)
-{
- DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
- KiIdt[sel].a = (((int)func)&0xffff) +
- (KERNEL_CS << 16);
- KiIdt[sel].b = 0x8e00 + (((int)func)&0xffff0000);
-}
-
-static void set_trap_gate(unsigned int sel, unsigned int func, unsigned int dpl)
-{
- DPRINT("set_trap_gate(sel %d, func %x, dpl %d)\n",sel, func, dpl);
- ASSERT(dpl <= 3);
- KiIdt[sel].a = (((int)func)&0xffff) +
- (KERNEL_CS << 16);
- KiIdt[sel].b = 0x8f00 + (dpl << 13) + (((int)func)&0xffff0000);
-}
-
-static void
-set_task_gate(unsigned int sel, unsigned task_sel)
-{
- KiIdt[sel].a = task_sel << 16;
- KiIdt[sel].b = 0x8500;
-}
-
VOID
INIT_FUNCTION
NTAPI
KeInitExceptions(VOID)
-/*
- * FUNCTION: Initalize CPU exception handling
- */
{
- int i;
-
- DPRINT("KeInitExceptions()\n");
+ ULONG i;
+ USHORT FlippedSelector;
- /*
- * Set up the other gates
- */
- set_trap_gate(0, (ULONG)KiTrap0, 0);
- set_trap_gate(1, (ULONG)KiTrap1, 0);
- set_trap_gate(2, (ULONG)KiTrap2, 0);
- set_trap_gate(3, (ULONG)KiTrap3, 3);
- set_trap_gate(4, (ULONG)KiTrap4, 0);
- set_trap_gate(5, (ULONG)KiTrap5, 0);
- set_trap_gate(6, (ULONG)KiTrap6, 0);
- set_trap_gate(7, (ULONG)KiTrap7, 0);
- set_task_gate(8, TRAP_TSS_SELECTOR);
- set_trap_gate(9, (ULONG)KiTrap9, 0);
- set_trap_gate(10, (ULONG)KiTrap10, 0);
- set_trap_gate(11, (ULONG)KiTrap11, 0);
- set_trap_gate(12, (ULONG)KiTrap12, 0);
- set_trap_gate(13, (ULONG)KiTrap13, 0);
- set_interrupt_gate(14, (ULONG)KiTrap14);
- set_trap_gate(15, (ULONG)KiTrap15, 0);
- set_trap_gate(16, (ULONG)KiTrap16, 0);
- set_trap_gate(17, (ULONG)KiTrap17, 0);
- set_trap_gate(18, (ULONG)KiTrap18, 0);
- set_trap_gate(19, (ULONG)KiTrap19, 0);
-
- for (i = 20; i < 256; i++)
- {
- set_trap_gate(i,(int)KiTrapUnknown, 0);
- }
+ /* Loop the IDT */
+ for (i = 0; i <= MAXIMUM_IDTVECTOR; i ++)
+ {
+ /* Save the current Selector */
+ FlippedSelector = KiIdt[i].Selector;
- set_system_call_gate(0x2d,(int)KiDebugService);
- set_system_call_gate(0x2e,(int)KiSystemService);
+ /* Flip Selector and Extended Offset */
+ KiIdt[i].Selector = KiIdt[i].ExtendedOffset;
+ KiIdt[i].ExtendedOffset = FlippedSelector;
+ }
}
VOID
{
/* Add the FPU Flag */
Context.ContextFlags |= CONTEXT_FLOATING_POINT;
+ if (KeI386FxsrPresent) Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
}
/* Get a Context */
&Context,
TrapFrame,
TRUE,
- FALSE);
+ TRUE);
/* Exit if we're continuing */
if (Action == kdContinue) goto Handled;
/* Probe stack and copy Context */
ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
- RtlMoveMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
+ RtlCopyMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
/* Align exception record size and get stack pointer */
Size = (sizeof(EXCEPTION_RECORD) -
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
Size + 2 * sizeof(ULONG_PTR),
sizeof(ULONG));
- RtlMoveMemory((PVOID)NewStack, ExceptionRecord, Size);
+ RtlCopyMemory((PVOID)NewStack, ExceptionRecord, Size);
/* Now write the two params for the user-mode dispatcher */
*(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) = Stack;
Handled:
/* Convert the context back into Trap/Exception Frames */
- KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
+ KeContextToTrapFrame(&Context,
+ NULL,
+ TrapFrame,
+ Context.ContextFlags,
+ PreviousMode);
return;
}
/*
* @implemented
*/
-NTSTATUS STDCALL
+NTSTATUS
+NTAPI
KeRaiseUserException(IN NTSTATUS ExceptionCode)
{
ULONG OldEip;
PKTHREAD Thread = KeGetCurrentThread();
- _SEH_TRY {
+ /* Make sure we can access the TEB */
+ _SEH_TRY
+ {
Thread->Teb->ExceptionCode = ExceptionCode;
- } _SEH_HANDLE {
+ }
+ _SEH_HANDLE
+ {
return(ExceptionCode);
- } _SEH_END;
+ }
+ _SEH_END;
+
+ /* Get the old EIP */
+ OldEip = Thread->TrapFrame->Eip;
+
+ /* Change it to the user-mode dispatcher */
+ Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher;
- OldEip = Thread->TrapFrame->Eip;
- Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher;
- return((NTSTATUS)OldEip);
+ /* Return the old EIP */
+ return((NTSTATUS)OldEip);
}