1
0
Fork 0

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>
hifive-unleashed-5.1
Maciej W. Rozycki 2015-04-03 23:27:10 +01:00 committed by Ralf Baechle
parent ed2d72c1eb
commit 443c44032a
2 changed files with 20 additions and 1 deletions

View File

@ -1169,6 +1169,12 @@ fpu_emul:
err = fpu_emulator_cop1Handler(regs, &current->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;
/*
* this is a tricky issue - lose_fpu() uses LL/SC atomics
* if FPU is owned and effectively cancels user level LL/SC.

View File

@ -761,6 +761,12 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode,
sig = fpu_emulator_cop1Handler(regs, &current->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 *regs, unsigned long fcr31)
/*
* 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 *regs)
sig = fpu_emulator_cop1Handler(regs,
&current->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();
}