aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2015-04-03 18:27:10 -0400
committerRalf Baechle <ralf@linux-mips.org>2015-04-07 19:10:17 -0400
commit443c44032a54f9acf027a8e688380fddc809bc19 (patch)
tree482d477dc139c712bec7f79212408c46e5e79409
parented2d72c1eb3643b7c109bdf387563d9b9a30c279 (diff)
MIPS: Always clear FCSR cause bits after emulation
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 <macro@linux-mips.org> Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/9704/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/mips-r2-to-r6-emul.c6
-rw-r--r--arch/mips/kernel/traps.c15
2 files changed, 20 insertions, 1 deletions
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c
index f1d1b42d1902..6633fa97d431 100644
--- a/arch/mips/kernel/mips-r2-to-r6-emul.c
+++ b/arch/mips/kernel/mips-r2-to-r6-emul.c
@@ -1170,6 +1170,12 @@ fpu_emul:
1170 &fault_addr); 1170 &fault_addr);
1171 1171
1172 /* 1172 /*
1173 * We can't allow the emulated instruction to leave any of
1174 * the cause bits set in $fcr31.
1175 */
1176 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
1177
1178 /*
1173 * this is a tricky issue - lose_fpu() uses LL/SC atomics 1179 * this is a tricky issue - lose_fpu() uses LL/SC atomics
1174 * if FPU is owned and effectively cancels user level LL/SC. 1180 * if FPU is owned and effectively cancels user level LL/SC.
1175 * So, it could be logical to don't restore FPU ownership here. 1181 * So, it could be logical to don't restore FPU ownership here.
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index dbfa47cdc8c1..4a0552dbcf4a 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -761,6 +761,12 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode,
761 sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1, 761 sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
762 &fault_addr); 762 &fault_addr);
763 763
764 /*
765 * We can't allow the emulated instruction to leave any of
766 * the cause bits set in $fcr31.
767 */
768 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
769
764 /* If something went wrong, signal */ 770 /* If something went wrong, signal */
765 process_fpemu_return(sig, fault_addr); 771 process_fpemu_return(sig, fault_addr);
766 772
@@ -807,7 +813,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
807 813
808 /* 814 /*
809 * We can't allow the emulated instruction to leave any of 815 * We can't allow the emulated instruction to leave any of
810 * the cause bit set in $fcr31. 816 * the cause bits set in $fcr31.
811 */ 817 */
812 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; 818 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
813 819
@@ -1384,6 +1390,13 @@ asmlinkage void do_cpu(struct pt_regs *regs)
1384 sig = fpu_emulator_cop1Handler(regs, 1390 sig = fpu_emulator_cop1Handler(regs,
1385 &current->thread.fpu, 1391 &current->thread.fpu,
1386 0, &fault_addr); 1392 0, &fault_addr);
1393
1394 /*
1395 * We can't allow the emulated instruction to leave
1396 * any of the cause bits set in $fcr31.
1397 */
1398 current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
1399
1387 if (!process_fpemu_return(sig, fault_addr) && !err) 1400 if (!process_fpemu_return(sig, fault_addr) && !err)
1388 mt_ase_fp_affinity(); 1401 mt_ase_fp_affinity();
1389 } 1402 }