Commit 443c4403 authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle

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: default avatarMaciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9704/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent ed2d72c1
...@@ -1169,6 +1169,12 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst) ...@@ -1169,6 +1169,12 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst)
err = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 0, err = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 0,
&fault_addr); &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 * this is a tricky issue - lose_fpu() uses LL/SC atomics
* if FPU is owned and effectively cancels user level LL/SC. * if FPU is owned and effectively cancels user level LL/SC.
......
...@@ -761,6 +761,12 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode, ...@@ -761,6 +761,12 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode,
sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1, sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
&fault_addr); &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 */ /* If something went wrong, signal */
process_fpemu_return(sig, fault_addr); process_fpemu_return(sig, fault_addr);
...@@ -807,7 +813,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31) ...@@ -807,7 +813,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
/* /*
* We can't allow the emulated instruction to leave any of * 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; current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X;
...@@ -1384,6 +1390,13 @@ asmlinkage void do_cpu(struct pt_regs *regs) ...@@ -1384,6 +1390,13 @@ asmlinkage void do_cpu(struct pt_regs *regs)
sig = fpu_emulator_cop1Handler(regs, sig = fpu_emulator_cop1Handler(regs,
&current->thread.fpu, &current->thread.fpu,
0, &fault_addr); 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) if (!process_fpemu_return(sig, fault_addr) && !err)
mt_ase_fp_affinity(); mt_ase_fp_affinity();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment