diff --git a/reactos/ntoskrnl/include/internal/i386/intrin_i.h b/reactos/ntoskrnl/include/internal/i386/intrin_i.h index 3a2664ba5b4..35cfd8ecbcc 100644 --- a/reactos/ntoskrnl/include/internal/i386/intrin_i.h +++ b/reactos/ntoskrnl/include/internal/i386/intrin_i.h @@ -50,21 +50,6 @@ Ke386SaveFpuState(IN PFX_SAVE_AREA SaveArea) } } -FORCEINLINE -VOID -Ke386LoadFpuState(IN PFX_SAVE_AREA SaveArea) -{ - extern ULONG KeI386FxsrPresent; - if (KeI386FxsrPresent) - { - __asm__ __volatile__ ("fxrstor %0\n" : "=m"(SaveArea) : ); - } - else - { - __asm__ __volatile__ (".globl _FrRestore\n _FrRestore: \n frstor %0\n wait\n" : "=m"(SaveArea) : ); - } -} - FORCEINLINE USHORT Ke386GetLocalDescriptorTable() diff --git a/reactos/ntoskrnl/include/internal/i386/ke.h b/reactos/ntoskrnl/include/internal/i386/ke.h index cfe674c3dec..a610734a611 100644 --- a/reactos/ntoskrnl/include/internal/i386/ke.h +++ b/reactos/ntoskrnl/include/internal/i386/ke.h @@ -541,7 +541,6 @@ extern VOID NTAPI ExpInterlockedPopEntrySListFault(VOID); extern VOID NTAPI ExpInterlockedPopEntrySListResume(VOID); extern VOID __cdecl CopyParams(VOID); extern VOID __cdecl ReadBatch(VOID); -extern VOID __cdecl FrRestore(VOID); extern CHAR KiSystemCallExitBranch[]; extern CHAR KiSystemCallExit[]; extern CHAR KiSystemCallExit2[]; diff --git a/reactos/ntoskrnl/ke/i386/ctxswitch.S b/reactos/ntoskrnl/ke/i386/ctxswitch.S index 3491fcb6eba..3a35a3aa60d 100644 --- a/reactos/ntoskrnl/ke/i386/ctxswitch.S +++ b/reactos/ntoskrnl/ke/i386/ctxswitch.S @@ -159,4 +159,28 @@ PUBLIC @Ki386BiosCallReturnAddress@4 popad ret 4 +PUBLIC _FrRestore +PUBLIC @Ke386LoadFpuState@4 +@Ke386LoadFpuState@4: + + /* Check if we have FXSR and choose which operand to use */ + test byte ptr [_KeI386FxsrPresent], 1 + jz _FrRestore + + /* Restore all the FPU, MMX, XMM and MXCSR registers */ + fxrstor [ecx] + ret + + /* + * Just restore the basic FPU registers. + * This may raise an exception depending + * on the status word, which KiNpxHandler will + * need to check for and handle during delayed load + * to avoid raising an unhandled exception + * and crashing the system. + */ +_FrRestore: + frstor [ecx] + ret + END diff --git a/reactos/ntoskrnl/ke/i386/traphdlr.c b/reactos/ntoskrnl/ke/i386/traphdlr.c index 4170a7b13b1..9e5defed420 100644 --- a/reactos/ntoskrnl/ke/i386/traphdlr.c +++ b/reactos/ntoskrnl/ke/i386/traphdlr.c @@ -15,6 +15,9 @@ VOID KiFastCallEntry(VOID); VOID KiFastCallEntryWithSingleStep(VOID); +extern PVOID FrRestore; +VOID FASTCALL Ke386LoadFpuState(IN PFX_SAVE_AREA SaveArea); + /* GLOBALS ********************************************************************/ UCHAR KiTrapPrefixTable[] = @@ -251,16 +254,16 @@ KiNpxHandler(IN PKTRAP_FRAME TrapFrame, SaveArea->Cr0NpxState |= CR0_TS; /* Only valid if it happened during a restore */ - //if ((PVOID)TrapFrame->Eip == FrRestore) + if ((PVOID)TrapFrame->Eip == FrRestore) { /* It did, so just skip the instruction */ - //TrapFrame->Eip += 3; /* sizeof(FRSTOR) */ - //KiEoiHelper(TrapFrame); + TrapFrame->Eip += 3; /* Size of FRSTOR instruction */ + KiEoiHelper(TrapFrame); } } /* User or kernel trap -- get ready to issue an exception */ - //if (Thread->NpxState == NPX_STATE_NOT_LOADED) + if (Thread->NpxState == NPX_STATE_NOT_LOADED) { /* Update CR0 */ Cr0 = __readcr0(); @@ -744,7 +747,7 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame) KiEnterTrap(TrapFrame); /* Try to handle NPX delay load */ - while (TRUE) + for (;;) { /* Get the current thread */ Thread = KeGetCurrentThread(); @@ -775,15 +778,14 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame) NpxSaveArea = KiGetThreadNpxArea(NpxThread); /* Save FPU state */ - DPRINT("FIXME: Save FPU state: %p\n", NpxSaveArea); - //Ke386SaveFpuState(NpxSaveArea); + Ke386SaveFpuState(NpxSaveArea); /* Update NPX state */ NpxThread->NpxState = NPX_STATE_NOT_LOADED; } /* Load FPU state */ - //Ke386LoadFpuState(SaveArea); + Ke386LoadFpuState(SaveArea); /* Update NPX state */ Thread->NpxState = NPX_STATE_LOADED; @@ -823,7 +825,7 @@ KiTrap07Handler(IN PKTRAP_FRAME TrapFrame) { /* * 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. + * but we could have lost track of that due to a BIOS call. * Make sure MP is still set, which should verify the theory. */ if (Cr0 & CR0_MP)