diff --git a/reactos/include/ndk/asm.h b/reactos/include/ndk/asm.h index 4e22a69fa02..a4d348ac16b 100644 --- a/reactos/include/ndk/asm.h +++ b/reactos/include/ndk/asm.h @@ -110,6 +110,7 @@ Author: #define KPCR_TEB 0x18 #define KPCR_SELF 0x1C #define KPCR_PRCB 0x20 +#define KPCR_IRQL 0x24 #define KPCR_KD_VERSION_BLOCK 0x34 #define KPCR_GDT 0x3C #define KPCR_TSS 0x40 @@ -121,6 +122,7 @@ Author: #define KPCR_NPX_THREAD 0x2F4 #define KPCR_DR6 0x428 #define KPCR_DR7 0x42C +#define KPCR_SYSTEM_CALLS 0x6B8 // // KGDTENTRY Offsets @@ -142,6 +144,12 @@ Author: #define SIZEOF_FX_SAVE_AREA 528 #define NPX_FRAME_LENGTH 0x210 +// +// NPX States +// +#define NPX_STATE_NOT_LOADED 0xA +#define NPX_STATE_LOADED 0x0 + // // Trap Frame Offsets // diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 92922b1dfb5..5f4a6b37fb5 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -41,6 +41,9 @@ extern PVOID KeUserExceptionDispatcher; extern PVOID KeRaiseUserExceptionDispatcher; extern LARGE_INTEGER SystemBootTime; extern ULONG_PTR KERNEL_BASE; +extern ULONG KeI386NpxPresent; +extern ULONG KeI386XMMIPresent; +extern ULONG KeI386FxsrPresent; /* MACROS *************************************************************************/ @@ -475,12 +478,13 @@ PULONG NTAPI KeGetStackTopThread(struct _ETHREAD* Thread); -BOOLEAN +VOID STDCALL KeContextToTrapFrame( PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame, + ULONG ContextFlags, KPROCESSOR_MODE PreviousMode ); diff --git a/reactos/ntoskrnl/kd/wrappers/gdbstub.c b/reactos/ntoskrnl/kd/wrappers/gdbstub.c index d9b53c4a198..64047de09b3 100644 --- a/reactos/ntoskrnl/kd/wrappers/gdbstub.c +++ b/reactos/ntoskrnl/kd/wrappers/gdbstub.c @@ -1720,7 +1720,7 @@ GspBreakIn(PKINTERRUPT Interrupt, KdpGdbEnterDebuggerException(NULL, &Context, TrapFrame); - KeContextToTrapFrame(&Context, NULL, TrapFrame, KernelMode); + KeContextToTrapFrame(&Context, NULL, TrapFrame, Context.ContextFlags, KernelMode); KeLowerIrql(OldIrql); diff --git a/reactos/ntoskrnl/ke/exception.c b/reactos/ntoskrnl/ke/exception.c index 872df7240bc..4f762dd7b65 100644 --- a/reactos/ntoskrnl/ke/exception.c +++ b/reactos/ntoskrnl/ke/exception.c @@ -28,7 +28,11 @@ KiContinuePreviousModeUser(IN PCONTEXT Context, Context = &LocalContext; /* Convert the context into Exception/Trap Frames */ - KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame, UserMode); + KeContextToTrapFrame(&LocalContext, + ExceptionFrame, + TrapFrame, + LocalContext.ContextFlags, + UserMode); } NTSTATUS @@ -62,7 +66,11 @@ KiContinue(IN PCONTEXT Context, else { /* Convert the context into Exception/Trap Frames */ - KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, KernelMode); + KeContextToTrapFrame(Context, + ExceptionFrame, + TrapFrame, + Context->ContextFlags, + KernelMode); } } _SEH_HANDLE @@ -142,7 +150,11 @@ KiRaiseException(PEXCEPTION_RECORD ExceptionRecord, if (NT_SUCCESS(Status)) { /* Convert the context record */ - KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, PreviousMode); + KeContextToTrapFrame(Context, + ExceptionFrame, + TrapFrame, + Context->ContextFlags, + PreviousMode); /* Dispatch the exception */ KiDispatchException(ExceptionRecord, diff --git a/reactos/ntoskrnl/ke/i386/exp.c b/reactos/ntoskrnl/ke/i386/exp.c index 0f313b8f6b8..11d5f273347 100644 --- a/reactos/ntoskrnl/ke/i386/exp.c +++ b/reactos/ntoskrnl/ke/i386/exp.c @@ -1,10 +1,11 @@ /* * 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) */ @@ -22,7 +23,6 @@ /* * FIXMES: - * - Put back VEH. * - Clean up file. * - Sanitize some context fields. * - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord). @@ -689,17 +689,20 @@ KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame, } } -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) != @@ -746,7 +749,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, } /* 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; @@ -757,7 +760,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, } /* 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) @@ -770,7 +773,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, } else if (!(TrapFrame->SegCs & MODE_MASK)) { - /* For user mode, write the values directly */ + /* 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; @@ -778,7 +781,7 @@ KeContextToTrapFrame(IN PCONTEXT Context, } else { - /* For kernel-mode, return the values */ + /* For user mode, return the values directlry */ TrapFrame->SegDs = Context->SegDs; TrapFrame->SegEs = Context->SegEs; TrapFrame->SegFs = Context->SegFs; @@ -797,8 +800,42 @@ KeContextToTrapFrame(IN PCONTEXT Context, } } + /* 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; @@ -812,12 +849,13 @@ KeContextToTrapFrame(IN PCONTEXT Context, if (PreviousMode != KernelMode) { /* Set the Debug Flag */ - KeGetCurrentThread()->DispatcherHeader.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 @@ -898,15 +936,52 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, Context->Edi = TrapFrame->Edi; } - if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS) + /* Handle extended registers */ + if (((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == + CONTEXT_EXTENDED_REGISTERS) && + ((TrapFrame->SegCs & MODE_MASK) == UserMode)) { - /* - * FIXME: Implement this case - */ - Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386; + /* 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; + } } - if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT) + + /* 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) { @@ -917,18 +992,30 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame, Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386; } } - if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS) + + /* Handle debug registers */ + if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == + CONTEXT_DEBUG_REGISTERS) { - if (FxSaveArea == NULL) - FxSaveArea = KiGetFpuState(KeGetCurrentThread()); - if (FxSaveArea != NULL) + /* 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)) { - memcpy(Context->ExtendedRegisters, &FxSaveArea->U.FxArea, - min(sizeof (Context->ExtendedRegisters), sizeof (FxSaveArea->U.FxArea)) ); + /* Copy it over */ + Context->Dr7 = TrapFrame->Dr7; } else { - Context->ContextFlags &= (~CONTEXT_EXTENDED_REGISTERS) | CONTEXT_i386; + /* Clear it */ + Context->Dr7 = 0; } } } @@ -1187,11 +1274,9 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, /* Check if User Mode */ if (PreviousMode == UserMode) { - extern ULONG FxsrSupport; /* Add the FPU Flag */ Context.ContextFlags |= CONTEXT_FLOATING_POINT; - if (FxsrSupport) - Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS; + if (KeI386FxsrPresent) Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS; } /* Get a Context */ @@ -1321,27 +1406,42 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord, 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; - OldEip = Thread->TrapFrame->Eip; - Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher; - return((NTSTATUS)OldEip); + /* Get the old EIP */ + OldEip = Thread->TrapFrame->Eip; + + /* Change it to the user-mode dispatcher */ + Thread->TrapFrame->Eip = (ULONG_PTR)KeRaiseUserExceptionDispatcher; + + /* Return the old EIP */ + return((NTSTATUS)OldEip); } diff --git a/reactos/ntoskrnl/ke/i386/fpu.c b/reactos/ntoskrnl/ke/i386/fpu.c index 7ec5d77548d..45461967e1b 100644 --- a/reactos/ntoskrnl/ke/i386/fpu.c +++ b/reactos/ntoskrnl/ke/i386/fpu.c @@ -1,11 +1,10 @@ -/* $Id$ - * +/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/fpu.c * PURPOSE: Handles the FPU - * * PROGRAMMERS: David Welch (welch@mcmail.com) + * Gregor Anich */ /* INCLUDES *****************************************************************/ @@ -39,9 +38,11 @@ /* GLOBALS *******************************************************************/ -ULONG HardwareMathSupport = 0; -static ULONG MxcsrFeatureMask = 0, XmmSupport = 0; -ULONG FxsrSupport = 0; /* used by Ki386ContextSwitch for SMP */ +extern ULONG KeI386NpxPresent; +extern ULONG KeI386XMMIPresent; +extern ULONG KeI386FxsrPresent; + +static ULONG MxcsrFeatureMask = 0; /* FUNCTIONS *****************************************************************/ @@ -122,7 +123,7 @@ KiFnsaveToFxsaveFormat(PFXSAVE_FORMAT FxSave, PFNSAVE_FORMAT FnSave) FxSave->ErrorSelector = FnSave->ErrorSelector & 0x0000ffff; FxSave->DataOffset = FnSave->DataOffset; FxSave->DataSelector = FnSave->DataSelector & 0x0000ffff; - if (XmmSupport) + if (KeI386XMMIPresent) FxSave->MXCsr = 0x00001f80 & MxcsrFeatureMask; else FxSave->MXCsr = 0; @@ -160,7 +161,7 @@ KiFxsaveToFnsaveFormat(PFNSAVE_FORMAT FnSave, PFXSAVE_FORMAT FxSave) STATIC VOID KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, FLOATING_SAVE_AREA *FloatingSaveArea) { - if (FxsrSupport) + if (KeI386FxsrPresent) { KiFnsaveToFxsaveFormat(&FxSaveArea->U.FxArea, (PFNSAVE_FORMAT)FloatingSaveArea); } @@ -176,7 +177,7 @@ KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, FLOATING_SAVE_AREA *Flo VOID KiFxSaveAreaToFloatingSaveArea(FLOATING_SAVE_AREA *FloatingSaveArea, CONST PFX_SAVE_AREA FxSaveArea) { - if (FxsrSupport) + if (KeI386FxsrPresent) { KiFxsaveToFnsaveFormat((PFNSAVE_FORMAT)FloatingSaveArea, &FxSaveArea->U.FxArea); } @@ -203,7 +204,7 @@ KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context) /* Now merge the FX_SAVE_AREA from the context with the destination area */ if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS) { - if (FxsrSupport) + if (KeI386FxsrPresent) { PFXSAVE_FORMAT src = (PFXSAVE_FORMAT)Context->ExtendedRegisters; PFXSAVE_FORMAT dst = &FxSaveArea->U.FxArea; @@ -245,9 +246,9 @@ KiCheckFPU(VOID) Ke386SaveFlags(Flags); Ke386DisableInterrupts(); - HardwareMathSupport = 0; - FxsrSupport = 0; - XmmSupport = 0; + KeI386NpxPresent = 0; + KeI386FxsrPresent = 0; + KeI386XMMIPresent = 0; cr0 = Ke386GetCr0(); cr0 |= X86_CR0_NE | X86_CR0_MP; @@ -284,7 +285,7 @@ KiCheckFPU(VOID) #error Unknown compiler for inline assembler #endif - HardwareMathSupport = 1; + KeI386NpxPresent = 1; /* check for and enable MMX/SSE support if possible */ if ((Prcb->FeatureBits & X86_FEATURE_FXSR) != 0) @@ -293,7 +294,7 @@ KiCheckFPU(VOID) PFX_SAVE_AREA FxSaveArea; /* enable FXSR */ - FxsrSupport = 1; + KeI386FxsrPresent = 1; /* we need a 16 byte aligned FX_SAVE_AREA */ FxSaveArea = (PFX_SAVE_AREA)(((ULONG_PTR)DummyArea + 0xf) & (~0x0f)); @@ -313,7 +314,7 @@ KiCheckFPU(VOID) Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT); /* enable SSE */ - XmmSupport = 1; + KeI386XMMIPresent = 1; } Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS); @@ -338,7 +339,7 @@ KiGetFpuState(PKTHREAD Thread) Cr0 = Ke386GetCr0(); asm volatile("clts"); - if (FxsrSupport) + if (KeI386FxsrPresent) asm volatile("fxsave %0" : : "m"(FxSaveArea->U.FxArea)); else { @@ -399,7 +400,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) KeGetCurrentPrcb()->NpxThread = NULL; FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)NpxThread->InitialStack - sizeof (FX_SAVE_AREA)); /* the fnsave might raise a delayed #MF exception */ - if (FxsrSupport) + if (KeI386FxsrPresent) { asm volatile("fxsave %0" : : "m"(FxSaveArea->U.FxArea)); } @@ -417,7 +418,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)CurrentThread->InitialStack - sizeof (FX_SAVE_AREA)); if (CurrentThread->NpxState & NPX_STATE_VALID) { - if (FxsrSupport) + if (KeI386FxsrPresent) { FxSaveArea->U.FxArea.MXCsr &= MxcsrFeatureMask; asm volatile("fxrstor %0" : : "m"(FxSaveArea->U.FxArea)); @@ -430,11 +431,11 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr) else /* NpxState & NPX_STATE_INVALID */ { DPRINT("Setting up clean FPU state\n"); - if (FxsrSupport) + if (KeI386FxsrPresent) { memset(&FxSaveArea->U.FxArea, 0, sizeof(FxSaveArea->U.FxArea)); FxSaveArea->U.FxArea.ControlWord = 0x037f; - if (XmmSupport) + if (KeI386XMMIPresent) { FxSaveArea->U.FxArea.MXCsr = 0x00001f80 & MxcsrFeatureMask; } @@ -550,7 +551,7 @@ KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save) ASSERT_IRQL(DISPATCH_LEVEL); /* check if we are doing software emulation */ - if (!HardwareMathSupport) + if (!KeI386NpxPresent) { return STATUS_ILLEGAL_FLOAT_CONTEXT; } diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index 0b31acbad52..e362f9c565f 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -26,6 +26,9 @@ BOOLEAN Ke386NoExecute = FALSE; BOOLEAN Ke386Pae = FALSE; BOOLEAN Ke386GlobalPagesEnabled = FALSE; ULONG KiFastSystemCallDisable = 1; +ULONG KeI386NpxPresent = 0; +ULONG KeI386XMMIPresent = 0; +ULONG KeI386FxsrPresent = 0; extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS]; extern ULONG IdleProcessorMask; diff --git a/reactos/ntoskrnl/ke/i386/thread.c b/reactos/ntoskrnl/ke/i386/thread.c index ed559d3acfd..9a1b5cf842b 100644 --- a/reactos/ntoskrnl/ke/i386/thread.c +++ b/reactos/ntoskrnl/ke/i386/thread.c @@ -3,8 +3,7 @@ * PROJECT: ReactOS kernel * FILE: ntoskrnl/ke/i386/thread.c * PURPOSE: i386 Thread Context Creation - * - * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) */ /* INCLUDES ****************************************************************/ @@ -13,13 +12,15 @@ #define NDEBUG #include -typedef struct _KSHARED_CTXSWITCH_FRAME { +typedef struct _KSHARED_CTXSWITCH_FRAME +{ ULONG Esp0; PVOID ExceptionList; PVOID RetEip; } KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME; -typedef struct _KSTART_FRAME { +typedef struct _KSTART_FRAME +{ PKSYSTEM_ROUTINE SystemRoutine; PKSTART_ROUTINE StartRoutine; PVOID StartContext; @@ -65,38 +66,112 @@ Ke386InitThreadWithContext(PKTHREAD Thread, PKSYSTEM_ROUTINE SystemRoutine, PKSTART_ROUTINE StartRoutine, PVOID StartContext, - PCONTEXT Context) + PCONTEXT ContextPointer) { PFX_SAVE_AREA FxSaveArea; + PFXSAVE_FORMAT FxSaveFormat; PKSTART_FRAME StartFrame; PKSHARED_CTXSWITCH_FRAME CtxSwitchFrame; - PKTRAP_FRAME TrapFrame = NULL; + PKTRAP_FRAME TrapFrame; + CONTEXT LocalContext; + PCONTEXT Context = NULL; + ULONG ContextFlags; /* Check if this is a With-Context Thread */ DPRINT("Ke386InitThreadContext\n"); - if (Context) + if (ContextPointer) { /* Set up the Initial Frame */ PKUINIT_FRAME InitFrame; - InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack - sizeof(KUINIT_FRAME)); - DPRINT("Setting up a user-mode thread with the Frame at: %x\n", InitFrame); + InitFrame = (PKUINIT_FRAME)((ULONG_PTR)Thread->InitialStack - + sizeof(KUINIT_FRAME)); + DPRINT("Setting up a user-mode thread. InitFrame at: %p\n", InitFrame); + + /* Copy over the context we got */ + RtlMoveMemory(&LocalContext, ContextPointer, sizeof(CONTEXT)); + Context = &LocalContext; + ContextFlags = CONTEXT_CONTROL; + + /* Setup the Fx Area */ + FxSaveArea = &InitFrame->FxSaveArea; + + /* Check if we support FXsr */ + if (KeI386FxsrPresent) + { + /* Get the FX Save Format Area */ + FxSaveFormat = (PFXSAVE_FORMAT)Context->ExtendedRegisters; + + /* Set an initial state */ + FxSaveFormat->ControlWord = 0x27F; + FxSaveFormat->StatusWord = 0; + FxSaveFormat->TagWord = 0; + FxSaveFormat->ErrorOffset = 0; + FxSaveFormat->ErrorSelector = 0; + FxSaveFormat->DataOffset =0; + FxSaveFormat->DataSelector = 0; + FxSaveFormat->MXCsr = 0x1F80; + } + else + { + /* Setup the regular save area */ + Context->FloatSave.ControlWord = 0x27F; + Context->FloatSave.StatusWord = 0; + Context->FloatSave.TagWord = -1; + Context->FloatSave.ErrorOffset = 0; + Context->FloatSave.ErrorSelector = 0; + Context->FloatSave.DataOffset =0; + Context->FloatSave.DataSelector = 0; + } + + /* Check if the CPU has NPX */ + if (KeI386NpxPresent) + { + /* Set an intial NPX State */ + Context->FloatSave.Cr0NpxState = 0; + FxSaveArea->Cr0NpxState = 0; + FxSaveArea->NpxSavedCpu = 0; + + /* Now set the context flags depending on XMM support */ + ContextFlags |= (KeI386XMMIPresent) ? CONTEXT_EXTENDED_REGISTERS : + CONTEXT_FLOATING_POINT; + + /* Set the Thread's NPX State */ + Thread->NpxState = NPX_STATE_NOT_LOADED; + Thread->DispatcherHeader.NpxIrql = PASSIVE_LEVEL; + } + else + { + /* We'll use emulation */ + FxSaveArea->Cr0NpxState = CR0_EM; + Thread->NpxState = NPX_STATE_NOT_LOADED &~ CR0_MP; + } + + /* Disable any debug regiseters */ + Context->Dr0 = 0; + Context->Dr1 = 0; + Context->Dr2 = 0; + Context->Dr3 = 0; + Context->Dr6 = 0; + Context->Dr7 = 0; + Context->ContextFlags &= ~CONTEXT_DEBUG_REGISTERS; /* Setup the Trap Frame */ TrapFrame = &InitFrame->TrapFrame; /* Set up a trap frame from the context. */ - if (KeContextToTrapFrame(Context, NULL, TrapFrame, UserMode)) - { - Thread->NpxState = NPX_STATE_VALID; - } - else - { - Thread->NpxState = NPX_STATE_INVALID; - } + KeContextToTrapFrame(Context, + NULL, + TrapFrame, + Context->ContextFlags | ContextFlags, + UserMode); - /* Enable Interrupts and disable some unsupported flags right now */ - TrapFrame->EFlags = Context->EFlags | X86_EFLAGS_IF; - TrapFrame->EFlags &= ~(X86_EFLAGS_VM | X86_EFLAGS_NT | X86_EFLAGS_IOPL); + /* Set SS, DS, ES's RPL Mask properly */ + TrapFrame->HardwareSegSs |= RPL_MASK; + TrapFrame->SegDs |= RPL_MASK; + TrapFrame->SegEs |= RPL_MASK; + + /* Set the debug mark */ + TrapFrame->DbgArgMark = 0xBADB0D00; /* Set the previous mode as user */ TrapFrame->PreviousPreviousMode = UserMode; @@ -116,19 +191,32 @@ Ke386InitThreadWithContext(PKTHREAD Thread, } else { - /* No context Thread, meaning System Thread */ - - /* Set up the Initial Frame */ + /* Set up the Initial Frame for the system thread */ PKKINIT_FRAME InitFrame; - InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack - sizeof(KKINIT_FRAME)); - DPRINT("Setting up a kernel thread with the Frame at: %x\n", InitFrame); + InitFrame = (PKKINIT_FRAME)((ULONG_PTR)Thread->InitialStack - + sizeof(KKINIT_FRAME)); + DPRINT("Setting up a kernel thread. InitFrame at: %p\n", InitFrame); /* Setup the Fx Area */ FxSaveArea = &InitFrame->FxSaveArea; - RtlZeroMemory(FxSaveArea, sizeof(FX_SAVE_AREA)); - Thread->NpxState = NPX_STATE_INVALID; + /* Check if we have Fxsr support */ + if (KeI386FxsrPresent) + { + /* Set the stub FX area */ + FxSaveArea->U.FxArea.ControlWord = 0x27F; + FxSaveArea->U.FxArea.MXCsr = 0x1F80; + } + else + { + /* Set the stub FN area */ + FxSaveArea->U.FnArea.ControlWord = 0x27F; + FxSaveArea->U.FnArea.TagWord = -1; + } + + /* No NPX State */ + Thread->NpxState = NPX_STATE_NOT_LOADED; /* Setup the Stack for KiThreadStartup and Context Switching */ StartFrame = &InitFrame->StartFrame; diff --git a/reactos/ntoskrnl/ps/debug.c b/reactos/ntoskrnl/ps/debug.c index 99c0b30644e..c8fbb779f24 100644 --- a/reactos/ntoskrnl/ps/debug.c +++ b/reactos/ntoskrnl/ps/debug.c @@ -68,7 +68,7 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc, KeTrapFrameToContext(TrapFrame, NULL, Context); } else { /* Set the Context */ - KeContextToTrapFrame(Context, NULL, TrapFrame, Mode); + KeContextToTrapFrame(Context, NULL, TrapFrame, Context->ContextFlags, Mode); } GetSetContext->Status = STATUS_SUCCESS; } @@ -249,7 +249,7 @@ NtSetContextThread(IN HANDLE ThreadHandle, * I don't know if trying to set your own context makes much * sense but we can handle it more efficently. */ - KeContextToTrapFrame(ThreadContext, NULL, Thread->Tcb.TrapFrame, PreviousMode); + KeContextToTrapFrame(ThreadContext, NULL, Thread->Tcb.TrapFrame, ThreadContext->ContextFlags, PreviousMode); } else {