- Update KeContextToTrapFrame to support separate ContextFlags parameters in the...
authorAlex Ionescu <aionescu@gmail.com>
Sun, 15 Jan 2006 09:23:55 +0000 (09:23 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sun, 15 Jan 2006 09:23:55 +0000 (09:23 +0000)
- 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

reactos/include/ndk/asm.h
reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/kd/wrappers/gdbstub.c
reactos/ntoskrnl/ke/exception.c
reactos/ntoskrnl/ke/i386/exp.c
reactos/ntoskrnl/ke/i386/fpu.c
reactos/ntoskrnl/ke/i386/kernel.c
reactos/ntoskrnl/ke/i386/thread.c
reactos/ntoskrnl/ps/debug.c

index 4e22a69..a4d348a 100644 (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
 //
index 92922b1..5f4a6b3 100644 (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
 );
 
index d9b53c4..64047de 100644 (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);
 
index 872df72..4f762dd 100644 (file)
@@ -28,7 +28,11 @@ KiContinuePreviousModeUser(IN PCONTEXT Context,
     Context = &LocalContext;\r
 \r
     /* Convert the context into Exception/Trap Frames */\r
-    KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame, UserMode);\r
+    KeContextToTrapFrame(&LocalContext,\r
+                         ExceptionFrame,\r
+                         TrapFrame,\r
+                         LocalContext.ContextFlags,\r
+                         UserMode);\r
 }\r
 \r
 NTSTATUS\r
@@ -62,7 +66,11 @@ KiContinue(IN PCONTEXT Context,
         else\r
         {\r
             /* Convert the context into Exception/Trap Frames */\r
-            KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, KernelMode);\r
+            KeContextToTrapFrame(Context,\r
+                                 ExceptionFrame,\r
+                                 TrapFrame,\r
+                                 Context->ContextFlags,\r
+                                 KernelMode);\r
         }\r
     }\r
     _SEH_HANDLE\r
@@ -142,7 +150,11 @@ KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
     if (NT_SUCCESS(Status))\r
     {\r
         /* Convert the context record */\r
-        KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, PreviousMode);\r
+        KeContextToTrapFrame(Context,\r
+                             ExceptionFrame,\r
+                             TrapFrame,\r
+                             Context->ContextFlags,\r
+                             PreviousMode);\r
 \r
         /* Dispatch the exception */\r
         KiDispatchException(ExceptionRecord,\r
index 0f313b8..11d5f27 100644 (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;
+
+    /* 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);
 }
 
index 7ec5d77..4546196 100644 (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 *****************************************************************/
 
 /* 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;
     }
index 0b31acb..e362f9c 100644 (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;
 
index ed559d3..9a1b5cf 100644 (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 ****************************************************************/
 #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);
 
-        /* Setup the Trap Frame */
-        TrapFrame = &InitFrame->TrapFrame;
+        /* Copy over the context we got */
+        RtlMoveMemory(&LocalContext, ContextPointer, sizeof(CONTEXT));
+        Context = &LocalContext;
+        ContextFlags = CONTEXT_CONTROL;
 
-        /* Set up a trap frame from the context. */
-        if (KeContextToTrapFrame(Context, NULL, TrapFrame, UserMode))
+        /* 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
         {
-            Thread->NpxState = NPX_STATE_VALID;
+            /* 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
         {
-            Thread->NpxState = NPX_STATE_INVALID;
+            /* We'll use emulation */
+            FxSaveArea->Cr0NpxState = CR0_EM;
+            Thread->NpxState = NPX_STATE_NOT_LOADED &~ CR0_MP;
         }
 
-        /* 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);
+        /* 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. */
+        KeContextToTrapFrame(Context,
+                             NULL,
+                             TrapFrame,
+                             Context->ContextFlags | ContextFlags,
+                             UserMode);
+
+        /* 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;
index 99c0b30..c8fbb77 100644 (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 {