- Update KeContextToTrapFrame to support separate ContextFlags parameters in the scenario where we want to convert more then the Context's flag specify

- Rename some of the internal FPU flags to external names and make them global.
- Improve context creation of new threads to initialize the virgin NPX state for new threads, to clear DR debug registers, to properly convert the context to a trap frame, to set the right segment registers, to set the debugging mark in the trap frame, and to properly set the initial eflags.
- Add stubs for upcoming support for extended/floating point registers in KeContextToTrapFrame and KeTrapFrameToContext.

svn path=/trunk/; revision=20887
This commit is contained in:
Alex Ionescu 2006-01-15 09:23:55 +00:00
parent 1b8586982f
commit 20e6dde401
9 changed files with 310 additions and 94 deletions

View file

@ -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
//

View file

@ -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
);

View file

@ -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);

View file

@ -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,

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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 <internal/debug.h>
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;

View file

@ -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 {