|
@@ -463,7 +463,7 @@ static int fpr_get_msa(struct task_struct *target,
|
|
|
/*
|
|
|
* Copy the floating-point context to the supplied NT_PRFPREG buffer.
|
|
|
* Choose the appropriate helper for general registers, and then copy
|
|
|
- * the FCSR register separately.
|
|
|
+ * the FCSR and FIR registers separately.
|
|
|
*/
|
|
|
static int fpr_get(struct task_struct *target,
|
|
|
const struct user_regset *regset,
|
|
@@ -471,6 +471,7 @@ static int fpr_get(struct task_struct *target,
|
|
|
void *kbuf, void __user *ubuf)
|
|
|
{
|
|
|
const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
|
|
|
+ const int fir_pos = fcr31_pos + sizeof(u32);
|
|
|
int err;
|
|
|
|
|
|
if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t))
|
|
@@ -483,6 +484,12 @@ static int fpr_get(struct task_struct *target,
|
|
|
err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
|
|
&target->thread.fpu.fcr31,
|
|
|
fcr31_pos, fcr31_pos + sizeof(u32));
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ err = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
|
|
|
+ &boot_cpu_data.fpu_id,
|
|
|
+ fir_pos, fir_pos + sizeof(u32));
|
|
|
|
|
|
return err;
|
|
|
}
|
|
@@ -531,7 +538,8 @@ static int fpr_set_msa(struct task_struct *target,
|
|
|
/*
|
|
|
* Copy the supplied NT_PRFPREG buffer to the floating-point context.
|
|
|
* Choose the appropriate helper for general registers, and then copy
|
|
|
- * the FCSR register separately.
|
|
|
+ * the FCSR register separately. Ignore the incoming FIR register
|
|
|
+ * contents though, as the register is read-only.
|
|
|
*
|
|
|
* We optimize for the case where `count % sizeof(elf_fpreg_t) == 0',
|
|
|
* which is supposed to have been guaranteed by the kernel before
|
|
@@ -545,6 +553,7 @@ static int fpr_set(struct task_struct *target,
|
|
|
const void *kbuf, const void __user *ubuf)
|
|
|
{
|
|
|
const int fcr31_pos = NUM_FPU_REGS * sizeof(elf_fpreg_t);
|
|
|
+ const int fir_pos = fcr31_pos + sizeof(u32);
|
|
|
u32 fcr31;
|
|
|
int err;
|
|
|
|
|
@@ -572,6 +581,11 @@ static int fpr_set(struct task_struct *target,
|
|
|
ptrace_setfcr31(target, fcr31);
|
|
|
}
|
|
|
|
|
|
+ if (count > 0)
|
|
|
+ err = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
|
|
|
+ fir_pos,
|
|
|
+ fir_pos + sizeof(u32));
|
|
|
+
|
|
|
return err;
|
|
|
}
|
|
|
|