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;