summaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/traps.c
diff options
context:
space:
mode:
authorPaul Burton2018-11-08 00:14:00 +0100
committerPaul Burton2018-11-09 19:23:14 +0100
commit1975ed43ce67542befed188f6aed6a82cfaffd0b (patch)
tree05a793e45dad2239c041495da54d2db361c52fc3 /arch/mips/kernel/traps.c
parentMIPS: Simplify FP context initialization (diff)
downloadkernel-qcow2-linux-1975ed43ce67542befed188f6aed6a82cfaffd0b.tar.gz
kernel-qcow2-linux-1975ed43ce67542befed188f6aed6a82cfaffd0b.tar.xz
kernel-qcow2-linux-1975ed43ce67542befed188f6aed6a82cfaffd0b.zip
MIPS: Ensure emulated FP sets PF_USED_MATH
Emulated floating point instructions don't ensure that the PF_USED_MATH flag is set for the task. This results in a couple of inconsistencies: - ptrace will return the default initial state of FP registers rather than the values actually stored in struct thread_struct, hiding state that has been updated by emulated floating point instructions. - If a task migrates to a CPU with an FPU after having emulated floating point instructions then its floating point register state will be reset to the default ~0 bit pattern, losing state from the emulated instructions. Fix this by calling init_fp_ctx() from fpu_emulator_cop1Handler() to consistently initialize FP state if it was previously uninitialized, setting the PF_USED_MATH flag in the process. All callers of fpu_emulator_cop1Handler() either call lose_fpu(1) before it in order to save any live FPU registers to struct thread_struct, or in the case of do_cpu() already know that the task does not own an FPU so lose_fpu(1) would be a no-op. Since we know that saving FP context will be unnecessary in the case where FP context was just initialized we move this call into fpu_emulator_cop1Handler() too, providing consistency & avoiding needless duplication. Calls to own_fpu(1) are common after return from fpu_emulator_cop1Handler() too, but this would not be a no-op in the do_cpu() case so these are left as-is. A potential future improvement could be to have fpu_emulator_cop1Handler() restore FPU state automatically only if it saved it, though this may not be optimal if some callers are better off without their current calls to own_fpu(1). One potential example of this could be mipsr2_decoder() which as-is could end up saving & restoring FP context repeatedly & unnecessarily if emulating multiple FP instructions. Signed-off-by: Paul Burton <paul.burton@mips.com> Patchwork: https://patchwork.linux-mips.org/patch/21003/ Cc: linux-mips@linux-mips.org
Diffstat (limited to 'arch/mips/kernel/traps.c')
-rw-r--r--arch/mips/kernel/traps.c5
1 files changed, 0 insertions, 5 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 650b9dd05b8e..db52d30eacec 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -794,9 +794,6 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode,
regs->cp0_epc = old_epc;
regs->regs[31] = old_ra;
- /* Save the FP context to struct thread_struct */
- lose_fpu(1);
-
/* Run the emulator */
sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,
&fault_addr);
@@ -848,8 +845,6 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
* register operands before invoking the emulator, which seems
* a bit extreme for what should be an infrequent event.
*/
- /* Ensure 'resume' not overwrite saved fp context again. */
- lose_fpu(1);
/* Run the emulator */
sig = fpu_emulator_cop1Handler(regs, &current->thread.fpu, 1,