Hello again!
Hartmut Birr wrote:
I've revert some parts of fpu.c to your first patch. It works now on my smp machine.
I have attached a patch to this email, maybe you can try if it works with this patch. It is a patch against current reactos CVS.
I didn't see diff which you attached to your mail the first time, but it looks like it's an old version of the fpu.c which I have modified... maybe it doesn't bugcheck but I think it won't work (unless you have also reverted tskswitch.S...)
I have also attached a fputest program which tests wether the FPU state is preserved or not.
- blight
Index: ntoskrnl/ke/i386/fpu.c =================================================================== RCS file: /CVS/ReactOS/reactos/ntoskrnl/ke/i386/fpu.c,v retrieving revision 1.16 diff -u -r1.16 fpu.c --- ntoskrnl/ke/i386/fpu.c 21 Nov 2004 13:33:34 -0000 1.16 +++ ntoskrnl/ke/i386/fpu.c 23 Nov 2004 20:36:58 -0000 @@ -28,6 +28,7 @@
/* INCLUDES *****************************************************************/
+#include <roscfg.h> #include <ntoskrnl.h> #define NDEBUG #include <internal/debug.h> @@ -67,7 +68,8 @@ /* GLOBALS *******************************************************************/
ULONG HardwareMathSupport = 0; -static ULONG MxcsrFeatureMask = 0, FxsrSupport = 0, XmmSupport = 0; +static ULONG MxcsrFeatureMask = 0, XmmSupport = 0; +ULONG FxsrSupport = 0; /* used by Ki386ContextSwitch for MP */
/* FUNCTIONS *****************************************************************/
@@ -406,10 +408,14 @@ { if (ExceptionNr == 7) /* device not present */ { + BOOL FpuInitialized = FALSE; unsigned int cr0 = Ke386GetCr0(); - PKTHREAD CurrentThread, NpxThread; + PKTHREAD CurrentThread; PFX_SAVE_AREA FxSaveArea; KIRQL oldIrql; +#ifndef MP + PKTHREAD NpxThread; +#endif
(void) cr0; ASSERT((cr0 & X86_CR0_TS) == X86_CR0_TS); @@ -422,15 +428,17 @@ asm volatile("clts");
CurrentThread = KeGetCurrentThread(); +#ifndef MP NpxThread = KeGetCurrentKPCR()->PrcbData.NpxThread; +#endif
ASSERT(CurrentThread != NULL); - DPRINT("Device not present exception happened! (Cr0 = 0x%x, NpxState = 0x%x)\n", Ke386GetCr0(), CurrentThread->NpxState); + DPRINT("Device not present exception happened! (Cr0 = 0x%x, NpxState = 0x%x)\n", cr0, CurrentThread->NpxState);
+#ifndef MP /* check if the current thread already owns the FPU */ if (NpxThread != CurrentThread) /* FIXME: maybe this could be an assertation */ { - BOOL FpuInitialized = FALSE; /* save the FPU state into the owner's save area */ if (NpxThread != NULL) { @@ -448,6 +456,7 @@ } NpxThread->NpxState = NPX_STATE_VALID; } +#endif /* !MP */
/* restore the state of the current thread */ ASSERT((CurrentThread->NpxState & NPX_STATE_DIRTY) == 0); @@ -483,7 +492,9 @@ } } KeGetCurrentKPCR()->PrcbData.NpxThread = CurrentThread; +#ifndef MP } +#endif
CurrentThread->NpxState |= NPX_STATE_DIRTY; KeLowerIrql(oldIrql); @@ -508,8 +519,8 @@ CurrentThread = KeGetCurrentThread(); if (NpxThread == NULL) { - DPRINT1("!!! Math/Xmm fault ignored! (NpxThread == NULL)\n"); KeLowerIrql(oldIrql); + DPRINT1("!!! Math/Xmm fault ignored! (NpxThread == NULL)\n"); return STATUS_SUCCESS; }
@@ -540,7 +551,6 @@ PFNSAVE_FORMAT FnSave = (PFNSAVE_FORMAT)&Context->FloatSave; asm volatile("fnsave %0" : : "m"(*FnSave)); KeLowerIrql(oldIrql); - memset(Context->FloatSave.RegisterArea, 0, sizeof(Context->FloatSave.RegisterArea)); KiFnsaveToFxsaveFormat((PFXSAVE_FORMAT)Context->ExtendedRegisters, FnSave); }
Index: ntoskrnl/ke/i386/tskswitch.S =================================================================== RCS file: /CVS/ReactOS/reactos/ntoskrnl/ke/i386/tskswitch.S,v retrieving revision 1.20 diff -u -r1.20 tskswitch.S --- ntoskrnl/ke/i386/tskswitch.S 20 Nov 2004 23:46:36 -0000 1.20 +++ ntoskrnl/ke/i386/tskswitch.S 23 Nov 2004 20:13:31 -0000 @@ -26,6 +26,7 @@
/* INCLUDES ******************************************************************/
+#include <roscfg.h> #include <internal/i386/segment.h> #include <internal/i386/ke.h> #include <internal/i386/fpu.h> @@ -105,8 +106,30 @@ 0: lldtw %ax
+ /* + * Get the pointer to the old thread. + */ movl 12(%ebp), %ebx
+#ifdef MP + /* + * Save FPU state if the thread has used it. + */ + movl $0, %fs:KPCR_NPX_THREAD + testl $NPX_STATE_DIRTY, KTHREAD_NPX_STATE(%ebx) + jz 3f + movl KTHREAD_INITIAL_STACK(%ebx), %eax + cmpl $0, _FxsrSupport + je 1f + fxsave -SIZEOF_FX_SAVE_AREA(%eax) + jmp 2f +1: + fnsave -SIZEOF_FX_SAVE_AREA(%eax) +2: + movl $NPX_STATE_VALID, KTHREAD_NPX_STATE(%ebx) +3: +#endif /* MP */ + /* * FIXME: Save debugging state. */ @@ -152,14 +175,16 @@
/* * Set TS in cr0 to catch FPU code and load the FPU state when needed - * We do this only if NewThread != KPCR->NpxThread + * For uni-processor we do this only if NewThread != KPCR->NpxThread */ +#ifndef MP cmpl %ebx, %fs:KPCR_NPX_THREAD - je 1f + je 4f +#endif /* !MP */ movl %cr0, %eax orl $X86_CR0_TS, %eax movl %eax, %cr0 -1: +4:
/* * FIXME: Restore debugging state @@ -174,9 +199,9 @@ call _KeReleaseSpinLockFromDpcLevel@4
cmpl $0, _PiNrThreadsAwaitingReaping - je 4f + je 5f call _PiWakeupReaperThread@0 -4: +5:
/* * Restore the saved register and exit