Hi James, On 20 August 2014 15:07, James Hogan <james.hogan@xxxxxxxxxx> wrote: > 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? Ralf emailed me saying he'd dropped the patch because it was causing warnings, and he didn't respond when I asked what the warnings were (I'm unable to reproduce any). Ralf: if you can let me know what warnings you were getting I can send an updated patch. Thanks, Alex > > 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