Commit in reactos on MAIN
include/ntos/tss.h+2-11.4 -> 1.5
ntoskrnl/include/internal/i386/fpu.h+23-41.5 -> 1.6
                              /ke.h+29-31.15 -> 1.16
                              /ps.h+4-21.16 -> 1.17
ntoskrnl/include/internal/trap.h+4-51.4 -> 1.5
ntoskrnl/include/ntoskrnl.h+1-11.5 -> 1.6
ntoskrnl/ke/i386/bthread.S+1-131.10 -> 1.11
                /exp.c+53-421.93 -> 1.94
                /fpu.c+488-391.13 -> 1.14
                /kernel.c+27-71.41 -> 1.42
                /multiboot.S+2-11.28 -> 1.29
                /thread.c+51-451.33 -> 1.34
                /trap.s+28-11.20 -> 1.21
                /tskswitch.S+40-261.19 -> 1.20
                /tss.c+6-61.9 -> 1.10
                /v86m_sup.S+10-231.11 -> 1.12
ntoskrnl/ke/main.c+10-11.205 -> 1.206
ntoskrnl/ps/debug.c+18-11.14 -> 1.15
           /kill.c+9-21.84 -> 1.85
           /w32call.c+32-131.17 -> 1.18
ntoskrnl/ps/i386/continue.c+27-51.5 -> 1.6
+865-241
21 modified files
FPU/SSE state saving on taskswitching, FPU and SSE exception support.

reactos/include/ntos
tss.h 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- tss.h	5 Jan 2004 14:28:19 -0000	1.4
+++ tss.h	20 Nov 2004 23:46:35 -0000	1.5
@@ -5,7 +5,8 @@
 #ifndef __INCLUDE_DDK_I386_TSS_H
 #define __INCLUDE_DDK_I386_TSS_H
 
-#define KTSS_ESP0 (0x4)
+#define KTSS_ESP0      (0x4)
+#define KTSS_EFLAGS    (0x24)
 #define KTSS_IOMAPBASE (0x66)
 
 #ifndef __ASM__

reactos/ntoskrnl/include/internal/i386
fpu.h 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- fpu.h	12 Oct 2004 00:33:30 -0000	1.5
+++ fpu.h	20 Nov 2004 23:46:36 -0000	1.6
@@ -20,10 +20,11 @@
 #ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
 #define __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
 
-extern ULONG HardwareMathSupport;
+#define SIZEOF_FX_SAVE_AREA    528
 
-VOID
-KiCheckFPU(VOID);
+#ifndef __ASM__
+
+#include <internal/i386/ke.h>
 
 typedef struct _FNSAVE_FORMAT {
 	ULONG ControlWord;
@@ -52,7 +53,7 @@
 	UCHAR Reserved4[224];
 	UCHAR Align16Byte[8];
 } FXSAVE_FORMAT, *PFXSAVE_FORMAT;
-   
+
 typedef struct _FX_SAVE_AREA {
 	union {
 		FNSAVE_FORMAT FnArea;
@@ -62,4 +63,22 @@
 	ULONG Cr0NpxState;
 } FX_SAVE_AREA, *PFX_SAVE_AREA;
 
+
+extern ULONG HardwareMathSupport;
+
+VOID
+KiCheckFPU(VOID);
+
+NTSTATUS
+KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr);
+
+VOID
+KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST FLOATING_SAVE_AREA *FloatingSaveArea);
+
+BOOL
+KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context);
+
+#endif /* !__ASM__ */
+
 #endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H */
+

reactos/ntoskrnl/include/internal/i386
ke.h 1.15 -> 1.16
diff -u -r1.15 -r1.16
--- ke.h	31 Oct 2004 12:49:36 -0000	1.15
+++ ke.h	20 Nov 2004 23:46:36 -0000	1.16
@@ -69,22 +69,39 @@
 #define KTRAP_FRAME_RESERVED9      (0x8A)
 #define KTRAP_FRAME_SIZE           (0x8C)
 
+#define X86_EFLAGS_IF           0x00000200 /* Interrupt Enable flag */
+#define X86_EFLAGS_IOPL         0x00003000 /* I/O Privilege Level bits */
+#define X86_EFLAGS_NT           0x00004000 /* Nested Task flag */
 #define X86_EFLAGS_VM           0x00020000 /* Virtual Mode */
 #define X86_EFLAGS_ID           0x00200000 /* CPUID detection flag */
 
+#define X86_CR0_NE              0x00000020 /* enable native FPU error reporting */
+#define X86_CR0_TS              0x00000008 /* enable exception on FPU instruction for task switch */
+#define X86_CR0_EM              0x00000004 /* enable FPU emulation (disable FPU) */
+#define X86_CR0_MP              0x00000002 /* enable FPU monitoring */
+
 #define X86_CR4_PAE             0x00000020 /* enable physical address extensions */
 #define X86_CR4_PGE             0x00000080 /* enable global pages */
+#define X86_CR4_OSFXSR          0x00000200 /* enable FXSAVE/FXRSTOR instructions */
+#define X86_CR4_OSXMMEXCPT      0x00000400 /* enable #XF exception */
 
 #define X86_FEATURE_TSC         0x00000010 /* time stamp counters are present */
 #define X86_FEATURE_PAE         0x00000040 /* physical address extension is present */
 #define X86_FEATURE_CX8         0x00000100 /* CMPXCHG8B instruction present */
 #define X86_FEATURE_PGE         0x00002000 /* Page Global Enable */
 #define X86_FEATURE_MMX         0x00800000 /* MMX extension present */
+#define X86_FEATURE_FXSR        0x01000000 /* FXSAVE/FXRSTOR instructions present */
 #define X86_FEATURE_SSE         0x02000000 /* SSE extension present */
 #define X86_FEATURE_SSE2        0x04000000 /* SSE2 extension present */
 
+#define X86_EXT_FEATURE_SSE3    0x00000001 /* SSE3 extension present */
 #define X86_EXT_FEATURE_3DNOW   0x40000000 /* 3DNOW! extension present */
 
+/* Possible values for KTHREAD's NpxState */
+#define NPX_STATE_INVALID   0x01
+#define NPX_STATE_VALID     0x02
+#define NPX_STATE_DIRTY     0x04
+
 #ifndef __ASM__
 
 typedef struct _KTRAP_FRAME
@@ -187,12 +204,20 @@
 	                                 : "r" (X));
 #define Ke386SaveFlags(x)        __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
 #define Ke386RestoreFlags(x)     __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
-#define Ke386GetCr4()            ({ \
+
+#define _Ke386GetCr(N)           ({ \
                                      unsigned int __d; \
-                                     __asm__("movl %%cr4,%0\n\t" :"=r" (__d)); \
+                                     __asm__("movl %%cr" #N ",%0\n\t" :"=r" (__d)); \
                                      __d; \
                                  })
-#define Ke386SetCr4(X)           __asm__ __volatile__("movl %0,%%cr4": :"r" (X));
+#define _Ke386SetCr(N,X)         __asm__ __volatile__("movl %0,%%cr" #N : :"r" (X));
+
+#define Ke386GetCr0()            _Ke386GetCr(0)
+#define Ke386SetCr0(X)           _Ke386SetCr(0,X)
+#define Ke386GetCr2()            _Ke386GetCr(2)
+#define Ke386SetCr2(X)           _Ke386SetCr(2,X)
+#define Ke386GetCr4()            _Ke386GetCr(4)
+#define Ke386SetCr4(X)           _Ke386SetCr(4,X)
 
 static inline void Ki386Cpuid(ULONG Op, PULONG Eax, PULONG Ebx, PULONG Ecx, PULONG Edx)
 {
@@ -207,6 +232,7 @@
 
 
 #elif defined(_MSC_VER)
+
 #define Ke386DisableInterrupts() __asm cli
 #define Ke386EnableInterrupts()  __asm sti
 #define Ke386HaltProcessor()     __asm hlt

reactos/ntoskrnl/include/internal/i386
ps.h 1.16 -> 1.17
diff -u -r1.16 -r1.17
--- ps.h	30 Oct 2004 23:48:56 -0000	1.16
+++ ps.h	20 Nov 2004 23:46:36 -0000	1.17
@@ -26,6 +26,7 @@
 #define KTHREAD_STACK_LIMIT       0x1C
 #define KTHREAD_TEB               0x20
 #define KTHREAD_KERNEL_STACK      0x28
+#define KTHREAD_NPX_STATE         0x31
 #define KTHREAD_APCSTATE_PROCESS  0x44
 #define KTHREAD_SERVICE_TABLE     0xDC
 #define KTHREAD_PREVIOUS_MODE     0x137
@@ -44,6 +45,7 @@
 #define KPCR_SELF                 0x1C
 #define KPCR_TSS                  0x40
 #define KPCR_CURRENT_THREAD       0x124	
+#define KPCR_NPX_THREAD           0x2A4
 
 #ifndef __ASM__
 
@@ -51,12 +53,12 @@
 
 #pragma pack(push,4)
 
-// Fixme: Use correct types?
+/* Fixme: Use correct types? */
 typedef struct _KPROCESSOR_STATE {
    PCONTEXT ContextFrame;
    PVOID SpecialRegisters;
 } KPROCESSOR_STATE;
-  
+
 /* ProcessoR Control Block */ 
 typedef struct _KPRCB {
 	USHORT MinorVersion;

reactos/ntoskrnl/include/internal
trap.h 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- trap.h	8 Sep 2002 10:23:23 -0000	1.4
+++ trap.h	20 Nov 2004 23:46:36 -0000	1.5
@@ -27,10 +27,9 @@
 #ifndef __NTOSKRNL_INCLUDE_INTERNAL_TRAP_H
 #define __NTOSKRNL_INCLUDE_INTERNAL_TRAP_H
 
-#define TF_SAVED_ORIG_STACK (0x8C)
-#define TF_REGS         (0x90)
-#define TF_ORIG_EBP     (0x94)
-
+#define TF_SAVED_EXCEPTION_STACK (0x8C)
+#define TF_REGS                  (0x90)
+#define TF_ORIG_EBP              (0x94)
 
 #ifndef __ASM__
 
@@ -40,7 +39,7 @@
 {
   KTRAP_FRAME Tf;
   
-  ULONG SavedInitialStack;
+  ULONG SavedExceptionStack;
 
   /*
    * These are put on the top of the stack by the routine that entered

reactos/ntoskrnl/include
ntoskrnl.h 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- ntoskrnl.h	28 Oct 2004 19:01:58 -0000	1.5
+++ ntoskrnl.h	20 Nov 2004 23:46:36 -0000	1.6
@@ -24,6 +24,7 @@
 #include <ddk/kefuncs.h>
 #include <ddk/pnptypes.h>
 #include <ddk/pnpfuncs.h>
+#include <ntdll/ldr.h>
 #include <internal/ctype.h>
 #include <internal/ntoskrnl.h>
 #include <internal/id.h>
@@ -55,7 +56,6 @@
 #include <internal/trap.h>
 #include <internal/safe.h>
 #include <internal/test.h>
-#include <ntdll/ldr.h>
 #include <napi/core.h>
 #include <napi/dbg.h>
 #include <napi/teb.h>

reactos/ntoskrnl/ke/i386
bthread.S 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- bthread.S	31 Oct 2004 19:46:10 -0000	1.10
+++ bthread.S	20 Nov 2004 23:46:36 -0000	1.11
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: bthread.S,v 1.10 2004/10/31 19:46:10 ekohl Exp $
+/* $Id: bthread.S,v 1.11 2004/11/20 23:46:36 blight Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -141,18 +141,6 @@
 	addl	$24, %esp
 .L3:
 
-	/*
-	 * Load the floating point registers
-	 */
-	movl	(_HardwareMathSupport), %eax
-	testl	%eax,%eax
-	jz	.L2
-	testl	$(CONTEXT_FLOATING_POINT & ~CONTEXT_i386), %ebx
-	jz	.L2
-	frstor	(%esp)
-.L2:
-	addl	$112, %esp
-
 	/* Load the rest of the thread's user mode context. */
 	movl	$0, %eax
 	jmp	KeReturnFromSystemCallWithHook

reactos/ntoskrnl/ke/i386
exp.c 1.93 -> 1.94
diff -u -r1.93 -r1.94
--- exp.c	22 Oct 2004 20:32:48 -0000	1.93
+++ exp.c	20 Nov 2004 23:46:36 -0000	1.94
@@ -40,6 +40,10 @@
 #define _STR(x) #x
 #define STR(x) _STR(x)
 
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
+#endif
+
 extern void interrupt_handler2e(void);
 extern void interrupt_handler2d(void);
 
@@ -60,6 +64,9 @@
 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;
@@ -84,9 +91,11 @@
     "Stack Segment Fault",
     "General Protection",
     "Page Fault",
+    "Reserved(15)",
     "Math Fault",
     "Alignment Check",
-    "Machine Check"
+    "Machine Check",
+    "SIMD Fault"
   };
 
 static NTSTATUS ExceptionToNtStatus[] =
@@ -106,9 +115,11 @@
     STATUS_STACK_OVERFLOW,
     STATUS_ACCESS_VIOLATION,
     STATUS_ACCESS_VIOLATION,
+    STATUS_ACCESS_VIOLATION, /* RESERVED */
     STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
     STATUS_DATATYPE_MISALIGNMENT,
-    STATUS_ACCESS_VIOLATION
+    STATUS_ACCESS_VIOLATION,
+    STATUS_ACCESS_VIOLATION  /* STATUS_FLT_MULTIPLE_TRAPS? */
   };
 
 /* FUNCTIONS ****************************************************************/
@@ -167,7 +178,7 @@
     }
   else
     {
-      if (ExceptionNr < 16)
+      if (ExceptionNr < ARRAY_SIZE(ExceptionToNtStatus))
 	{
 	  Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
 	}
@@ -190,7 +201,7 @@
 ULONG
 KiDoubleFaultHandler(VOID)
 {
-  unsigned int cr2_;
+  unsigned int cr2;
   ULONG StackLimit;
   ULONG StackBase;
   ULONG Esp0;
@@ -211,15 +222,7 @@
   Esp0 = OldTss->Esp;
 
   /* Get CR2 */
-#if defined(__GNUC__)
-  __asm__("movl %%cr2,%0\n\t" : "=d" (cr2_));
-#elif defined(_MSC_VER)
-  __asm mov eax, cr2;
-  __asm mov cr2_, eax;
-#else
-#error Unknown compiler for inline assembler
-#endif
-
+  cr2 = Ke386GetCr2();
   if (PsGetCurrentThread() != NULL &&
       PsGetCurrentThread()->ThreadsProcess != NULL)
     {
@@ -245,7 +248,7 @@
    /*
     * Print out the CPU registers
     */
-   if (ExceptionNr < 19)
+   if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
      {
        DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
 		ExceptionNr, 0);
@@ -257,7 +260,7 @@
    DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
    KeRosPrintAddress((PVOID)OldTss->Eip);
    DbgPrint("\n");
-   DbgPrint("cr2 %x cr3 %x ", cr2_, OldCr3);
+   DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
    DbgPrint("Proc: %x ",PsGetCurrentProcess());
    if (PsGetCurrentProcess() != NULL)
      {
@@ -420,7 +423,7 @@
    /*
     * Print out the CPU registers
     */
-   if (ExceptionNr < 19)
+   if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
      {
 	DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
 		 ExceptionNr, Tf->ErrorCode&0xffff);
@@ -529,7 +532,7 @@
  *        Complete CPU context
  */
 {
-   unsigned int cr2_;
+   unsigned int cr2;
    NTSTATUS Status;
    ULONG Esp0;
 
@@ -540,22 +543,15 @@
    Esp0 = (ULONG)&Tf->Eip;
 
    /* Get CR2 */
-#if defined(__GNUC__)
-   __asm__("movl %%cr2,%0\n\t" : "=d" (cr2_));
-#elif defined(_MSC_VER)
-  __asm mov eax, cr2;
-  __asm mov cr2_, eax;
-#else
-#error Unknown compiler for inline assembler
-#endif
-   Tf->DebugPointer = (PVOID)cr2_;
+   cr2 = Ke386GetCr2();
+   Tf->DebugPointer = (PVOID)cr2;
 
    /*
     * If this was a V86 mode exception then handle it specially
     */
    if (Tf->Eflags & (1 << 17))
      {
-       return(KeV86Exception(ExceptionNr, Tf, cr2_));
+       return(KeV86Exception(ExceptionNr, Tf, cr2));
      }
 
    /*
@@ -574,7 +570,7 @@
     */
    if (ExceptionNr == 14)
      {
-        if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2_ >= KERNEL_BASE)
+        if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2 >= KERNEL_BASE)
 	{
            KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
 	}
@@ -585,7 +581,7 @@
 	Status = MmPageFault(Tf->Cs&0xffff,
 			     &Tf->Eip,
 			     &Tf->Eax,
-			     cr2_,
+			     cr2,
 			     Tf->ErrorCode);
 	if (NT_SUCCESS(Status))
 	  {
@@ -606,15 +602,27 @@
      }
 
    /*
+    * Try to handle device-not-present, math-fault and xmm-fault exceptions.
+    */
+   if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
+     {
+       Status = KiHandleFpuFault(Tf, ExceptionNr);
+       if (NT_SUCCESS(Status))
+         {
+           return(0);
+         }
+     }
+
+   /*
     * Handle user exceptions differently
     */
    if ((Tf->Cs & 0xFFFF) == USER_CS)
      {
-       return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2_));
+       return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
      }
    else
     {
-      return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2_));
+      return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
     }
 }
 
@@ -728,11 +736,14 @@
    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=17;i<256;i++)
-        {
-	   set_trap_gate(i,(int)KiTrapUnknown, 0);
-        }
+   for (i = 20; i < 256; i++)
+     {
+        set_trap_gate(i,(int)KiTrapUnknown, 0);
+     }
 
    set_system_call_gate(0x2d,(int)interrupt_handler2d);
    set_system_call_gate(0x2e,(int)interrupt_handler2e);
@@ -746,14 +757,14 @@
 KeRaiseUserException(IN NTSTATUS ExceptionCode)
 {
    /* FIXME: This needs SEH */
-	ULONG OldEip;
-	PKTHREAD Thread = KeGetCurrentThread();
+   ULONG OldEip;
+   PKTHREAD Thread = KeGetCurrentThread();
 
-	ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */
-	OldEip = Thread->TrapFrame->Eip;
-	Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
-	Thread->Teb->ExceptionCode = ExceptionCode;
-	return((NTSTATUS)OldEip);
+   ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */
+   OldEip = Thread->TrapFrame->Eip;
+   Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
+   Thread->Teb->ExceptionCode = ExceptionCode;
+   return((NTSTATUS)OldEip);
 }
 
 VOID

reactos/ntoskrnl/ke/i386
fpu.c 1.13 -> 1.14
diff -u -r1.13 -r1.14
--- fpu.c	15 Aug 2004 16:39:05 -0000	1.13
+++ fpu.c	20 Nov 2004 23:46:36 -0000	1.14
@@ -1,4 +1,4 @@
-/* $Id: fpu.c,v 1.13 2004/08/15 16:39:05 chorns Exp $
+/* $Id: fpu.c,v 1.14 2004/11/20 23:46:36 blight Exp $
  *
  *  ReactOS kernel
  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
@@ -32,71 +32,310 @@
 #define NDEBUG
 #include <internal/debug.h>
 
+/* DEFINES *******************************************************************/
+
+#define EXCEPTION_FLT_DENORMAL_OPERAND          (0xc000008dL)
+#define EXCEPTION_FLT_DIVIDE_BY_ZERO            (0xc000008eL)
+#define EXCEPTION_FLT_INEXACT_RESULT            (0xc000008fL)
+#define EXCEPTION_FLT_INVALID_OPERATION         (0xc0000090L)
+#define EXCEPTION_FLT_OVERFLOW                  (0xc0000091L)
+#define EXCEPTION_FLT_STACK_CHECK               (0xc0000092L)
+#define EXCEPTION_FLT_UNDERFLOW                 (0xc0000093L)
+#define EXCEPTION_FLT_MULTIPLE_FAULTS           (0xC00002B4L)
+#define EXCEPTION_FLT_MULTIPLE_TRAPS            (0xC00002B5L)
+
+/* x87 Status Word exception flags */
+#define X87_SW_IE       (1<<0)   /* Invalid Operation */
+#define X87_SW_DE       (1<<1)   /* Denormalized Operand */
+#define X87_SW_ZE       (1<<2)   /* Zero Devide */
+#define X87_SW_OE       (1<<3)   /* Overflow */
+#define X87_SW_UE       (1<<4)   /* Underflow */
+#define X87_SW_PE       (1<<5)   /* Precision */
+#define X87_SW_SE       (1<<6)   /* Stack Fault */
+
+#define X87_SW_ES       (1<<7)   /* Error Summary */
+
+/* MXCSR exception flags */
+#define MXCSR_IE        (1<<0)   /* Invalid Operation */
+#define MXCSR_DE        (1<<1)   /* Denormalized Operand */
+#define MXCSR_ZE        (1<<2)   /* Zero Devide */
+#define MXCSR_OE        (1<<3)   /* Overflow */
+#define MXCSR_UE        (1<<4)   /* Underflow */
+#define MXCSR_PE        (1<<5)   /* Precision */
+#define MXCSR_DAZ       (1<<6)   /* Denormals Are Zeros (P4 only) */
+
 /* GLOBALS *******************************************************************/
 
-ULONG HardwareMathSupport;
+ULONG HardwareMathSupport = 0;
+static ULONG MxcsrFeatureMask = 0, FxsrSupport = 0, XmmSupport = 0;
 
 /* FUNCTIONS *****************************************************************/
 
+STATIC USHORT
+KiTagWordFnsaveToFxsave(USHORT TagWord)
+{
+  INT tmp;
+
+  /*
+   * Converts the tag-word. 11 (Empty) is converted into 0, everything else into 1
+   */
+  tmp = ~TagWord; /* Empty is now 00, any 2 bits containing 1 mean valid */
+  tmp = (tmp | (tmp >> 1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+  tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+  tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+  tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+
+  return tmp;
+}
+
+STATIC USHORT
+KiTagWordFxsaveToFnsave(PFXSAVE_FORMAT FxSave)
+{
+  USHORT TagWord = 0;
+  UCHAR Tag;
+  INT i;
+  struct FPREG { USHORT Significand[4]; USHORT Exponent; } *FpReg;
+  
+  for (i = 0; i < 8; i++)
+    {
+      if (FxSave->TagWord & (1 << i)) /* valid */
+        {
+          FpReg = (struct FPREG *)(FxSave->RegisterArea + (i * 16));
+          switch (FpReg->Exponent & 0x00007fff)
+            {
+              case 0x0000:
+                if (FpReg->Significand[0] == 0 && FpReg->Significand[1] == 0 &&
+                    FpReg->Significand[2] == 0 && FpReg->Significand[3] == 0)
+                  {
+                    Tag = 1;  /* Zero */
+                  }
+                else
+                  {
+                    Tag = 2;  /* Special */
+                  }
+                break;
+            
+              case 0x7fff:
+                Tag = 2;      /* Special */
+                break;
+                
+              default:
+                if (FpReg->Significand[3] & 0x00008000)
+                  {
+                    Tag = 0;  /* Valid */
+                  }
+                else
+                  {
+                    Tag = 2;  /* Special */
+                  }
+                break;
+            }
+        }
+      else /* empty */
+        {
+          Tag = 3;
+        }
+      TagWord |= Tag << (i * 2);
+    }
+
+  return TagWord;
+}
+
+STATIC VOID
+KiFnsaveToFxsaveFormat(PFXSAVE_FORMAT FxSave, CONST PFNSAVE_FORMAT FnSave)
+{
+  INT i;
+
+  FxSave->ControlWord = (USHORT)FnSave->ControlWord;
+  FxSave->StatusWord = (USHORT)FnSave->StatusWord;
+  FxSave->TagWord = KiTagWordFnsaveToFxsave((USHORT)FnSave->TagWord);
+  FxSave->ErrorOpcode = (USHORT)(FnSave->ErrorSelector >> 16);
+  FxSave->ErrorOffset = FnSave->ErrorOffset;
+  FxSave->ErrorSelector = FnSave->ErrorSelector & 0x0000ffff;
+  FxSave->DataOffset = FnSave->DataOffset;
+  FxSave->DataSelector = FnSave->DataSelector & 0x0000ffff;
+  if (XmmSupport)
+    FxSave->MXCsr = 0x00001f80 & MxcsrFeatureMask;
+  else
+    FxSave->MXCsr = 0;
+  FxSave->MXCsrMask = MxcsrFeatureMask;
+  memset(FxSave->Reserved3, 0, sizeof(FxSave->Reserved3) +
+         sizeof(FxSave->Reserved4)); /* XXX - doesnt zero Align16Byte because
+                                        Context->ExtendedRegisters is only 512 bytes, not 520 */
+  for (i = 0; i < 8; i++)
+    {
+      memcpy(FxSave->RegisterArea + (i * 16), FnSave->RegisterArea + (i * 10), 10);
+      memset(FxSave->RegisterArea + (i * 16) + 10, 0, 6);
+    }
+}
+
+STATIC VOID
+KiFxsaveToFnsaveFormat(PFNSAVE_FORMAT FnSave, CONST PFXSAVE_FORMAT FxSave)
+{
+  INT i;
+
+  FnSave->ControlWord = 0xffff0000 | FxSave->ControlWord;
+  FnSave->StatusWord = 0xffff0000 | FxSave->StatusWord;
+  FnSave->TagWord = 0xffff0000 | KiTagWordFxsaveToFnsave(FxSave);
+  FnSave->ErrorOffset = FxSave->ErrorOffset;
+  FnSave->ErrorSelector = FxSave->ErrorSelector & 0x0000ffff;
+  FnSave->ErrorSelector |= FxSave->ErrorOpcode << 16;
+  FnSave->DataOffset = FxSave->DataOffset;
+  FnSave->DataSelector = FxSave->DataSelector | 0xffff0000;
+  for (i = 0; i < 8; i++)
+    {
+      memcpy(FnSave->RegisterArea + (i * 10), FxSave->RegisterArea + (i * 16), 10);
+    }
+}
+
+VOID
+KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST FLOATING_SAVE_AREA *FloatingSaveArea)
+{
+  if (FxsrSupport)
+  {
+    KiFnsaveToFxsaveFormat(&FxSaveArea->U.FxArea, (PFNSAVE_FORMAT)FloatingSaveArea);
+  }
+  else
+  {
+    memcpy(&FxSaveArea->U.FnArea, FloatingSaveArea, sizeof(FxSaveArea->U.FnArea));
+  }
+  FxSaveArea->NpxSavedCpu = 0;
+  FxSaveArea->Cr0NpxState = FloatingSaveArea->Cr0NpxState;
+}
+
+BOOL
+KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context)
+{
+  BOOL FpuContextChanged = FALSE;
+
+  /* First of all convert the FLOATING_SAVE_AREA into the FX_SAVE_AREA */
+  if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
+    {
+      KiFloatingSaveAreaToFxSaveArea(FxSaveArea, &Context->FloatSave);
+      FpuContextChanged = TRUE;
+    }
+
+  /* Now merge the FX_SAVE_AREA from the context with the destination area */
+  if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
+    {
+      if (FxsrSupport)
+        {
+          PFXSAVE_FORMAT src = (PFXSAVE_FORMAT)Context->ExtendedRegisters;
+          PFXSAVE_FORMAT dst = &FxSaveArea->U.FxArea;
+          dst->MXCsr = src->MXCsr & MxcsrFeatureMask;
+          memcpy(dst->Reserved3, src->Reserved3,
+                 sizeof(src->Reserved3) + sizeof(src->Reserved4));
+
+          if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) != CONTEXT_FLOATING_POINT)
+            {
+              dst->ControlWord = src->ControlWord;
+              dst->StatusWord = src->StatusWord;
+              dst->TagWord = src->TagWord;
+              dst->ErrorOpcode = src->ErrorOpcode;
+              dst->ErrorOffset = src->ErrorOffset;
+              dst->ErrorSelector = src->ErrorSelector;
+              dst->DataOffset = src->DataOffset;
+              dst->DataSelector = src->DataSelector;
+              memcpy(dst->RegisterArea, src->RegisterArea, sizeof(src->RegisterArea));
+
+              FxSaveArea->NpxSavedCpu = 0;
+              FxSaveArea->Cr0NpxState = 0;
+            }
+          FpuContextChanged = TRUE;
+        }
+    }
+
+  return FpuContextChanged;
+}
+
 VOID INIT_FUNCTION
 KiCheckFPU(VOID)
 {
    unsigned short int status;
-   int cr0_;
-   
+   int cr0;
+   ULONG Flags;
+   PKPCR Pcr = KeGetCurrentKPCR();
+
+   Ke386SaveFlags(Flags);
+   Ke386DisableInterrupts();
+
    HardwareMathSupport = 0;
-   
+   FxsrSupport = 0;
+   XmmSupport = 0;
+
+   cr0 = Ke386GetCr0();
+   cr0 |= X86_CR0_NE | X86_CR0_MP;
+   cr0 &= ~(X86_CR0_EM | X86_CR0_TS);
+   Ke386SetCr0(cr0);
+
 #if defined(__GNUC__)
-   __asm__("movl %%cr0, %0\n\t" : "=a" (cr0_));
-   /* Set NE and MP. */
-   cr0_ = cr0_ | 0x22;
-   /* Clear EM */
-   cr0_ = cr0_ & (~0x4);
-   __asm__("movl %0, %%cr0\n\t" : : "a" (cr0_));
-
-   __asm__("clts\n\t");
-   __asm__("fninit\n\t");
-   __asm__("fstsw %0\n\t" : "=a" (status));
-   if (status != 0)
-     {
-	__asm__("movl %%cr0, %0\n\t" : "=a" (cr0_));
-	/* Set the EM flag in CR0 so any FPU instructions cause a trap. */
-	cr0_ = cr0_ | 0x4;
-	__asm__("movl %0, %%cr0\n\t" :
-		: "a" (cr0_));
-	return;
-     }
-   /* fsetpm for i287, ignored by i387 */
-   __asm__(".byte 0xDB, 0xE4\n\t");
+   asm volatile("fninit\n\t");
+   asm volatile("fstsw %0\n\t" : "=a" (status));
 #elif defined(_MSC_VER)
-   __asm mov eax, cr0;
-   __asm mov cr0_, eax;
-   cr0_ |= 0x22;	/* Set NE and MP. */
-   cr0_ &= ~0x4;	/* Clear EM */
    __asm
    {
-	   mov eax, cr0_;
-	   mov cr0, eax;
-	   clts;
 	   fninit;
 	   fstsw status
    }
+#else
+#error Unknown compiler for inline assembler
+#endif
+
    if (status != 0)
      {
-	__asm mov eax, cr0_;
-	__asm or eax, 4; /* Set the EM flag in CR0 so any FPU instructions cause a trap. */
-	__asm mov cr0, eax;
+	/* Set the EM flag in CR0 so any FPU instructions cause a trap. */
+	Ke386SetCr0(Ke386GetCr0() | X86_CR0_EM);
+        Ke386RestoreFlags(Flags);
 	return;
      }
+
    /* fsetpm for i287, ignored by i387 */
+#if defined(__GNUC__)
+   asm volatile(".byte 0xDB, 0xE4\n\t");
+#elif defined(_MSC_VER)
    __asm _emit 0xDB __asm _emit 0xe4
-//   __asm fsetpm;
-//   __asm__(".byte 0xDB, 0xE4\n\t");
 #else
 #error Unknown compiler for inline assembler
 #endif
 
    HardwareMathSupport = 1;
+
+   /* check for and enable MMX/SSE support if possible */
+   if ((Pcr->PrcbData.FeatureBits & X86_FEATURE_FXSR) != 0)
+     {
+        BYTE DummyArea[sizeof(FX_SAVE_AREA) + 15];
+        PFX_SAVE_AREA FxSaveArea;
+
+        /* enable FXSR */
+        FxsrSupport = 1;
+
+        /* we need a 16 byte aligned FX_SAVE_AREA */
+        FxSaveArea = (PFX_SAVE_AREA)DummyArea;
+        if ((ULONG_PTR)FxSaveArea & 0x0f)
+          {
+            FxSaveArea = (PFX_SAVE_AREA)(((ULONG_PTR)FxSaveArea + 0x10) & (~0x0f));
+          }
+
+        Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSFXSR);
+        memset(&FxSaveArea->U.FxArea, 0, sizeof(FxSaveArea->U.FxArea));
+        asm volatile("fxsave %0" : : "m"(FxSaveArea->U.FxArea));
+        MxcsrFeatureMask = FxSaveArea->U.FxArea.MXCsrMask;
+        if (MxcsrFeatureMask == 0)
+          {
+             MxcsrFeatureMask = 0x0000ffbf;
+          }
+     }
+   /* FIXME: Check for SSE3 in Ke386CpuidFlags2! */
+   if (Pcr->PrcbData.FeatureBits & (X86_FEATURE_SSE | X86_FEATURE_SSE2))
+     {
+        Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT);
+        
+        /* enable SSE */
+        XmmSupport = 1;
+     }
+     
+   Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS);
+   Ke386RestoreFlags(Flags);
 }
 
 /* This is a rather naive implementation of Ke(Save/Restore)FloatingPointState
@@ -109,6 +348,14 @@
 {
   char *FpState;
 
+  ASSERT_IRQL(DISPATCH_LEVEL); /* FIXME: is this removed for non-debug builds? I hope not! */
+
+  /* check if we are doing software emulation */
+  if (!HardwareMathSupport)
+    {
+      return STATUS_ILLEGAL_FLOAT_CONTEXT;
+    }
+
   FpState = ExAllocatePool(PagedPool, FPU_STATE_SIZE);
   if (NULL == FpState)
     {
@@ -117,7 +364,7 @@
   *((PVOID *) Save) = FpState;
 
 #if defined(__GNUC__)
-  __asm__("fsave %0\n\t" : "=m" (*FpState));
+  asm volatile("fsave %0\n\t" : "=m" (*FpState));
 #elif defined(_MSC_VER)
   __asm mov eax, FpState;
   __asm fsave [eax];
@@ -125,6 +372,8 @@
 #error Unknown compiler for inline assembler
 #endif
 
+  KeGetCurrentThread()->NpxIrql = KeGetCurrentIrql();
+
   return STATUS_SUCCESS;
 }
 
@@ -133,6 +382,11 @@
 {
   char *FpState = *((PVOID *) Save);
 
+  if (KeGetCurrentThread()->NpxIrql != KeGetCurrentIrql())
+    {
+      KEBUGCHECK(UNDEFINED_BUG_CODE);
+    }
+
 #if defined(__GNUC__)
   __asm__("frstor %0\n\t" : "=m" (*FpState));
 #elif defined(_MSC_VER)
@@ -146,3 +400,198 @@
 
   return STATUS_SUCCESS;
 }
+
+NTSTATUS
+KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
+{
+  if (ExceptionNr == 7) /* device not present */
+    {
+      unsigned int cr0 = Ke386GetCr0();
+      PKTHREAD CurrentThread, NpxThread;
+      PFX_SAVE_AREA FxSaveArea;
+      KIRQL oldIrql;
+      
+      ASSERT((cr0 & X86_CR0_TS) == X86_CR0_TS);
+      ASSERT((Tf->Eflags & X86_EFLAGS_VM) == 0);
+      ASSERT((cr0 & X86_CR0_EM) == 0);
+
+      /* disable scheduler, clear TS in cr0 */
+      ASSERT_IRQL(DISPATCH_LEVEL);
+      KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+      asm volatile("clts");
+
+      CurrentThread = KeGetCurrentThread();
+      NpxThread = KeGetCurrentKPCR()->PrcbData.NpxThread;
+
+      ASSERT(CurrentThread != NULL);
+      DPRINT("Device not present exception happened! (Cr0 = 0x%x, NpxState = 0x%x)\n", Ke386GetCr0(), CurrentThread->NpxState);
+
+      /* check if the current thread already owns the FPU */
+      if (NpxThread != CurrentThread) /* FIXME: maybe this could be an assertation */
+        {
+          BOOL FpuInitialized = FALSE;
+          /* save the FPU state into the owner's save area */
+          if (NpxThread != NULL)
+            {
+              KeGetCurrentKPCR()->PrcbData.NpxThread = NULL;
+              FxSaveArea = (PFX_SAVE_AREA)((char *)NpxThread->InitialStack - sizeof (FX_SAVE_AREA));
+              /* the fnsave might raise a delayed #MF exception */
+              if (FxsrSupport)
+                {
+                  asm volatile("fxsave %0" : : "m"(FxSaveArea->U.FxArea));
+                }
+              else
+                {
+                  asm volatile("fnsave %0" : : "m"(FxSaveArea->U.FnArea));
+                  FpuInitialized = TRUE;
+                }
+              NpxThread->NpxState = NPX_STATE_VALID;
+            }
+
+          /* restore the state of the current thread */
+          ASSERT((CurrentThread->NpxState & NPX_STATE_DIRTY) == 0);
+          FxSaveArea = (PFX_SAVE_AREA)((char *)CurrentThread->InitialStack - sizeof (FX_SAVE_AREA));
+          if (CurrentThread->NpxState & NPX_STATE_VALID)
+            {
+              if (FxsrSupport)
+                {
+                  FxSaveArea->U.FxArea.MXCsr &= MxcsrFeatureMask;
+                  asm volatile("fxrstor %0" : : "m"(FxSaveArea->U.FxArea));
+                }
+              else
+                {
+                  asm volatile("frstor %0" : : "m"(FxSaveArea->U.FnArea));
+                }
+            }
+          else /* NpxState & NPX_STATE_INVALID */
+            {
+              DPRINT("Setting up clean FPU state\n");
+              if (FxsrSupport)
+                {
+                  memset(&FxSaveArea->U.FxArea, 0, sizeof(FxSaveArea->U.FxArea));
+                  FxSaveArea->U.FxArea.ControlWord = 0x037f;
+                  if (XmmSupport)
+                    {
+                      FxSaveArea->U.FxArea.MXCsr = 0x00001f80 & MxcsrFeatureMask;
+                    }
+                  asm volatile("fxrstor %0" : : "m"(FxSaveArea->U.FxArea));
+                }
+              else if (!FpuInitialized)
+                {
+                  asm volatile("finit");
+                }
+            }
+          KeGetCurrentKPCR()->PrcbData.NpxThread = CurrentThread;
+        }
+
+      CurrentThread->NpxState |= NPX_STATE_DIRTY;
+      KeLowerIrql(oldIrql);
+      DPRINT("Device not present exception handled!\n");
+
+      return STATUS_SUCCESS;
+    }
+  else /* ExceptionNr == 16 || ExceptionNr == 19 */
+    {
+      EXCEPTION_RECORD Er;
+      UCHAR DummyContext[sizeof(CONTEXT) + 16];
+      PCONTEXT Context;
+      KPROCESSOR_MODE PreviousMode;
+      PKTHREAD CurrentThread, NpxThread;
+      KIRQL oldIrql;
+
+      ASSERT(ExceptionNr == 16 || ExceptionNr == 19); /* math fault or XMM fault*/
+
+      KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+
+      NpxThread = KeGetCurrentKPCR()->PrcbData.NpxThread;
+      CurrentThread = KeGetCurrentThread();
+      if (NpxThread == NULL)
+        {
+          DPRINT1("!!! Math/Xmm fault ignored! (NpxThread == NULL)\n");
+          KeLowerIrql(oldIrql);
+          return STATUS_SUCCESS;
+        }
+
+      PreviousMode = ((Tf->Cs & 0xffff) == USER_CS) ? (UserMode) : (KernelMode);
+      DPRINT("Math/Xmm fault happened! (PreviousMode = %s)\n",
+              (PreviousMode == UserMode) ? ("UserMode") : ("KernelMode"));
+
+      ASSERT(NpxThread == CurrentThread); /* FIXME: Is not always true I think */
+
+      /* For fxsave we have to align Context->ExtendedRegisters on 16 bytes */
+      Context = (PCONTEXT)DummyContext;
+      Context = (PCONTEXT)((ULONG_PTR)Context + 0x10 - ((ULONG_PTR)Context->ExtendedRegisters & 0x0f));
+
+      /* Get FPU/XMM state */
+      Context->FloatSave.Cr0NpxState = 0;
+      if (FxsrSupport)
+        {
+          PFXSAVE_FORMAT FxSave = (PFXSAVE_FORMAT)Context->ExtendedRegisters;
+          FxSave->MXCsrMask = MxcsrFeatureMask;
+          memset(FxSave->RegisterArea, 0, sizeof(FxSave->RegisterArea) +
+                 sizeof(FxSave->Reserved3) + sizeof(FxSave->Reserved4));
+          asm volatile("fxsave %0" : : "m"(*FxSave));
+          KeLowerIrql(oldIrql);
+          KiFxsaveToFnsaveFormat((PFNSAVE_FORMAT)&Context->FloatSave, FxSave);
+        }
+      else
+        {
+          PFNSAVE_FORMAT FnSave = (PFNSAVE_FORMAT)&Context->FloatSave;
+          asm volatile("fnsave %0" : : "m"(*FnSave));
+          KeLowerIrql(oldIrql);
+          memset(Context->FloatSave.RegisterArea, 0, sizeof(Context->FloatSave.RegisterArea));
+          KiFnsaveToFxsaveFormat((PFXSAVE_FORMAT)Context->ExtendedRegisters, FnSave);
+        }
+
+      /* Fill the rest of the context */
+      Context->ContextFlags = CONTEXT_FULL;
+      KeTrapFrameToContext(Tf, Context);
+      Context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
+
+      /* Determine exception code */
+      if (ExceptionNr == 16)
+        {
+          USHORT FpuStatusWord = Context->FloatSave.StatusWord & 0xffff;
+          DPRINT("FpuStatusWord = 0x%04x\n", FpuStatusWord);
+
+          if (FpuStatusWord & X87_SW_IE)
+            Er.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
+          else if (FpuStatusWord & X87_SW_DE)
+            Er.ExceptionCode = EXCEPTION_FLT_DENORMAL_OPERAND;
+          else if (FpuStatusWord & X87_SW_ZE)
+            Er.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
+          else if (FpuStatusWord & X87_SW_OE)
+            Er.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
+          else if (FpuStatusWord & X87_SW_UE)
+            Er.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
+          else if (FpuStatusWord & X87_SW_PE)
+            Er.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
+          else if (FpuStatusWord & X87_SW_SE)
+            Er.ExceptionCode = EXCEPTION_FLT_STACK_CHECK;
+          else
+            ASSERT(0); /* not reached */
+          /* FIXME: is this the right way to get the correct EIP of the faulting instruction? */
+          Er.ExceptionAddress = (PVOID)Context->FloatSave.ErrorOffset;
+        }
+      else /* ExceptionNr == 19 */
+        {
+          /* FIXME: When should we use EXCEPTION_FLT_MULTIPLE_FAULTS? */
+          Er.ExceptionCode = EXCEPTION_FLT_MULTIPLE_TRAPS;
+          Er.ExceptionAddress = (PVOID)Tf->Eip;
+        }
+
+      Er.ExceptionFlags = 0;
+      Er.ExceptionRecord = NULL;
+      Er.NumberParameters = 0;
+
+      /* Dispatch exception */
+      DPRINT("Dispatching exception (ExceptionCode = 0x%08x)\n", Er.ExceptionCode);
+      KiDispatchException(&Er, Context, Tf, PreviousMode, TRUE);
+      
+      DPRINT("Math-fault handled!\n");
+      return STATUS_SUCCESS;
+    }
+
+  return STATUS_UNSUCCESSFUL;
+}
+

reactos/ntoskrnl/ke/i386
kernel.c 1.41 -> 1.42
diff -u -r1.41 -r1.42
--- kernel.c	13 Nov 2004 23:08:35 -0000	1.41
+++ kernel.c	20 Nov 2004 23:46:36 -0000	1.42
@@ -181,8 +181,6 @@
   Offset = InterlockedIncrement(&PcrsAllocated) - 1;
   Pcr = (PKPCR)((ULONG_PTR)KPCR_BASE + Offset * PAGE_SIZE);
 
-  KiCheckFPU();
-
   /*
    * Initialize the GDT
    */
@@ -191,6 +189,9 @@
   /* Get processor information. */
   Ki386GetCpuId();
 
+  /* Check FPU/MMX/SSE support. */
+  KiCheckFPU();
+
   /*
    * It is now safe to process interrupts
    */
@@ -220,14 +221,18 @@
    extern USHORT KiBootGdt[];
    extern KTSS KiBootTss;
 
+   /* Get processor information. */
+   Ki386GetCpuId();
+
+   /* Check FPU/MMX/SSE support. */
    KiCheckFPU();
-   
+
    KiInitializeGdt (NULL);
    Ki386BootInitializeTSS();
    KeInitExceptions ();
    KeInitInterrupts ();
 
-   /* 
+   /*
     * Initialize the initial PCR region. We can't allocate a page
     * with MmAllocPage() here because MmInit1() has not yet been
     * called, so we use a predefined page in low memory 
@@ -251,9 +256,6 @@
 
    Ki386InitializeLdt();
    
-   /* Get processor information. */
-   Ki386GetCpuId();
-
    if (KPCR->PrcbData.FeatureBits & X86_FEATURE_PGE)
    {
       ULONG Flags;
@@ -348,6 +350,24 @@
          DPRINT1("CPU doesn't run in PAE mode\n");
       }
    }
+   if ((Pcr->PrcbData.FeatureBits & (X86_FEATURE_FXSR | X86_FEATURE_MMX | X86_FEATURE_SSE | X86_FEATURE_SSE2)) ||
+       (Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3))
+      {
+         DPRINT1("CPU supports" "%s%s%s%s%s" ".\n",
+                 ((Pcr->PrcbData.FeatureBits & X86_FEATURE_FXSR) ? " FXSR" : ""),
+                 ((Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX) ? " MMX" : ""),
+                 ((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE) ? " SSE" : ""),
+                 ((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? " SSE2" : ""),
+                 ((Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3) ? " SSE3" : ""));
+      }
+   if (Ke386GetCr4() & X86_CR4_OSFXSR)
+      {
+         DPRINT1("SSE enabled.\n");
+      }
+   if (Ke386GetCr4() & X86_CR4_OSXMMEXCPT)
+      {
+         DPRINT1("Unmasked SIMD exceptions enabled.\n");
+      }
    if (Pcr->PrcbData.VendorString[0])
    {
       DPRINT1("CPU Vendor: %s\n", Pcr->PrcbData.VendorString);

reactos/ntoskrnl/ke/i386
multiboot.S 1.28 -> 1.29
diff -u -r1.28 -r1.29
--- multiboot.S	31 Oct 2004 19:46:10 -0000	1.28
+++ multiboot.S	20 Nov 2004 23:46:36 -0000	1.29
@@ -3,6 +3,7 @@
 #include <internal/i386/segment.h>
 #include <internal/ps.h>
 #include <internal/i386/mm.h>
+#include <internal/i386/fpu.h>
 
 #define MULTIBOOT_HEADER_MAGIC (0x1BADB002)
 
@@ -279,7 +280,7 @@
 	/*
 	 * Load the initial kernel stack
 	 */
-	movl	$_init_stack_top, %esp
+	movl	$(_init_stack_top - SIZEOF_FX_SAVE_AREA), %esp
 
 	/*
 	 * Initialize EFLAGS

reactos/ntoskrnl/ke/i386
thread.c 1.33 -> 1.34
diff -u -r1.33 -r1.34
--- thread.c	15 Aug 2004 16:39:05 -0000	1.33
+++ thread.c	20 Nov 2004 23:46:36 -0000	1.34
@@ -31,13 +31,6 @@
 #define NDEBUG
 #include <internal/debug.h>
 
-/* GLOBALS *******************************************************************/
-
-#define FLAG_NT (1<<14)
-#define FLAG_VM (1<<17)
-#define FLAG_IF (1<<9)
-#define FLAG_IOPL ((1<<12)+(1<<13))
-
 /* FUNCTIONS *****************************************************************/
 
 NTSTATUS 
@@ -77,10 +70,10 @@
      {
 	return(STATUS_UNSUCCESSFUL);
      }
-   if ((Context->EFlags & FLAG_IOPL) != 0 ||
-       (Context->EFlags & FLAG_NT) ||
-       (Context->EFlags & FLAG_VM) ||
-       (!(Context->EFlags & FLAG_IF)))
+   if ((Context->EFlags & X86_EFLAGS_IOPL) != 0 ||
+       (Context->EFlags & X86_EFLAGS_NT) ||
+       (Context->EFlags & X86_EFLAGS_VM) ||
+       (!(Context->EFlags & X86_EFLAGS_IF)))
      {
         return(STATUS_UNSUCCESSFUL);
      }
@@ -93,40 +86,37 @@
   PULONG KernelStack;
   ULONG InitSize;
   PKTRAP_FRAME TrapFrame;
+  PFX_SAVE_AREA FxSaveArea;
 
   /*
    * Setup a stack frame for exit from the task switching routine
    */
   
-  InitSize = 5 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) + 
-    sizeof(FLOATING_SAVE_AREA) + sizeof(KTRAP_FRAME);
+  InitSize = 6 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) +
+           + sizeof(KTRAP_FRAME) + sizeof (FX_SAVE_AREA);
   KernelStack = (PULONG)((char*)Thread->KernelStack - InitSize);
 
   /* Set up the initial frame for the return from the dispatcher. */
-  KernelStack[0] = 0;      /* EDI */
-  KernelStack[1] = 0;      /* ESI */
-  KernelStack[2] = 0;      /* EBX */
-  KernelStack[3] = 0;      /* EBP */
-  KernelStack[4] = (ULONG)&PsBeginThreadWithContextInternal;   /* EIP */
+  KernelStack[0] = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA);  /* TSS->Esp0 */
+  KernelStack[1] = 0;      /* EDI */
+  KernelStack[2] = 0;      /* ESI */
+  KernelStack[3] = 0;      /* EBX */
+  KernelStack[4] = 0;      /* EBP */
+  KernelStack[5] = (ULONG)&PsBeginThreadWithContextInternal;   /* EIP */
 
   /* Save the context flags. */
-  KernelStack[5] = Context->ContextFlags;
+  KernelStack[6] = Context->ContextFlags;
 
   /* Set up the initial values of the debugging registers. */
-  KernelStack[6] = Context->Dr0;
-  KernelStack[7] = Context->Dr1;
-  KernelStack[8] = Context->Dr2;
-  KernelStack[9] = Context->Dr3;
-  KernelStack[10] = Context->Dr6;
-  KernelStack[11] = Context->Dr7;
-
-  /* Set up the initial floating point state. */
-  memcpy((PVOID)&KernelStack[12], (PVOID)&Context->FloatSave,
-	 sizeof(FLOATING_SAVE_AREA));
+  KernelStack[7] = Context->Dr0;
+  KernelStack[8] = Context->Dr1;
+  KernelStack[9] = Context->Dr2;
+  KernelStack[10] = Context->Dr3;
+  KernelStack[11] = Context->Dr6;
+  KernelStack[12] = Context->Dr7;
 
   /* Set up a trap frame from the context. */
-  TrapFrame = (PKTRAP_FRAME)
-    ((char*)KernelStack + 12 * sizeof(DWORD) + sizeof(FLOATING_SAVE_AREA));
+  TrapFrame = (PKTRAP_FRAME)(&KernelStack[13]);
   TrapFrame->DebugEbp = (PVOID)Context->Ebp;
   TrapFrame->DebugEip = (PVOID)Context->Eip;
   TrapFrame->DebugArgMark = 0;
@@ -149,12 +139,24 @@
   TrapFrame->ErrorCode = 0;
   TrapFrame->Cs = Context->SegCs;
   TrapFrame->Eip = Context->Eip;
-  TrapFrame->Eflags = Context->EFlags | FLAG_IF;
-  TrapFrame->Eflags &= ~(FLAG_VM | FLAG_NT | FLAG_IOPL);
+  TrapFrame->Eflags = Context->EFlags | X86_EFLAGS_IF;
+  TrapFrame->Eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_NT | X86_EFLAGS_IOPL);
   TrapFrame->Esp = Context->Esp;
   TrapFrame->Ss = (USHORT)Context->SegSs;
   /* FIXME: Should check for a v86 mode context here. */
 
+  /* Set up the initial floating point state. */
+  /* FIXME: Do we have to zero the FxSaveArea or is it already? */
+  FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)KernelStack + InitSize - sizeof(FX_SAVE_AREA));
+  if (KiContextToFxSaveArea(FxSaveArea, Context))
+    {
+      Thread->NpxState = NPX_STATE_VALID;
+    }
+  else
+    {
+      Thread->NpxState = NPX_STATE_INVALID;
+    }
+
   /* Save back the new value of the kernel stack. */
   Thread->KernelStack = (PVOID)KernelStack;
 
@@ -175,21 +177,25 @@
    * Setup a stack frame for exit from the task switching routine
    */
 
-  KernelStack = (PULONG)((char*)Thread->KernelStack - (8*4));
-  KernelStack[0] = 0;      /* EDI */
-  KernelStack[1] = 0;      /* ESI */
-  KernelStack[2] = 0;      /* EBX */
-  KernelStack[3] = 0;      /* EBP */
-  KernelStack[4] = (ULONG)&PsBeginThread;   /* EIP */
-  KernelStack[5] = 0;     /* Return EIP */
-  KernelStack[6] = (ULONG)StartRoutine; /* First argument to PsBeginThread */
-  KernelStack[7] = (ULONG)StartContext; /* Second argument to PsBeginThread */
+  KernelStack = (PULONG)((char*)Thread->KernelStack - (9 * sizeof(DWORD)) - sizeof(FX_SAVE_AREA));
+  KernelStack[0] = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA);  /* TSS->Esp0 */
+  KernelStack[1] = 0;      /* EDI */
+  KernelStack[2] = 0;      /* ESI */
+  KernelStack[3] = 0;      /* EBX */
+  KernelStack[4] = 0;      /* EBP */
+  KernelStack[5] = (ULONG)&PsBeginThread;   /* EIP */
+  KernelStack[6] = 0;     /* Return EIP */
+  KernelStack[7] = (ULONG)StartRoutine; /* First argument to PsBeginThread */
+  KernelStack[8] = (ULONG)StartContext; /* Second argument to PsBeginThread */
   Thread->KernelStack = (VOID*)KernelStack;
 
+  /*
+   * Setup FPU state
+   */
+  Thread->NpxState = NPX_STATE_INVALID;
+
   return(STATUS_SUCCESS);
 }
 
-
-
-
 /* EOF */
+

reactos/ntoskrnl/ke/i386
trap.s 1.20 -> 1.21
diff -u -r1.20 -r1.21
--- trap.s	1 Jul 2004 02:40:23 -0000	1.20
+++ trap.s	20 Nov 2004 23:46:36 -0000	1.21
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: trap.s,v 1.20 2004/07/01 02:40:23 hyperion Exp $
+/* $Id: trap.s,v 1.21 2004/11/20 23:46:36 blight Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/i386/trap.s
@@ -353,6 +353,33 @@
 	movl	$16, %esi
 	jmp	_KiTrapProlog
 	 
+.globl _KiTrap17
+_KiTrap17:
+	pushl	$0
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	movl	$17, %esi
+	jmp	_KiTrapProlog
+
+.globl _KiTrap18
+_KiTrap18:
+	pushl	$0
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	movl	$18, %esi
+	jmp	_KiTrapProlog
+
+.globl _KiTrap19
+_KiTrap19:
+	pushl	$0
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	movl	$19, %esi
+	jmp	_KiTrapProlog
+
 .globl _KiTrapUnknown
 _KiTrapUnknown:
         pushl	$0

reactos/ntoskrnl/ke/i386
tskswitch.S 1.19 -> 1.20
diff -u -r1.19 -r1.20
--- tskswitch.S	31 Oct 2004 19:46:10 -0000	1.19
+++ tskswitch.S	20 Nov 2004 23:46:36 -0000	1.20
@@ -17,16 +17,18 @@
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 /*
- * FILE:            ntoskrnl/ke/i386/tskswitch.S
- * PURPOSE:         Microkernel thread support
+ * FILE:	    ntoskrnl/ke/i386/tskswitch.S
+ * PURPOSE:	 Microkernel thread support
  * PROGRAMMER:      David Welch (welch@cwcom.net)
  * UPDATE HISTORY:
- *                  Created 09/10/00
+ *		  Created 09/10/00
  */
 
 /* INCLUDES ******************************************************************/
 
 #include <internal/i386/segment.h>
+#include <internal/i386/ke.h>
+#include <internal/i386/fpu.h>
 #include <internal/ps.h>
 #include <ntos/tss.h>
 #include <internal/ntoskrnl.h>
@@ -34,12 +36,13 @@
 /* FUNCTIONS ****************************************************************/
 
 .globl _Ki386ContextSwitch
+.func Ki386ContextSwitch
 _Ki386ContextSwitch:
-/* 
+/*
  * FUNCTIONS: Switches to another thread's context
  * ARGUMENTS:
- *        Thread = Thread to switch to
- *        OldThread = Thread to switch from
+ *	Thread = Thread to switch to
+ *	OldThread = Thread to switch from
  */
 	pushl	%ebp
 	movl	%esp, %ebp
@@ -60,7 +63,7 @@
 	 * Get the pointer to the new thread.
 	 */
 	movl	8(%ebp), %ebx
-		
+
 	/*
 	 * Set the base of the TEB selector to the base of the TEB for
 	 * this thread.
@@ -89,7 +92,7 @@
 	xorl	%eax, %eax
 	movl	KTHREAD_APCSTATE_PROCESS(%ebx), %edi
 	testw	$0xFFFF, KPROCESS_LDT_DESCRIPTOR0(%edi)
-	jz	.L4
+	jz	0f
 
 	pushl	KPROCESS_LDT_DESCRIPTOR1(%edi)
 	pushl	KPROCESS_LDT_DESCRIPTOR0(%edi)
@@ -99,35 +102,35 @@
 
 	movl	$LDT_SELECTOR, %eax
 
-.L4:
+0:
 	lldtw	%ax
 
+	movl	12(%ebp), %ebx
+
 	/*
-	 * Load up the iomap offset for this thread in
-	 * preparation for setting it below.
+	 * FIXME: Save debugging state.
 	 */
-	movl	KPROCESS_IOPM_OFFSET(%edi), %eax
 
 	/*
-	 * FIXME: Save debugging state.
+	 * Load up the iomap offset for this thread in
+	 * preparation for setting it below.
 	 */
+	movl	KPROCESS_IOPM_OFFSET(%edi), %eax
 
 	/*
-	 * FIXME: Save floating point state.
+	 * Save the stack pointer in this processors TSS
 	 */
+	movl	%fs:KPCR_TSS, %esi
+	pushl	KTSS_ESP0(%esi)
 
 	/*
 	 * Switch stacks
 	 */
-	movl	12(%ebp), %ebx
 	movl	%esp, KTHREAD_KERNEL_STACK(%ebx)
 	movl	8(%ebp), %ebx
 	movl	KTHREAD_KERNEL_STACK(%ebx), %esp
 	movl	KTHREAD_STACK_LIMIT(%ebx), %edi
 
-	/*
-	 * Set the stack pointer in this processors TSS
-	 */
 	movl	%fs:KPCR_TSS, %esi
 
 	/*
@@ -135,19 +138,28 @@
 	 */
 	movw	%ax, KTSS_IOMAPBASE(%esi)
 
-	movl	KTHREAD_INITIAL_STACK(%ebx), %eax
-	movl	%eax, KTSS_ESP0(%esi)
-
 	/*
 	 * Change the address space
 	 */
-	movl	KTHREAD_APCSTATE_PROCESS(%ebx), %ebx
-	movl	KPROCESS_DIRECTORY_TABLE_BASE(%ebx), %eax
+	movl	KTHREAD_APCSTATE_PROCESS(%ebx), %eax
+	movl	KPROCESS_DIRECTORY_TABLE_BASE(%eax), %eax
 	movl	%eax, %cr3
 
 	/*
-	 * FIXME: Restore floating point state
+	 * Restore the stack pointer in this processors TSS
 	 */
+	popl	KTSS_ESP0(%esi)
+
+	/*
+	 * Set TS in cr0 to catch FPU code and load the FPU state when needed
+	 * We do this only if NewThread != KPCR->NpxThread
+	 */
+	cmpl	%ebx, %fs:KPCR_NPX_THREAD
+	je	1f
+	movl	%cr0, %eax
+	orl	$X86_CR0_TS, %eax
+	movl	%eax, %cr0
+1:
 
 	/*
 	 * FIXME: Restore debugging state
@@ -162,9 +174,9 @@
 	call	_KeReleaseSpinLockFromDpcLevel@4
 
 	cmpl	$0, _PiNrThreadsAwaitingReaping
-	je	.L3
+	je	4f
 	call	_PiWakeupReaperThread@0
-.L3:
+4:
 
 	/*
 	 * Restore the saved register and exit
@@ -175,3 +187,5 @@
 
 	popl	%ebp
 	ret
+.endfunc
+

reactos/ntoskrnl/ke/i386
tss.c 1.9 -> 1.10
diff -u -r1.9 -r1.10
--- tss.c	15 Aug 2004 16:39:05 -0000	1.9
+++ tss.c	20 Nov 2004 23:46:36 -0000	1.10
@@ -134,7 +134,7 @@
   KeGetCurrentKPCR()->TSS = Tss;
 
   /* Initialize the boot TSS. */
-  Tss->Esp0 = (ULONG)Ki386InitialStackArray[Id];
+  Tss->Esp0 = (ULONG)Ki386InitialStackArray[Id] + MM_STACK_SIZE; /* FIXME: - sizeof(FX_SAVE_AREA)? */
   Tss->Ss0 = KERNEL_DS;
   Tss->IoMapBase = 0xFFFF; /* No i/o bitmap */
   Tss->IoBitmap[8192] = 0xFF;   
@@ -154,9 +154,9 @@
 
   /* Initialize the TSS used for handling double faults. */
   TrapTss->Eflags = 0;
-  TrapTss->Esp0 = ((ULONG)TrapStack + MM_STACK_SIZE);
+  TrapTss->Esp0 = ((ULONG)TrapStack + MM_STACK_SIZE); /* FIXME: - sizeof(FX_SAVE_AREA)? */
   TrapTss->Ss0 = KERNEL_DS;
-  TrapTss->Esp = ((ULONG)TrapStack + MM_STACK_SIZE);
+  TrapTss->Esp = ((ULONG)TrapStack + MM_STACK_SIZE); /* FIXME: - sizeof(FX_SAVE_AREA)? */
   TrapTss->Cs = KERNEL_CS;
   TrapTss->Eip = (ULONG)KiTrap8;
   TrapTss->Ss = KERNEL_DS;
@@ -211,7 +211,7 @@
   Ki386InitialStackArray[0] = (PVOID)&init_stack;
 
   /* Initialize the boot TSS. */
-  KiBootTss.Esp0 = (ULONG)&init_stack_top;
+  KiBootTss.Esp0 = (ULONG)&init_stack_top - sizeof(FX_SAVE_AREA);
   KiBootTss.Ss0 = KERNEL_DS;
   //   KiBootTss.IoMapBase = FIELD_OFFSET(KTSS, IoBitmap);
   KiBootTss.IoMapBase = 0xFFFF; /* No i/o bitmap */
@@ -232,9 +232,9 @@
 
   /* Initialize the TSS used for handling double faults. */
   KiBootTrapTss.Eflags = 0;
-  KiBootTrapTss.Esp0 = (ULONG)&trap_stack_top;
+  KiBootTrapTss.Esp0 = (ULONG)&trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */
   KiBootTrapTss.Ss0 = KERNEL_DS;
-  KiBootTrapTss.Esp = (ULONG)&trap_stack_top;
+  KiBootTrapTss.Esp = (ULONG)&trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */
   KiBootTrapTss.Cs = KERNEL_CS;
   KiBootTrapTss.Eip = (ULONG)KiTrap8;
   KiBootTrapTss.Ss = KERNEL_DS;

reactos/ntoskrnl/ke/i386
v86m_sup.S 1.11 -> 1.12
diff -u -r1.11 -r1.12
--- v86m_sup.S	31 Oct 2004 19:46:10 -0000	1.11
+++ v86m_sup.S	20 Nov 2004 23:46:36 -0000	1.12
@@ -71,25 +71,19 @@
 	 * Since we are going to fiddle with the stack pointer this must be
 	 * a critical section for this processor
 	 */
-
-	/*
-	 * Save the old initial stack
-	 */
-	movl	%fs:KPCR_CURRENT_THREAD, %esi
-	movl	KTHREAD_INITIAL_STACK(%esi), %edi
-	pushl	%edi
-
-	/*
-	 * We also need to set the stack in the kthread structure
-	 */
-	movl	%esp, KTHREAD_INITIAL_STACK(%esi)
+	cli
+	
+        /*
+         * Save the exception handler stack from the TSS
+         */
+	movl	%fs:KPCR_TSS, %esi
+	pushl	KTSS_ESP0(%esi)
 
 	/*
 	 * The stack used for handling exceptions from v86 mode in this thread
 	 * will be the current stack adjusted so we don't overwrite the 
 	 * existing stack frames
 	 */
-	movl	%fs:KPCR_TSS, %esi
 	movl	%esp, KTSS_ESP0(%esi)
 
 	/*
@@ -180,18 +174,10 @@
 	cli
 
 	/*
-	 * Restore the initial stack
+	 * Restore the exception handler stack in the TSS
 	 */
-	popl	%eax
 	movl	%fs:KPCR_TSS, %esi
-	movl	%eax, KTSS_ESP0(%esi)
-
-	/*
-	 * We also need to set the stack in the kthread structure
-	 */
-	movl	%fs:KPCR_CURRENT_THREAD, %esi
-	movl	KTHREAD_INITIAL_STACK(%esi), %edi
-	movl	%eax, KTHREAD_INITIAL_STACK(%esi)	
+	popl	KTSS_ESP0(%esi)
 
 	/* Exit the critical section */
 	sti
@@ -207,3 +193,4 @@
 	movl	%ebp, %esp
 	popl	%ebp
 	ret
+

reactos/ntoskrnl/ke
main.c 1.205 -> 1.206
diff -u -r1.205 -r1.206
--- main.c	13 Nov 2004 22:30:18 -0000	1.205
+++ main.c	20 Nov 2004 23:46:37 -0000	1.206
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: main.c,v 1.205 2004/11/13 22:30:18 hbirr Exp $
+/* $Id: main.c,v 1.206 2004/11/20 23:46:37 blight Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/main.c
@@ -299,6 +299,7 @@
   ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
   ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
   ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
+  ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
   ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
   ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
   ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
@@ -309,12 +310,20 @@
   ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
   ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
   ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
+  ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
   ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
   ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
 
   ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
   ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
   ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);  
+  ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
+
+  ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
+  ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
+  ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
+
+  ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
 
   LdrInit1();
 

reactos/ntoskrnl/ps
debug.c 1.14 -> 1.15
diff -u -r1.14 -r1.15
--- debug.c	24 Oct 2004 20:37:27 -0000	1.14
+++ debug.c	20 Nov 2004 23:46:37 -0000	1.15
@@ -17,7 +17,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: debug.c,v 1.14 2004/10/24 20:37:27 weiden Exp $
+/* $Id: debug.c,v 1.15 2004/11/20 23:46:37 blight Exp $
  *
  * PROJECT:                ReactOS kernel
  * FILE:                   ntoskrnl/ps/debug.c
@@ -77,6 +77,9 @@
      {
 	/*
 	 * Not handled
+	 *
+	 * This should be handled separately I think.
+	 *  - blight
 	 */
      }
    if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
@@ -129,19 +132,33 @@
 	/*
 	 * 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
 }

reactos/ntoskrnl/ps
kill.c 1.84 -> 1.85
diff -u -r1.84 -r1.85
--- kill.c	20 Nov 2004 16:46:05 -0000	1.84
+++ kill.c	20 Nov 2004 23:46:37 -0000	1.85
@@ -1,4 +1,4 @@
-/* $Id: kill.c,v 1.84 2004/11/20 16:46:05 weiden Exp $
+/* $Id: kill.c,v 1.85 2004/11/20 23:46:37 blight Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -136,10 +136,17 @@
    CurrentThread->ExitStatus = ExitStatus;
    KeQuerySystemTime((PLARGE_INTEGER)&CurrentThread->ExitTime);
    KeCancelTimer(&CurrentThread->Tcb.Timer);
-   
+
+   /* If the ProcessoR Control Block's NpxThread points to the current thread
+    * unset it.
+    */
+   InterlockedCompareExchange((LONG *)&KeGetCurrentKPCR()->PrcbData.NpxThread,
+                              (LONG)NULL, (LONG)ETHREAD_TO_KTHREAD(CurrentThread));
+
    KeReleaseSpinLock(&PiThreadLock, oldIrql);
  
    PsLockProcess(CurrentProcess, FALSE);
+
    /* Remove the thread from the thread list of its process */
    RemoveEntryList(&CurrentThread->ThreadListEntry);
    Last = IsListEmpty(&CurrentProcess->ThreadListHead);

reactos/ntoskrnl/ps
w32call.c 1.17 -> 1.18
diff -u -r1.17 -r1.18
--- w32call.c	30 Oct 2004 23:48:57 -0000	1.17
+++ w32call.c	20 Nov 2004 23:46:37 -0000	1.18
@@ -1,4 +1,4 @@
-/* $Id: w32call.c,v 1.17 2004/10/30 23:48:57 navaraf Exp $
+/* $Id: w32call.c,v 1.18 2004/11/20 23:46:37 blight Exp $
  *
  * COPYRIGHT:              See COPYING in the top level directory
  * PROJECT:                ReactOS kernel
@@ -44,6 +44,7 @@
   PNTSTATUS CallbackStatus;
   PKTRAP_FRAME SavedTrapFrame;
   PVOID SavedCallbackStack;
+  PVOID SavedExceptionStack;
 } NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
 
 typedef struct
@@ -81,6 +82,7 @@
   PNTW32CALL_SAVED_STATE State;
   PKTRAP_FRAME SavedTrapFrame;
   PVOID SavedCallbackStack;
+  PVOID SavedExceptionStack;
 
   Thread = PsGetCurrentThread();
   if (Thread->Tcb.CallbackStack == NULL)
@@ -102,7 +104,8 @@
   StackLimit = State->SavedStackLimit;
   SavedTrapFrame = State->SavedTrapFrame;
   SavedCallbackStack = State->SavedCallbackStack;
-  
+  SavedExceptionStack = State->SavedExceptionStack;
+
   /*
    * Copy the callback status and the callback result to NtW32Call
    */
@@ -124,12 +127,20 @@
    * Restore the old stack.
    */
   KeRaiseIrql(HIGH_LEVEL, &oldIrql);
+  if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
+      ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentKPCR()->PrcbData.NpxThread)
+    {
+      memcpy((char*)InitialStack - sizeof(FX_SAVE_AREA),
+             (char*)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA),
+             sizeof(FX_SAVE_AREA));
+    }
   Thread->Tcb.InitialStack = InitialStack;
   Thread->Tcb.StackBase = StackBase;
   Thread->Tcb.StackLimit = StackLimit;
   Thread->Tcb.TrapFrame = SavedTrapFrame;
   Thread->Tcb.CallbackStack = SavedCallbackStack;
-  KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack;
+  KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)SavedExceptionStack;
+  Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS); /* set TS */
   KeStackSwitchAndRet((PVOID)(OldStack + 1));
 
   /* Should never return. */
@@ -258,7 +269,7 @@
   Thread = PsGetCurrentThread();
 
   /* Set up the new kernel and user environment. */
-  StackSize = (ULONG_PTR)(Thread->Tcb.StackBase - Thread->Tcb.StackLimit);
+  StackSize = (ULONG_PTR)Thread->Tcb.StackBase - Thread->Tcb.StackLimit;
   KeAcquireSpinLock(&CallbackStackListLock, &oldIrql);
   if (IsListEmpty(&CallbackStackListHead))
     {
@@ -274,18 +285,18 @@
 
       StackEntry = RemoveHeadList(&CallbackStackListHead);
       KeReleaseSpinLock(&CallbackStackListLock, oldIrql);
-      AssignedStack = CONTAINING_RECORD(StackEntry, NTW32CALL_CALLBACK_STACK, 
+      AssignedStack = CONTAINING_RECORD(StackEntry, NTW32CALL_CALLBACK_STACK,
 					ListEntry);
       NewStack = AssignedStack->BaseAddress;
-      
+
       MmUpdatePageDir(PsGetCurrentProcess(), NewStack, StackSize);
 
     }
   /* FIXME: Need to check whether we were interrupted from v86 mode. */
-  memcpy((char*)NewStack + StackSize - sizeof(KTRAP_FRAME), Thread->Tcb.TrapFrame,
-	 sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD)));
-  NewFrame = (PKTRAP_FRAME)((char*)NewStack + StackSize - sizeof(KTRAP_FRAME));
-  NewFrame->Esp -= (ArgumentLength + (4 * sizeof(ULONG))); 
+  memcpy((char*)NewStack + StackSize - sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA),
+         Thread->Tcb.TrapFrame, sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD)));
+  NewFrame = (PKTRAP_FRAME)((char*)NewStack + StackSize - sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA));
+  NewFrame->Esp -= (ArgumentLength + (4 * sizeof(ULONG)));
   NewFrame->Eip = (ULONG)LdrpGetSystemDllCallbackDispatcher();
   UserEsp = (PULONG)NewFrame->Esp;
   UserEsp[0] = 0;     /* Return address. */
@@ -304,10 +315,18 @@
   SavedState.CallbackStatus = &CallbackStatus;
   SavedState.SavedTrapFrame = Thread->Tcb.TrapFrame;
   SavedState.SavedCallbackStack = Thread->Tcb.CallbackStack;
+  SavedState.SavedExceptionStack = (PVOID)KeGetCurrentKPCR()->TSS->Esp0;
+  if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
+      ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentKPCR()->PrcbData.NpxThread)
+    {
+      memcpy((char*)NewStack + StackSize - sizeof(FX_SAVE_AREA),
+             (char*)SavedState.SavedInitialStack - sizeof(FX_SAVE_AREA),
+             sizeof(FX_SAVE_AREA));
+    }
   Thread->Tcb.InitialStack = Thread->Tcb.StackBase = (char*)NewStack + StackSize;
-  Thread->Tcb.StackLimit = (ULONG_PTR)NewStack;
-  Thread->Tcb.KernelStack = (char*)NewStack + StackSize - sizeof(KTRAP_FRAME);
-  KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack;
+  Thread->Tcb.StackLimit = (ULONG)NewStack;
+  Thread->Tcb.KernelStack = (char*)NewStack + StackSize - sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA);
+  KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA);
   KePushAndStackSwitchAndSysRet((ULONG)&SavedState, Thread->Tcb.KernelStack);
 
   /* 

reactos/ntoskrnl/ps/i386
continue.c 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- continue.c	15 Aug 2004 16:39:11 -0000	1.5
+++ continue.c	20 Nov 2004 23:46:37 -0000	1.6
@@ -1,4 +1,4 @@
-/* $Id: continue.c,v 1.5 2004/08/15 16:39:11 chorns Exp $
+/* $Id: continue.c,v 1.6 2004/11/20 23:46:37 blight Exp $
  *
  * COPYRIGHT:              See COPYING in the top level directory
  * PROJECT:                ReactOS kernel
@@ -32,6 +32,8 @@
 {
 	PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame;
 	PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
+	PFX_SAVE_AREA FxSaveArea;
+	KIRQL oldIrql;
 
 	DPRINT("NtContinue: Context: Eip=0x%x, Esp=0x%x\n", Context->Eip, Context->Esp );
 	PULONG Frame = 0;
@@ -54,12 +56,32 @@
 	}
 
 	/*
-	* Copy the supplied context over the register information that was saved
-	* on entry to kernel mode, it will then be restored on exit
-	* FIXME: Validate the context
-	*/
+	 * Copy the supplied context over the register information that was saved
+	 * on entry to kernel mode, it will then be restored on exit
+	 * FIXME: Validate the context
+	 */
 	KeContextToTrapFrame ( Context, TrapFrame );
 
+        /* Put the floating point context into the thread's FX_SAVE_AREA
+         * and make sure it is reloaded when needed.
+         */
+        FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)KeGetCurrentThread()->InitialStack - sizeof(FX_SAVE_AREA));
+        if (KiContextToFxSaveArea(FxSaveArea, Context))
+          {
+            KeGetCurrentThread()->NpxState = NPX_STATE_VALID;
+            KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+            if (KeGetCurrentKPCR()->PrcbData.NpxThread == KeGetCurrentThread())
+              {
+                KeGetCurrentKPCR()->PrcbData.NpxThread = NULL;
+                Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS);
+              }
+            else
+              {
+                ASSERT((Ke386GetCr0() & X86_CR0_TS) == X86_CR0_TS);
+              }
+            KeLowerIrql(oldIrql);
+          }
+
 	KeRosTrapReturn ( TrapFrame, PrevTrapFrame );
 
 	return STATUS_SUCCESS; /* this doesn't actually happen b/c KeRosTrapReturn() won't return */
CVSspam 0.2.8