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