Skip to content

Commit

Permalink
MIPS: Always clear FCSR cause bits after emulation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Maciej W. Rozycki authored and Ralf Baechle committed Apr 7, 2015
1 parent ed2d72c commit 443c440
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
6 changes: 6 additions & 0 deletions arch/mips/kernel/mips-r2-to-r6-emul.c
Original file line number Diff line number Diff line change
Expand Up @@ -1169,6 +1169,12 @@ int mipsr2_decoder(struct pt_regs *regs, u32 inst)
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.
Expand Down
15 changes: 14 additions & 1 deletion arch/mips/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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();
}
Expand Down

0 comments on commit 443c440

Please sign in to comment.