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 <[email protected]>
> Cc: Paul Burton <[email protected]>
> Cc: <[email protected]> # 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 [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html