diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2015-04-03 22:27:48 (GMT) |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-04-07 23:10:37 (GMT) |
commit | 9b26616c8d9dae53fbac7f7cb2c6dd1308102976 (patch) | |
tree | d4249bd953d4fa955cecd1283cc0f518df83f8a2 /arch/mips/kernel/ptrace.c | |
parent | 232b6ec5df874236166fb0167cd473601a631715 (diff) | |
download | linux-9b26616c8d9dae53fbac7f7cb2c6dd1308102976.tar.xz |
MIPS: Respect the ISA level in FCSR handling
Define the central place the default FCSR value is set from, initialised
in `cpu_probe'. Determine the FCSR mask applied to values written to
the register with CTC1 in the full emulation mode and via ptrace(2),
according to the ISA level of processor hardware or the writability of
bits 31:18 if actual FPU hardware is used.
Software may rely on FCSR bits whose functions our emulator does not
implement, so it should not allow them to be set or software may get
confused. For ptrace(2) it's just sanity.
[ralf@linux-mips.org: Fixed double inclusion of <asm/current.h>.]
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/9711/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/ptrace.c')
-rw-r--r-- | arch/mips/kernel/ptrace.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 5104528..6d1e3f8 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -32,6 +32,7 @@ #include <asm/byteorder.h> #include <asm/cpu.h> +#include <asm/cpu-info.h> #include <asm/dsp.h> #include <asm/fpu.h> #include <asm/mipsregs.h> @@ -137,6 +138,9 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) { union fpureg *fregs; u64 fpr_val; + u32 fcr31; + u32 value; + u32 mask; int i; if (!access_ok(VERIFY_READ, data, 33 * 8)) @@ -149,8 +153,10 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data) set_fpr64(&fregs[i], 0, fpr_val); } - __get_user(child->thread.fpu.fcr31, data + 64); - child->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; + __get_user(value, data + 64); + fcr31 = child->thread.fpu.fcr31; + mask = current_cpu_data.fpu_msk31; + child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); /* FIR may not be written. */ |