Subject: ieee754_csr and smp (again)

From: Jun Sun <[email-masked]>
Date: Wed, 17 Apr 2002 17:30:17 -0700

OK, ieee754_csr is a global variable and it screws up fpu emulation code under 
smp.

I have a patch that makes the problem go away.  It basically transform this 
variable into an array of global variables.  Each cpu only uses one of the 
elements.  See the attachment.

That patch works, but I think there might be a better fix.  Looking through 
the code, I am rather confused by the usage of this variable.  Hopefully 
someone with more better knowledge can help me out here.

. should ieee754_csr be a per-thread variable?  If yes, we should just use the 
current->thread->xxx instead of this global variable.

. what is ieee754_csr for anyway?

. Some of the fields in ieee754_csr (such as nod, rm, cx) gets set in 
fpu_emulator_cop1Handler().  But what about others?

. I can't find anywhere we write iee754_csr back to the current->thread 
structure.  Do I miss anything?

Thanks.

Jun

Copy from the patch checked into our EAP.  This
is still a little hackish.  Hopefully we can settle it better later.
A per-cpu page would be nice so that we don't have declare arrays.

BTW, ralf thinks ieee754_csr should belong to per thread fpu structure.
I check it in now anyway so that we have some reliable for running.

Jun

diff -Nru smp/arch/mips/kernel/traps.c.orig smp/arch/mips/kernel/traps.c
--- smp/arch/mips/kernel/traps.c.orig	Wed Feb 13 16:23:12 2002
+++ smp/arch/mips/kernel/traps.c	Thu Apr 11 15:46:11 2002
@@ -678,14 +678,11 @@
 	return;
 
 fp_emul:
-	if (last_task_used_math != current) {
-		if (!current->used_math) {
-			fpu_emulator_init_fpu();
-			current->used_math = 1;
-		}
+	if (!current->used_math) {
+		fpu_emulator_init_fpu();
+		current->used_math = 1;
 	}
 	sig = fpu_emulator_cop1Handler(regs);
-	last_task_used_math = current;
 	if (sig)
 		force_sig(sig, current);
 	return;
diff -Nru smp/arch/mips/math-emu/ieee754.h.orig smp/arch/mips/math-emu/ieee754.h
--- smp/arch/mips/math-emu/ieee754.h.orig	Tue Jan 22 17:11:40 2002
+++ smp/arch/mips/math-emu/ieee754.h	Thu Apr 11 15:46:11 2002
@@ -323,7 +323,7 @@
 
 /* the control status register 
 */
-struct ieee754_csr {
+struct ieee754_csr_struct {
 	unsigned pad:13;
 	unsigned nod:1;		/* set 1 for no denormalised numbers */
 	unsigned cx:5;		/* exceptions this operation */
@@ -331,7 +331,13 @@
 	unsigned sx:5;		/* exceptions total */
 	unsigned rm:2;		/* current rounding mode */
 };
-extern struct ieee754_csr ieee754_csr;
+
+#include <linux/sched.h>
+#include <linux/threads.h>
+#include <linux/smp.h>
+#include <asm/current.h>
+extern struct ieee754_csr_struct ieee754_csr_array[NR_CPUS];
+#define	ieee754_csr ieee754_csr_array[smp_processor_id()]
 
 static __inline unsigned ieee754_getrm(void)
 {
diff -Nru smp/arch/mips/math-emu/ieee754.c.orig smp/arch/mips/math-emu/ieee754.c
--- smp/arch/mips/math-emu/ieee754.c.orig	Tue Jan 15 13:25:24 2002
+++ smp/arch/mips/math-emu/ieee754.c	Thu Apr 11 15:46:11 2002
@@ -52,7 +52,7 @@
 
 /* the control status register 
 */
-struct ieee754_csr ieee754_csr;
+struct ieee754_csr_struct ieee754_csr_array[NR_CPUS];
 
 /* special constants
 */
diff -Nru smp/arch/mips/math-emu/cp1emu.c.orig smp/arch/mips/math-emu/cp1emu.c
--- smp/arch/mips/math-emu/cp1emu.c.orig	Tue Jan 15 13:25:24 2002
+++ smp/arch/mips/math-emu/cp1emu.c	Thu Apr 11 15:46:12 2002
@@ -945,7 +945,7 @@
 static ieee754##p fpemu_##p##_##name (ieee754##p r, ieee754##p s, \
     ieee754##p t) \
 { \
-    struct ieee754_csr ieee754_csr_save; \
+    struct ieee754_csr_struct ieee754_csr_save; \
     s = f1 (s, t); \
     ieee754_csr_save = ieee754_csr; \
     s = f2 (s, r); \
diff -Nru smp/arch/mips/math-emu/dp_sqrt.c.orig smp/arch/mips/math-emu/dp_sqrt.c
--- smp/arch/mips/math-emu/dp_sqrt.c.orig	Tue Jan 15 13:25:24 2002
+++ smp/arch/mips/math-emu/dp_sqrt.c	Thu Apr 11 15:46:12 2002
@@ -37,7 +37,7 @@
 
 ieee754dp ieee754dp_sqrt(ieee754dp x)
 {
-	struct ieee754_csr oldcsr;
+	struct ieee754_csr_struct oldcsr;
 	ieee754dp y, z, t;
 	unsigned scalx, yh;
 	COMPXDP;