Huh, what? Oops! Just some stuff which noone cares about...
Modified: trunk/reactos/ntoskrnl/include/internal/i386/fpu.h
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
Modified: trunk/reactos/ntoskrnl/ke/i386/fpu.c
_____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/fpu.h
--- trunk/reactos/ntoskrnl/include/internal/i386/fpu.h 2005-10-06
11:59:15 UTC (rev 18291)
+++ trunk/reactos/ntoskrnl/include/internal/i386/fpu.h 2005-10-06
12:36:53 UTC (rev 18292)
@@ -12,10 +12,13 @@
KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr);
VOID
-KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST
FLOATING_SAVE_AREA *FloatingSaveArea);
+KiFxSaveAreaToFloatingSaveArea(FLOATING_SAVE_AREA *FloatingSaveArea,
CONST PFX_SAVE_AREA FxSaveArea);
BOOL
KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context);
+PFX_SAVE_AREA
+KiGetFpuState(PKTHREAD Thread);
+
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H */
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
--- trunk/reactos/ntoskrnl/ke/i386/exp.c 2005-10-06 11:59:15 UTC
(rev 18291)
+++ trunk/reactos/ntoskrnl/ke/i386/exp.c 2005-10-06 12:36:53 UTC
(rev 18292)
@@ -820,6 +820,8 @@
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT Context)
{
+ PFX_SAVE_AREA FxSaveArea = NULL;
+
/* Start with the Control flags */
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
@@ -890,40 +892,39 @@
Context->Edi = TrapFrame->Edi;
}
- if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
CONTEXT_DEBUG_REGISTERS)
- {
- /*
- * FIXME: Implement this case
- */
- Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) |
CONTEXT_i386;
- }
- if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
CONTEXT_FLOATING_POINT)
- {
- /*
- * FIXME: Implement this case
- *
- * I think this should only be filled for FPU exceptions,
otherwise I
- * would not know where to get it from as it can be the current
state
- * of the FPU or already saved in the thread's FPU save area.
- * -blight
- */
- Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) |
CONTEXT_i386;
- }
-#if 0
- if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
CONTEXT_EXTENDED_REGISTERS)
- {
- /*
- * FIXME: Investigate this
- *
- * This is the XMM state (first 512 bytes of
FXSAVE_FORMAT/FX_SAVE_AREA)
- * This should only be filled in case of a SIMD exception I
think, so
- * this is not the right place (like for FPU the state could
already be
- * saved in the thread's FX_SAVE_AREA or still be in the CPU)
- * -blight
- */
- Context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS;
- }
-#endif
+ if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
CONTEXT_DEBUG_REGISTERS)
+ {
+ /*
+ * FIXME: Implement this case
+ */
+ Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) |
CONTEXT_i386;
+ }
+ if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) ==
CONTEXT_FLOATING_POINT)
+ {
+ FxSaveArea = KiGetFpuState(KeGetCurrentThread());
+ if (FxSaveArea != NULL)
+ {
+ KiFxSaveAreaToFloatingSaveArea(&Context->FloatSave,
FxSaveArea);
+ }
+ else
+ {
+ Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) |
CONTEXT_i386;
+ }
+ }
+ if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) ==
CONTEXT_EXTENDED_REGISTERS)
+ {
+ if (FxSaveArea == NULL)
+ 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;
+ }
+ }
}
VOID
@@ -1180,8 +1181,11 @@
/* 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;
}
/* Get a Context */
@@ -1259,7 +1263,7 @@
/* Probe stack and copy Context */
ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
- RtlMoveMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
+ RtlCopyMemory((PVOID)Stack, &Context, sizeof(CONTEXT));
/* Align exception record size and get stack pointer */
Size = (sizeof(EXCEPTION_RECORD) -
@@ -1272,7 +1276,7 @@
ProbeForWrite((PVOID)(NewStack - 2 *
sizeof(ULONG_PTR)),
Size + 2 * sizeof(ULONG_PTR),
sizeof(ULONG));
- RtlMoveMemory((PVOID)NewStack, ExceptionRecord, Size);
+ RtlCopyMemory((PVOID)NewStack, ExceptionRecord, Size);
/* Now write the two params for the user-mode
dispatcher */
*(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) =
Stack;
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/fpu.c
--- trunk/reactos/ntoskrnl/ke/i386/fpu.c 2005-10-06 11:59:15 UTC
(rev 18291)
+++ trunk/reactos/ntoskrnl/ke/i386/fpu.c 2005-10-06 12:36:53 UTC
(rev 18292)
@@ -62,6 +62,7 @@
return tmp;
}
+
STATIC USHORT
KiTagWordFxsaveToFnsave(PFXSAVE_FORMAT FxSave)
{
@@ -107,6 +108,7 @@
return TagWord;
}
+
STATIC VOID
KiFnsaveToFxsaveFormat(PFXSAVE_FORMAT FxSave, CONST PFNSAVE_FORMAT
FnSave)
{
@@ -154,7 +156,8 @@
}
}
-VOID
+
+STATIC VOID
KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST
FLOATING_SAVE_AREA *FloatingSaveArea)
{
if (FxsrSupport)
@@ -169,6 +172,22 @@
FxSaveArea->Cr0NpxState = FloatingSaveArea->Cr0NpxState;
}
+
+VOID
+KiFxSaveAreaToFloatingSaveArea(FLOATING_SAVE_AREA *FloatingSaveArea,
CONST PFX_SAVE_AREA FxSaveArea)
+{
+ if (FxsrSupport)
+ {
+ KiFxsaveToFnsaveFormat((PFNSAVE_FORMAT)FloatingSaveArea,
&FxSaveArea->U.FxArea);
+ }
+ else
+ {
+ memcpy(FloatingSaveArea, &FxSaveArea->U.FnArea,
sizeof(FxSaveArea->U.FnArea));
+ }
+ FloatingSaveArea->Cr0NpxState = FxSaveArea->Cr0NpxState;
+}
+
+
BOOL
KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context)
{
@@ -214,6 +233,7 @@
return FpuContextChanged;
}
+
VOID INIT_FUNCTION
KiCheckFPU(VOID)
{
@@ -300,69 +320,39 @@
Ke386RestoreFlags(Flags);
}
-/* This is a rather naive implementation of
Ke(Save/Restore)FloatingPointState
- which will not work for WDM drivers. Please feel free to improve */
-#define FPU_STATE_SIZE 108
-
-NTSTATUS STDCALL
-KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
+PFX_SAVE_AREA
+KiGetFpuState(PKTHREAD Thread)
{
- char *FpState;
+ PFX_SAVE_AREA FxSaveArea = NULL;
+ KIRQL OldIrql;
- ASSERT_IRQL(DISPATCH_LEVEL);
-
- /* check if we are doing software emulation */
- if (!HardwareMathSupport)
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+ if (Thread->NpxState & NPX_STATE_VALID)
{
- return STATUS_ILLEGAL_FLOAT_CONTEXT;
- }
+ FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)Thread->InitialStack -
sizeof (FX_SAVE_AREA));
+ if (Thread->NpxState & NPX_STATE_DIRTY)
+ {
+ ASSERT(KeGetCurrentPrcb()->NpxThread == Thread);
+ ASSERT((Ke386GetCr0() & X86_CR0_TS) == 0);
- FpState = ExAllocatePool(NonPagedPool, FPU_STATE_SIZE);
- if (NULL == FpState)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
+ if (FxsrSupport)
+ asm volatile("fxsave %0" : :
"m"(FxSaveArea->U.FxArea));
+ else
+ {
+ KeGetCurrentPrcb()->NpxThread = NULL;
+ asm volatile("fnsave %0" : :
"m"(FxSaveArea->U.FnArea));
+ Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS); /* FPU state
has to be reloaded because fnsave changes it. */
+ }
+ Thread->NpxState = NPX_STATE_VALID;
+ }
}
- *((PVOID *) Save) = FpState;
+ KeLowerIrql(OldIrql);
-#if defined(__GNUC__)
- asm volatile("fsave %0\n\t" : "=m" (*FpState));
-#elif defined(_MSC_VER)
- __asm mov eax, FpState;
- __asm fsave [eax];
-#else
-#error Unknown compiler for inline assembler
-#endif
-
- KeGetCurrentThread()->NpxIrql = KeGetCurrentIrql();
-
- return STATUS_SUCCESS;
+ return FxSaveArea;
}
-NTSTATUS STDCALL
-KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
-{
- 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)
- __asm mov eax, FpState;
- __asm frstor [eax];
-#else
-#error Unknown compiler for inline assembler
-#endif
-
- ExFreePool(FpState);
-
- return STATUS_SUCCESS;
-}
-
NTSTATUS
KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
{
@@ -403,7 +393,7 @@
if (NpxThread != NULL)
{
KeGetCurrentPrcb()->NpxThread = NULL;
- FxSaveArea = (PFX_SAVE_AREA)((char
*)NpxThread->InitialStack - sizeof (FX_SAVE_AREA));
+ FxSaveArea =
(PFX_SAVE_AREA)((ULONG_PTR)NpxThread->InitialStack - sizeof
(FX_SAVE_AREA));
/* the fnsave might raise a delayed #MF exception */
if (FxsrSupport)
{
@@ -420,17 +410,17 @@
/* 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));
+ FxSaveArea =
(PFX_SAVE_AREA)((ULONG_PTR)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));
+ FxSaveArea->U.FxArea.MXCsr &= MxcsrFeatureMask;
+ asm volatile("fxrstor %0" : :
"m"(FxSaveArea->U.FxArea));
}
else
{
- asm volatile("frstor %0" : :
"m"(FxSaveArea->U.FnArea));
+ asm volatile("frstor %0" : :
"m"(FxSaveArea->U.FnArea));
}
}
else /* NpxState & NPX_STATE_INVALID */
@@ -448,7 +438,7 @@
}
else if (!FpuInitialized)
{
- asm volatile("finit");
+ asm volatile("fninit");
}
}
KeGetCurrentPrcb()->NpxThread = CurrentThread;
@@ -465,24 +455,31 @@
else /* ExceptionNr == 16 || ExceptionNr == 19 */
{
EXCEPTION_RECORD Er;
- UCHAR DummyContext[sizeof(CONTEXT) + 16];
- PCONTEXT Context;
KPROCESSOR_MODE PreviousMode;
PKTHREAD CurrentThread, NpxThread;
- KIRQL oldIrql;
+ KIRQL OldIrql;
+ ULONG FpuEnvBuffer[7];
+ PFNSAVE_FORMAT FpuEnv = (PFNSAVE_FORMAT)FpuEnvBuffer;
ASSERT(ExceptionNr == 16 || ExceptionNr == 19); /* math fault
or XMM fault*/
- KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
+ KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
NpxThread = KeGetCurrentPrcb()->NpxThread;
CurrentThread = KeGetCurrentThread();
if (NpxThread == NULL)
{
- KeLowerIrql(oldIrql);
- DPRINT1("!!! Math/Xmm fault ignored! (NpxThread ==
NULL)\n");
+ KeLowerIrql(OldIrql);
+ DPRINT("Math/Xmm fault ignored! (NpxThread == NULL)\n");
return STATUS_SUCCESS;
}
+ if (ExceptionNr == 16)
+ {
+ asm volatile("fnstenv %0" : : "m"(*FpuEnv));
+ asm volatile("fldenv %0" : : "m"(*FpuEnv)); /* Stupid
x87... */
+ FpuEnv->StatusWord &= 0xffff;
+ }
+ KeLowerIrql(OldIrql);
PreviousMode = ((Tf->Cs & 0xffff) == USER_CS) ? (UserMode) :
(KernelMode);
DPRINT("Math/Xmm fault happened! (PreviousMode = %s)\n",
@@ -490,63 +487,34 @@
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);
-
KiFnsaveToFxsaveFormat((PFXSAVE_FORMAT)Context->ExtendedRegisters,
FnSave);
- }
+ KeLowerIrql(OldIrql);
- /* Fill the rest of the context */
- Context->ContextFlags = CONTEXT_FULL;
- KeTrapFrameToContext(Tf, NULL, 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)
+ if (FpuEnv->StatusWord & X87_SW_IE)
Er.ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
- else if (FpuStatusWord & X87_SW_DE)
+ else if (FpuEnv->StatusWord & X87_SW_DE)
Er.ExceptionCode = STATUS_FLOAT_DENORMAL_OPERAND;
- else if (FpuStatusWord & X87_SW_ZE)
+ else if (FpuEnv->StatusWord & X87_SW_ZE)
Er.ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
- else if (FpuStatusWord & X87_SW_OE)
- Er.ExceptionCode = STATUS_FLOAT_OVERFLOW;
- else if (FpuStatusWord & X87_SW_UE)
+ else if (FpuEnv->StatusWord & X87_SW_OE)
+ Er.ExceptionCode = STATUS_FLOAT_OVERFLOW;
+ else if (FpuEnv->StatusWord & X87_SW_UE)
Er.ExceptionCode = STATUS_FLOAT_UNDERFLOW;
- else if (FpuStatusWord & X87_SW_PE)
+ else if (FpuEnv->StatusWord & X87_SW_PE)
Er.ExceptionCode = STATUS_FLOAT_INEXACT_RESULT;
- else if (FpuStatusWord & X87_SW_SE)
+ else if (FpuEnv->StatusWord & X87_SW_SE)
Er.ExceptionCode = STATUS_FLOAT_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;
+ Er.ExceptionAddress = (PVOID)FpuEnv->ErrorOffset;
}
else /* ExceptionNr == 19 */
{
- /* FIXME: When should we use STATUS_FLOAT_MULTIPLE_FAULTS?
*/
Er.ExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS;
Er.ExceptionAddress = (PVOID)Tf->Eip;
}
@@ -565,3 +533,67 @@
return STATUS_UNSUCCESSFUL;
}
+
+
+/* This is a rather naive implementation of
Ke(Save/Restore)FloatingPointState
+ which will not work for WDM drivers. Please feel free to improve */
+
+NTSTATUS STDCALL
+KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
+{
+ PFNSAVE_FORMAT FpState;
+
+ ASSERT_IRQL(DISPATCH_LEVEL);
+
+ /* check if we are doing software emulation */
+ if (!HardwareMathSupport)
+ {
+ return STATUS_ILLEGAL_FLOAT_CONTEXT;
+ }
+
+ FpState = ExAllocatePool(NonPagedPool, sizeof (FNSAVE_FORMAT));
+ if (NULL == FpState)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ *((PVOID *) Save) = FpState;
+
+#if defined(__GNUC__)
+ asm volatile("fnsave %0\n\t" : "=m" (*FpState));
+#elif defined(_MSC_VER)
+ __asm mov eax, FpState;
+ __asm fsave [eax];
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+ KeGetCurrentThread()->NpxIrql = KeGetCurrentIrql();
+
+ return STATUS_SUCCESS;
+}
+
+
+NTSTATUS STDCALL
+KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
+{
+ PFNSAVE_FORMAT FpState = *((PVOID *) Save);
+
+ if (KeGetCurrentThread()->NpxIrql != KeGetCurrentIrql())
+ {
+ KEBUGCHECK(UNDEFINED_BUG_CODE);
+ }
+
+#if defined(__GNUC__)
+ asm volatile("fnclex\n\t");
+ asm volatile("frstor %0\n\t" : "=m" (*FpState));
+#elif defined(_MSC_VER)
+ __asm mov eax, FpState;
+ __asm frstor [eax];
+#else
+#error Unknown compiler for inline assembler
+#endif
+
+ ExFreePool(FpState);
+
+ return STATUS_SUCCESS;
+}