Definition at line 714 of file traphdlr.c. {
PKTHREAD Thread, NpxThread;
PFX_SAVE_AREA SaveArea, NpxSaveArea;
ULONG Cr0;
/* Save trap frame */
KiEnterTrap(TrapFrame);
/* Try to handle NPX delay load */
while (TRUE)
{
/* Get the current thread */
Thread = KeGetCurrentThread();
/* Get the NPX frame */
SaveArea = KiGetThreadNpxArea(Thread);
/* Check if emulation is enabled */
if (SaveArea->Cr0NpxState & CR0_EM)
{
/* Not implemented */
UNIMPLEMENTED_FATAL();
}
/* Save CR0 and check NPX state */
Cr0 = __readcr0();
if (Thread->NpxState != NPX_STATE_LOADED)
{
/* Update CR0 */
Cr0 &= ~(CR0_MP | CR0_EM | CR0_TS);
__writecr0(Cr0);
/* Get the NPX thread */
NpxThread = KeGetCurrentPrcb()->NpxThread;
if (NpxThread)
{
/* Get the NPX frame */
NpxSaveArea = KiGetThreadNpxArea(NpxThread);
/* Save FPU state */
DPRINT("FIXME: Save FPU state: %p\n", NpxSaveArea);
//Ke386SaveFpuState(NpxSaveArea);
/* Update NPX state */
NpxThread->NpxState = NPX_STATE_NOT_LOADED;
}
/* Load FPU state */
//Ke386LoadFpuState(SaveArea);
/* Update NPX state */
Thread->NpxState = NPX_STATE_LOADED;
KeGetCurrentPrcb()->NpxThread = Thread;
/* Enable interrupts */
_enable();
/* Check if CR0 needs to be reloaded due to context switch */
if (!SaveArea->Cr0NpxState) KiEoiHelper(TrapFrame);
/* Otherwise, we need to reload CR0, disable interrupts */
_disable();
/* Reload CR0 */
Cr0 = __readcr0();
Cr0 |= SaveArea->Cr0NpxState;
__writecr0(Cr0);
/* Now restore interrupts and check for TS */
_enable();
if (Cr0 & CR0_TS) KiEoiHelper(TrapFrame);
/* We're still here -- clear TS and try again */
__writecr0(__readcr0() &~ CR0_TS);
_disable();
}
else
{
/* This is an actual fault, not a lack of FPU state */
break;
}
}
/* TS should not be set */
if (Cr0 & CR0_TS)
{
/*
* If it's incorrectly set, then maybe the state is actually still valid
* but we could've lock track of that due to a BIOS call.
* Make sure MP is still set, which should verify the theory.
*/
if (Cr0 & CR0_MP)
{
/* Indeed, the state is actually still valid, so clear TS */
__writecr0(__readcr0() &~ CR0_TS);
KiEoiHelper(TrapFrame);
}
/* Otherwise, something strange is going on */
KeBugCheckWithTf(TRAP_CAUSE_UNKNOWN, 2, Cr0, 0, 0, TrapFrame);
}
/* It's not a delayed load, so process this trap as an NPX fault */
KiNpxHandler(TrapFrame, Thread, SaveArea);
}
|