===================================================================
@@ -1170,6 +1170,12 @@ int mipsr2_decoder(struct pt_regs *regs,
&fault_addr);
/*
+ * We can't allow the emulated instruction to leave any of
+ * the cause bits set in $fcr31.
+ */
+ current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+
+ /*
* this is a tricky issue - lose_fpu() uses LL/SC atomics
* if FPU is owned and effectively cancels user level LL/SC.
* So, it could be logical to don't restore FPU ownership here.
===================================================================
@@ -761,6 +761,12 @@ static int simulate_fp(struct pt_regs *r
sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,
&fault_addr);
+ /*
+ * We can't allow the emulated instruction to leave any of
+ * the cause bits set in $fcr31.
+ */
+ current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+
/* If something went wrong, signal */
process_fpemu_return(sig, fault_addr);
@@ -807,7 +813,7 @@ asmlinkage void do_fpe(struct pt_regs *r
/*
* We can't allow the emulated instruction to leave any of
- * the cause bit set in $fcr31.
+ * the cause bits set in $fcr31.
*/
current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
@@ -1384,6 +1390,13 @@ asmlinkage void do_cpu(struct pt_regs *r
sig = fpu_emulator_cop1Handler(regs,
¤t->thread.fpu,
0, &fault_addr);
+
+ /*
+ * We can't allow the emulated instruction to leave
+ * any of the cause bits set in $fcr31.
+ */
+ current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
+
if (!process_fpemu_return(sig, fault_addr) && !err)
mt_ase_fp_affinity();
}
Clear any FCSR cause bits recorded in the saved FPU context after emulation in all cases rather than in `do_fpe' only, so that any unmasked IEEE 754 exception left from emulation does not cause a fatal kernel-mode FPE hardware exception with the CTC1 instruction used by the kernel to subsequently restore FCSR hardware from the saved FPU context. Signed-off-by: Maciej W. Rozycki <> --- linux-mips-fpe-emu-fcsr-cause.diff