Hi Ralf, On 24/07/14 13:50, Alex Smith wrote: > Copy FCSR in the FP regset to match the original pre-regset core dumper. > The code paths for where sizeof(union fpureg) == sizeof(elf_fpreg_t) > already do so, but they actually copy 4 bytes more than they should do > as FCSR is only 32 bits. The not equal code paths do not copy it at all. > Therefore change the copy to be done explicitly (with the correct size) > for both paths. > > Additionally, clear the cause bits from FCSR when setting the FP regset > to avoid the possibility of causing an FP exception (and an oops) in the > kernel. > > Signed-off-by: Alex Smith <alex@xxxxxxxxxxxxxxxx> > Cc: Paul Burton <paul.burton@xxxxxxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> # v3.13+ This patch seems to have been missed, although all the others in the series were included in the main v3.17 merge. Was that intentional? Cheers James > --- > Changes in v2: > - Zero fill the last 4 bytes in the FP regset. > --- > arch/mips/kernel/ptrace.c | 73 +++++++++++++++++++++++++++++++---------------- > 1 file changed, 49 insertions(+), 24 deletions(-) > > diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c > index 8bd13ed..e082079 100644 > --- a/arch/mips/kernel/ptrace.c > +++ b/arch/mips/kernel/ptrace.c > @@ -409,23 +409,35 @@ static int fpr_get(struct task_struct *target, > int err; > u64 fpr_val; > > - /* XXX fcr31 */ > - > - if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) > - return user_regset_copyout(&pos, &count, &kbuf, &ubuf, > - &target->thread.fpu, > - 0, sizeof(elf_fpregset_t)); > - > - for (i = 0; i < NUM_FPU_REGS; i++) { > - fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0); > + if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) { > err = user_regset_copyout(&pos, &count, &kbuf, &ubuf, > - &fpr_val, i * sizeof(elf_fpreg_t), > - (i + 1) * sizeof(elf_fpreg_t)); > + &target->thread.fpu.fpr, > + 0, NUM_FPU_REGS * sizeof(elf_fpreg_t)); > if (err) > return err; > + } else { > + for (i = 0; i < NUM_FPU_REGS; i++) { > + fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0); > + err = user_regset_copyout(&pos, &count, &kbuf, &ubuf, > + &fpr_val, > + i * sizeof(elf_fpreg_t), > + (i + 1) * sizeof(elf_fpreg_t)); > + if (err) > + return err; > + } > } > > - return 0; > + err = user_regset_copyout(&pos, &count, &kbuf, &ubuf, > + &target->thread.fpu.fcr31, > + NUM_FPU_REGS * sizeof(elf_fpreg_t), > + (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32)); > + if (err) > + return err; > + > + /* Zero fill the remaining 4 bytes. */ > + return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf, > + (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32), > + sizeof(elf_fpregset_t)); > } > > static int fpr_set(struct task_struct *target, > @@ -436,24 +448,37 @@ static int fpr_set(struct task_struct *target, > unsigned i; > int err; > u64 fpr_val; > + u32 fcr31; > > - /* XXX fcr31 */ > - > - if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) > - return user_regset_copyin(&pos, &count, &kbuf, &ubuf, > - &target->thread.fpu, > - 0, sizeof(elf_fpregset_t)); > - > - for (i = 0; i < NUM_FPU_REGS; i++) { > + if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) { > err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, > - &fpr_val, i * sizeof(elf_fpreg_t), > - (i + 1) * sizeof(elf_fpreg_t)); > + &target->thread.fpu.fpr, > + 0, NUM_FPU_REGS * sizeof(elf_fpreg_t)); > if (err) > return err; > - set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val); > + } else { > + for (i = 0; i < NUM_FPU_REGS; i++) { > + err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, > + &fpr_val, > + i * sizeof(elf_fpreg_t), > + (i + 1) * sizeof(elf_fpreg_t)); > + if (err) > + return err; > + set_fpr64(&target->thread.fpu.fpr[i], 0, fpr_val); > + } > } > > - return 0; > + err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fcr31, > + NUM_FPU_REGS * sizeof(elf_fpreg_t), > + (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32)); > + if (err) > + return err; > + > + target->thread.fpu.fcr31 = fcr31 & ~FPU_CSR_ALL_X; > + > + return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, > + (NUM_FPU_REGS * sizeof(elf_fpreg_t)) + sizeof(u32), > + sizeof(elf_fpregset_t)); > } > > enum mips_regset { > -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html