mirror of
https://github.com/reactos/reactos.git
synced 2024-09-03 09:09:19 +00:00
Huh, what? Oops! Just some stuff which noone cares about...
svn path=/trunk/; revision=18292
This commit is contained in:
parent
94f68fddfc
commit
8f4754e6fa
|
@ -12,10 +12,13 @@ NTSTATUS
|
||||||
KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr);
|
KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr);
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST FLOATING_SAVE_AREA *FloatingSaveArea);
|
KiFxSaveAreaToFloatingSaveArea(FLOATING_SAVE_AREA *FloatingSaveArea, CONST PFX_SAVE_AREA FxSaveArea);
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context);
|
KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context);
|
||||||
|
|
||||||
|
PFX_SAVE_AREA
|
||||||
|
KiGetFpuState(PKTHREAD Thread);
|
||||||
|
|
||||||
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H */
|
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H */
|
||||||
|
|
||||||
|
|
|
@ -820,6 +820,8 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
||||||
IN PKEXCEPTION_FRAME ExceptionFrame,
|
IN PKEXCEPTION_FRAME ExceptionFrame,
|
||||||
IN OUT PCONTEXT Context)
|
IN OUT PCONTEXT Context)
|
||||||
{
|
{
|
||||||
|
PFX_SAVE_AREA FxSaveArea = NULL;
|
||||||
|
|
||||||
/* Start with the Control flags */
|
/* Start with the Control flags */
|
||||||
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
|
||||||
{
|
{
|
||||||
|
@ -890,40 +892,39 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
|
||||||
Context->Edi = TrapFrame->Edi;
|
Context->Edi = TrapFrame->Edi;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
|
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* FIXME: Implement this case
|
* FIXME: Implement this case
|
||||||
*/
|
*/
|
||||||
Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
|
Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
|
||||||
}
|
}
|
||||||
if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
|
if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
|
||||||
{
|
{
|
||||||
/*
|
FxSaveArea = KiGetFpuState(KeGetCurrentThread());
|
||||||
* FIXME: Implement this case
|
if (FxSaveArea != NULL)
|
||||||
*
|
{
|
||||||
* I think this should only be filled for FPU exceptions, otherwise I
|
KiFxSaveAreaToFloatingSaveArea(&Context->FloatSave, FxSaveArea);
|
||||||
* 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.
|
else
|
||||||
* -blight
|
{
|
||||||
*/
|
Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
|
||||||
Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
|
}
|
||||||
}
|
}
|
||||||
#if 0
|
if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
|
||||||
if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
|
{
|
||||||
{
|
if (FxSaveArea == NULL)
|
||||||
/*
|
FxSaveArea = KiGetFpuState(KeGetCurrentThread());
|
||||||
* FIXME: Investigate this
|
if (FxSaveArea != NULL)
|
||||||
*
|
{
|
||||||
* This is the XMM state (first 512 bytes of FXSAVE_FORMAT/FX_SAVE_AREA)
|
memcpy(Context->ExtendedRegisters, &FxSaveArea->U.FxArea,
|
||||||
* This should only be filled in case of a SIMD exception I think, so
|
min(sizeof (Context->ExtendedRegisters), sizeof (FxSaveArea->U.FxArea)) );
|
||||||
* 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)
|
else
|
||||||
* -blight
|
{
|
||||||
*/
|
Context->ContextFlags &= (~CONTEXT_EXTENDED_REGISTERS) | CONTEXT_i386;
|
||||||
Context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS;
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
@ -1180,8 +1181,11 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
/* Check if User Mode */
|
/* Check if User Mode */
|
||||||
if (PreviousMode == UserMode)
|
if (PreviousMode == UserMode)
|
||||||
{
|
{
|
||||||
|
extern ULONG FxsrSupport;
|
||||||
/* Add the FPU Flag */
|
/* Add the FPU Flag */
|
||||||
Context.ContextFlags |= CONTEXT_FLOATING_POINT;
|
Context.ContextFlags |= CONTEXT_FLOATING_POINT;
|
||||||
|
if (FxsrSupport)
|
||||||
|
Context.ContextFlags |= CONTEXT_EXTENDED_REGISTERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get a Context */
|
/* Get a Context */
|
||||||
|
@ -1259,7 +1263,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
|
|
||||||
/* Probe stack and copy Context */
|
/* Probe stack and copy Context */
|
||||||
ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
|
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 */
|
/* Align exception record size and get stack pointer */
|
||||||
Size = (sizeof(EXCEPTION_RECORD) -
|
Size = (sizeof(EXCEPTION_RECORD) -
|
||||||
|
@ -1272,7 +1276,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
|
||||||
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
|
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
|
||||||
Size + 2 * sizeof(ULONG_PTR),
|
Size + 2 * sizeof(ULONG_PTR),
|
||||||
sizeof(ULONG));
|
sizeof(ULONG));
|
||||||
RtlMoveMemory((PVOID)NewStack, ExceptionRecord, Size);
|
RtlCopyMemory((PVOID)NewStack, ExceptionRecord, Size);
|
||||||
|
|
||||||
/* Now write the two params for the user-mode dispatcher */
|
/* Now write the two params for the user-mode dispatcher */
|
||||||
*(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) = Stack;
|
*(PULONG_PTR)(NewStack - 1 * sizeof(ULONG_PTR)) = Stack;
|
||||||
|
|
|
@ -62,6 +62,7 @@ KiTagWordFnsaveToFxsave(USHORT TagWord)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STATIC USHORT
|
STATIC USHORT
|
||||||
KiTagWordFxsaveToFnsave(PFXSAVE_FORMAT FxSave)
|
KiTagWordFxsaveToFnsave(PFXSAVE_FORMAT FxSave)
|
||||||
{
|
{
|
||||||
|
@ -107,6 +108,7 @@ KiTagWordFxsaveToFnsave(PFXSAVE_FORMAT FxSave)
|
||||||
return TagWord;
|
return TagWord;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
STATIC VOID
|
STATIC VOID
|
||||||
KiFnsaveToFxsaveFormat(PFXSAVE_FORMAT FxSave, CONST PFNSAVE_FORMAT FnSave)
|
KiFnsaveToFxsaveFormat(PFXSAVE_FORMAT FxSave, CONST PFNSAVE_FORMAT FnSave)
|
||||||
{
|
{
|
||||||
|
@ -154,7 +156,8 @@ KiFxsaveToFnsaveFormat(PFNSAVE_FORMAT FnSave, CONST PFXSAVE_FORMAT FxSave)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
|
||||||
|
STATIC VOID
|
||||||
KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST FLOATING_SAVE_AREA *FloatingSaveArea)
|
KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST FLOATING_SAVE_AREA *FloatingSaveArea)
|
||||||
{
|
{
|
||||||
if (FxsrSupport)
|
if (FxsrSupport)
|
||||||
|
@ -169,6 +172,22 @@ KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST FLOATING_SAVE_ARE
|
||||||
FxSaveArea->Cr0NpxState = FloatingSaveArea->Cr0NpxState;
|
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
|
BOOL
|
||||||
KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context)
|
KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context)
|
||||||
{
|
{
|
||||||
|
@ -214,6 +233,7 @@ KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context)
|
||||||
return FpuContextChanged;
|
return FpuContextChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VOID INIT_FUNCTION
|
VOID INIT_FUNCTION
|
||||||
KiCheckFPU(VOID)
|
KiCheckFPU(VOID)
|
||||||
{
|
{
|
||||||
|
@ -300,68 +320,38 @@ KiCheckFPU(VOID)
|
||||||
Ke386RestoreFlags(Flags);
|
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
|
PFX_SAVE_AREA
|
||||||
|
KiGetFpuState(PKTHREAD Thread)
|
||||||
NTSTATUS STDCALL
|
|
||||||
KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
|
|
||||||
{
|
{
|
||||||
char *FpState;
|
PFX_SAVE_AREA FxSaveArea = NULL;
|
||||||
|
KIRQL OldIrql;
|
||||||
|
|
||||||
ASSERT_IRQL(DISPATCH_LEVEL);
|
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||||
|
if (Thread->NpxState & NPX_STATE_VALID)
|
||||||
/* check if we are doing software emulation */
|
|
||||||
if (!HardwareMathSupport)
|
|
||||||
{
|
{
|
||||||
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
KeLowerIrql(OldIrql);
|
||||||
|
|
||||||
FpState = ExAllocatePool(NonPagedPool, FPU_STATE_SIZE);
|
return FxSaveArea;
|
||||||
if (NULL == FpState)
|
|
||||||
{
|
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
|
||||||
}
|
|
||||||
*((PVOID *) Save) = FpState;
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
NTSTATUS
|
||||||
KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
||||||
|
@ -403,7 +393,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
||||||
if (NpxThread != NULL)
|
if (NpxThread != NULL)
|
||||||
{
|
{
|
||||||
KeGetCurrentPrcb()->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 */
|
/* the fnsave might raise a delayed #MF exception */
|
||||||
if (FxsrSupport)
|
if (FxsrSupport)
|
||||||
{
|
{
|
||||||
|
@ -420,17 +410,17 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
||||||
|
|
||||||
/* restore the state of the current thread */
|
/* restore the state of the current thread */
|
||||||
ASSERT((CurrentThread->NpxState & NPX_STATE_DIRTY) == 0);
|
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 (CurrentThread->NpxState & NPX_STATE_VALID)
|
||||||
{
|
{
|
||||||
if (FxsrSupport)
|
if (FxsrSupport)
|
||||||
{
|
{
|
||||||
FxSaveArea->U.FxArea.MXCsr &= MxcsrFeatureMask;
|
FxSaveArea->U.FxArea.MXCsr &= MxcsrFeatureMask;
|
||||||
asm volatile("fxrstor %0" : : "m"(FxSaveArea->U.FxArea));
|
asm volatile("fxrstor %0" : : "m"(FxSaveArea->U.FxArea));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
asm volatile("frstor %0" : : "m"(FxSaveArea->U.FnArea));
|
asm volatile("frstor %0" : : "m"(FxSaveArea->U.FnArea));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* NpxState & NPX_STATE_INVALID */
|
else /* NpxState & NPX_STATE_INVALID */
|
||||||
|
@ -448,7 +438,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
||||||
}
|
}
|
||||||
else if (!FpuInitialized)
|
else if (!FpuInitialized)
|
||||||
{
|
{
|
||||||
asm volatile("finit");
|
asm volatile("fninit");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeGetCurrentPrcb()->NpxThread = CurrentThread;
|
KeGetCurrentPrcb()->NpxThread = CurrentThread;
|
||||||
|
@ -465,24 +455,31 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
||||||
else /* ExceptionNr == 16 || ExceptionNr == 19 */
|
else /* ExceptionNr == 16 || ExceptionNr == 19 */
|
||||||
{
|
{
|
||||||
EXCEPTION_RECORD Er;
|
EXCEPTION_RECORD Er;
|
||||||
UCHAR DummyContext[sizeof(CONTEXT) + 16];
|
|
||||||
PCONTEXT Context;
|
|
||||||
KPROCESSOR_MODE PreviousMode;
|
KPROCESSOR_MODE PreviousMode;
|
||||||
PKTHREAD CurrentThread, NpxThread;
|
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*/
|
ASSERT(ExceptionNr == 16 || ExceptionNr == 19); /* math fault or XMM fault*/
|
||||||
|
|
||||||
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
|
||||||
|
|
||||||
NpxThread = KeGetCurrentPrcb()->NpxThread;
|
NpxThread = KeGetCurrentPrcb()->NpxThread;
|
||||||
CurrentThread = KeGetCurrentThread();
|
CurrentThread = KeGetCurrentThread();
|
||||||
if (NpxThread == NULL)
|
if (NpxThread == NULL)
|
||||||
{
|
{
|
||||||
KeLowerIrql(oldIrql);
|
KeLowerIrql(OldIrql);
|
||||||
DPRINT1("!!! Math/Xmm fault ignored! (NpxThread == NULL)\n");
|
DPRINT("Math/Xmm fault ignored! (NpxThread == NULL)\n");
|
||||||
return STATUS_SUCCESS;
|
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);
|
PreviousMode = ((Tf->Cs & 0xffff) == USER_CS) ? (UserMode) : (KernelMode);
|
||||||
DPRINT("Math/Xmm fault happened! (PreviousMode = %s)\n",
|
DPRINT("Math/Xmm fault happened! (PreviousMode = %s)\n",
|
||||||
|
@ -490,63 +487,34 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
||||||
|
|
||||||
ASSERT(NpxThread == CurrentThread); /* FIXME: Is not always true I think */
|
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 */
|
/* Get FPU/XMM state */
|
||||||
Context->FloatSave.Cr0NpxState = 0;
|
KeLowerIrql(OldIrql);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 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 */
|
/* Determine exception code */
|
||||||
if (ExceptionNr == 16)
|
if (ExceptionNr == 16)
|
||||||
{
|
{
|
||||||
USHORT FpuStatusWord = Context->FloatSave.StatusWord & 0xffff;
|
|
||||||
DPRINT("FpuStatusWord = 0x%04x\n", FpuStatusWord);
|
DPRINT("FpuStatusWord = 0x%04x\n", FpuStatusWord);
|
||||||
|
|
||||||
if (FpuStatusWord & X87_SW_IE)
|
if (FpuEnv->StatusWord & X87_SW_IE)
|
||||||
Er.ExceptionCode = STATUS_FLOAT_INVALID_OPERATION;
|
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;
|
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;
|
Er.ExceptionCode = STATUS_FLOAT_DIVIDE_BY_ZERO;
|
||||||
else if (FpuStatusWord & X87_SW_OE)
|
else if (FpuEnv->StatusWord & X87_SW_OE)
|
||||||
Er.ExceptionCode = STATUS_FLOAT_OVERFLOW;
|
Er.ExceptionCode = STATUS_FLOAT_OVERFLOW;
|
||||||
else if (FpuStatusWord & X87_SW_UE)
|
else if (FpuEnv->StatusWord & X87_SW_UE)
|
||||||
Er.ExceptionCode = STATUS_FLOAT_UNDERFLOW;
|
Er.ExceptionCode = STATUS_FLOAT_UNDERFLOW;
|
||||||
else if (FpuStatusWord & X87_SW_PE)
|
else if (FpuEnv->StatusWord & X87_SW_PE)
|
||||||
Er.ExceptionCode = STATUS_FLOAT_INEXACT_RESULT;
|
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;
|
Er.ExceptionCode = STATUS_FLOAT_STACK_CHECK;
|
||||||
else
|
else
|
||||||
ASSERT(0); /* not reached */
|
ASSERT(0); /* not reached */
|
||||||
/* FIXME: is this the right way to get the correct EIP of the faulting instruction? */
|
Er.ExceptionAddress = (PVOID)FpuEnv->ErrorOffset;
|
||||||
Er.ExceptionAddress = (PVOID)Context->FloatSave.ErrorOffset;
|
|
||||||
}
|
}
|
||||||
else /* ExceptionNr == 19 */
|
else /* ExceptionNr == 19 */
|
||||||
{
|
{
|
||||||
/* FIXME: When should we use STATUS_FLOAT_MULTIPLE_FAULTS? */
|
|
||||||
Er.ExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS;
|
Er.ExceptionCode = STATUS_FLOAT_MULTIPLE_TRAPS;
|
||||||
Er.ExceptionAddress = (PVOID)Tf->Eip;
|
Er.ExceptionAddress = (PVOID)Tf->Eip;
|
||||||
}
|
}
|
||||||
|
@ -565,3 +533,67 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
||||||
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue