diff options
author | Paul Burton <paul.burton@mips.com> | 2018-11-08 00:14:00 +0100 |
---|---|---|
committer | Paul Burton <paul.burton@mips.com> | 2018-11-09 19:23:14 +0100 |
commit | 1975ed43ce67542befed188f6aed6a82cfaffd0b (patch) | |
tree | 05a793e45dad2239c041495da54d2db361c52fc3 /arch/mips/kernel/mips-r2-to-r6-emul.c | |
parent | MIPS: Simplify FP context initialization (diff) | |
download | linux-1975ed43ce67542befed188f6aed6a82cfaffd0b.tar.xz 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/mips-r2-to-r6-emul.c')
-rw-r--r-- | arch/mips/kernel/mips-r2-to-r6-emul.c | 3 |
1 files changed, 0 insertions, 3 deletions
diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 6092cdf7f8d9..cb22a558431e 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -1175,9 +1175,6 @@ fpu_emul: regs->regs[31] = r31; regs->cp0_epc = epc; - if (!init_fp_ctx(current)) - lose_fpu(1); - err = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0, &fault_addr); |