- Small patch to fix (delayed) loading of floating point state. Enables the special...
authorStefan Ginsberg <stefanginsberg@gmail.com>
Tue, 1 Sep 2015 00:20:57 +0000 (00:20 +0000)
committerStefan Ginsberg <stefanginsberg@gmail.com>
Tue, 1 Sep 2015 00:20:57 +0000 (00:20 +0000)
See CORE-10005.

svn path=/trunk/; revision=68886

reactos/ntoskrnl/include/internal/i386/intrin_i.h
reactos/ntoskrnl/include/internal/i386/ke.h
reactos/ntoskrnl/ke/i386/ctxswitch.S
reactos/ntoskrnl/ke/i386/traphdlr.c

index 3a2664b..35cfd8e 100644 (file)
@@ -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()
index cfe674c..a610734 100644 (file)
@@ -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[];
index 3491fcb..3a35a3a 100644 (file)
@@ -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
index 4170a7b..9e5defe 100644 (file)
@@ -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)