|
@@ -57,8 +57,7 @@ static void init_fp_ctx(struct task_struct *target)
|
|
|
/* Begin with data registers set to all 1s... */
|
|
|
memset(&target->thread.fpu.fpr, ~0, sizeof(target->thread.fpu.fpr));
|
|
|
|
|
|
- /* ...and FCSR zeroed */
|
|
|
- target->thread.fpu.fcr31 = 0;
|
|
|
+ /* FCSR has been preset by `mips_set_personality_nan'. */
|
|
|
|
|
|
/*
|
|
|
* Record that the target has "used" math, such that the context
|
|
@@ -79,6 +78,22 @@ void ptrace_disable(struct task_struct *child)
|
|
|
clear_tsk_thread_flag(child, TIF_LOAD_WATCH);
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Poke at FCSR according to its mask. Don't set the cause bits as
|
|
|
+ * this is currently not handled correctly in FP context restoration
|
|
|
+ * and will cause an oops if a corresponding enable bit is set.
|
|
|
+ */
|
|
|
+static void ptrace_setfcr31(struct task_struct *child, u32 value)
|
|
|
+{
|
|
|
+ u32 fcr31;
|
|
|
+ u32 mask;
|
|
|
+
|
|
|
+ value &= ~FPU_CSR_ALL_X;
|
|
|
+ fcr31 = child->thread.fpu.fcr31;
|
|
|
+ mask = boot_cpu_data.fpu_msk31;
|
|
|
+ child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Read a general register set. We always use the 64-bit format, even
|
|
|
* for 32-bit kernels and for 32-bit processes on a 64-bit kernel.
|
|
@@ -159,9 +174,7 @@ 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))
|
|
@@ -176,10 +189,7 @@ int ptrace_setfpregs(struct task_struct *child, __u32 __user *data)
|
|
|
}
|
|
|
|
|
|
__get_user(value, data + 64);
|
|
|
- value &= ~FPU_CSR_ALL_X;
|
|
|
- fcr31 = child->thread.fpu.fcr31;
|
|
|
- mask = boot_cpu_data.fpu_msk31;
|
|
|
- child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask);
|
|
|
+ ptrace_setfcr31(child, value);
|
|
|
|
|
|
/* FIR may not be written. */
|
|
|
|
|
@@ -807,7 +817,7 @@ long arch_ptrace(struct task_struct *child, long request,
|
|
|
break;
|
|
|
#endif
|
|
|
case FPC_CSR:
|
|
|
- child->thread.fpu.fcr31 = data & ~FPU_CSR_ALL_X;
|
|
|
+ ptrace_setfcr31(child, data);
|
|
|
break;
|
|
|
case DSP_BASE ... DSP_BASE + 5: {
|
|
|
dspreg_t *dregs;
|