Loading arch/sparc/kernel/ptrace_64.c +144 −33 Original line number Diff line number Diff line Loading @@ -541,6 +541,60 @@ static int getregs64_get(struct task_struct *target, return ret; } static int setregs64_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { struct pt_regs *regs = task_pt_regs(target); unsigned long y = regs->y; unsigned long tstate; int ret; if (target == current) flushw_user(); ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs->u_regs + 1, 0 * sizeof(u64), 15 * sizeof(u64)); if (ret) return ret; ret =user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 15 * sizeof(u64), 16 * sizeof(u64)); if (ret) return ret; /* TSTATE */ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tstate, 16 * sizeof(u64), 17 * sizeof(u64)); if (ret) return ret; /* Only the condition codes and the "in syscall" * state can be modified in the %tstate register. */ tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); regs->tstate |= tstate; /* TPC, TNPC */ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®s->tpc, 17 * sizeof(u64), 19 * sizeof(u64)); if (ret) return ret; /* Y */ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &y, 19 * sizeof(u64), 20 * sizeof(u64)); if (!ret) regs->y = y; return ret; } static const struct user_regset ptrace64_regsets[] = { /* Format is: * G1 --> G7 Loading @@ -549,7 +603,8 @@ static const struct user_regset ptrace64_regsets[] = { * TSTATE, TPC, TNPC, Y */ [REGSET_GENERAL] = { .n = 20, .size = sizeof(u64), .get = getregs64_get, .n = 20, .size = sizeof(u64), .get = getregs64_get, .set = setregs64_set, }, }; Loading Loading @@ -914,6 +969,40 @@ static int getregs_get(struct task_struct *target, 0, 19 * sizeof(u32)); } static int setregs_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { struct pt_regs *regs = task_pt_regs(target); unsigned long tstate; u32 uregs[19]; int i, ret; if (target == current) flushw_user(); ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, 19 * sizeof(u32)); if (ret) return ret; tstate = regs->tstate; tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); tstate |= psr_to_tstate_icc(uregs[0]); if (uregs[0] & PSR_SYSCALL) tstate |= TSTATE_SYSCALL; regs->tstate = tstate; regs->tpc = uregs[1]; regs->tnpc = uregs[2]; regs->y = uregs[3]; for (i = 1; i < 15; i++) regs->u_regs[i] = uregs[3 + i]; return 0; } static int getfpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, Loading Loading @@ -948,12 +1037,52 @@ static int getfpregs_get(struct task_struct *target, return ret; } static int setfpregs_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { unsigned long *fpregs = task_thread_info(target)->fpregs; unsigned long fprs; int ret; if (target == current) save_and_clear_fpu(); fprs = task_thread_info(target)->fpsaved[0]; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fpregs, 0, 32 * sizeof(u32)); if (!ret) { compat_ulong_t fsr; unsigned long val; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fsr, 32 * sizeof(u32), 33 * sizeof(u32)); if (!ret) { val = task_thread_info(target)->xfsr[0]; val &= 0xffffffff00000000UL; val |= fsr; task_thread_info(target)->xfsr[0] = val; } } fprs |= (FPRS_FEF | FPRS_DL); task_thread_info(target)->fpsaved[0] = fprs; return ret; } static const struct user_regset ptrace32_regsets[] = { [REGSET_GENERAL] = { .n = 19, .size = sizeof(u32), .get = getregs_get, .n = 19, .size = sizeof(u32), .get = getregs_get, .set = setregs_set, }, [REGSET_FP] = { .n = 68, .size = sizeof(u32), .get = getfpregs_get, .n = 68, .size = sizeof(u32), .get = getfpregs_get, .set = setfpregs_set, }, }; Loading Loading @@ -992,7 +1121,6 @@ struct compat_fps { long compat_arch_ptrace(struct task_struct *child, compat_long_t request, compat_ulong_t caddr, compat_ulong_t cdata) { const struct user_regset_view *view = task_user_regset_view(current); compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4]; struct pt_regs32 __user *pregs; struct compat_fps __user *fps; Loading @@ -1017,15 +1145,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, break; case PTRACE_SETREGS: ret = copy_regset_from_user(child, view, REGSET_GENERAL, 32 * sizeof(u32), 4 * sizeof(u32), &pregs->psr); if (!ret) ret = copy_regset_from_user(child, view, REGSET_GENERAL, 1 * sizeof(u32), 15 * sizeof(u32), &pregs->u_regs[0]); ret = copy_regset_from_user(child, &ptrace32_view, REGSET_GENERAL, 0, 19 * sizeof(u32), pregs); break; case PTRACE_GETFPREGS: Loading @@ -1036,15 +1159,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, break; case PTRACE_SETFPREGS: ret = copy_regset_from_user(child, view, REGSET_FP, 0 * sizeof(u32), 32 * sizeof(u32), &fps->regs[0]); if (!ret) ret = copy_regset_from_user(child, view, REGSET_FP, ret = copy_regset_from_user(child, &ptrace32_view, REGSET_FP, 0, 33 * sizeof(u32), 1 * sizeof(u32), &fps->fsr); fps); break; case PTRACE_READTEXT: Loading Loading @@ -1110,17 +1228,10 @@ long arch_ptrace(struct task_struct *child, long request, break; case PTRACE_SETREGS64: ret = copy_regset_from_user(child, view, REGSET_GENERAL, 1 * sizeof(u64), 15 * sizeof(u64), &pregs->u_regs[0]); if (!ret) { /* XXX doesn't handle 'y' register correctly XXX */ ret = copy_regset_from_user(child, view, REGSET_GENERAL, 32 * sizeof(u64), 4 * sizeof(u64), &pregs->tstate); } ret = copy_regset_from_user(child, &ptrace64_view, REGSET_GENERAL, 0, 19 * sizeof(u64), pregs); break; case PTRACE_GETFPREGS64: Loading Loading
arch/sparc/kernel/ptrace_64.c +144 −33 Original line number Diff line number Diff line Loading @@ -541,6 +541,60 @@ static int getregs64_get(struct task_struct *target, return ret; } static int setregs64_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { struct pt_regs *regs = task_pt_regs(target); unsigned long y = regs->y; unsigned long tstate; int ret; if (target == current) flushw_user(); ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs->u_regs + 1, 0 * sizeof(u64), 15 * sizeof(u64)); if (ret) return ret; ret =user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 15 * sizeof(u64), 16 * sizeof(u64)); if (ret) return ret; /* TSTATE */ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tstate, 16 * sizeof(u64), 17 * sizeof(u64)); if (ret) return ret; /* Only the condition codes and the "in syscall" * state can be modified in the %tstate register. */ tstate &= (TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); regs->tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); regs->tstate |= tstate; /* TPC, TNPC */ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ®s->tpc, 17 * sizeof(u64), 19 * sizeof(u64)); if (ret) return ret; /* Y */ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &y, 19 * sizeof(u64), 20 * sizeof(u64)); if (!ret) regs->y = y; return ret; } static const struct user_regset ptrace64_regsets[] = { /* Format is: * G1 --> G7 Loading @@ -549,7 +603,8 @@ static const struct user_regset ptrace64_regsets[] = { * TSTATE, TPC, TNPC, Y */ [REGSET_GENERAL] = { .n = 20, .size = sizeof(u64), .get = getregs64_get, .n = 20, .size = sizeof(u64), .get = getregs64_get, .set = setregs64_set, }, }; Loading Loading @@ -914,6 +969,40 @@ static int getregs_get(struct task_struct *target, 0, 19 * sizeof(u32)); } static int setregs_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { struct pt_regs *regs = task_pt_regs(target); unsigned long tstate; u32 uregs[19]; int i, ret; if (target == current) flushw_user(); ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, uregs, 0, 19 * sizeof(u32)); if (ret) return ret; tstate = regs->tstate; tstate &= ~(TSTATE_ICC | TSTATE_XCC | TSTATE_SYSCALL); tstate |= psr_to_tstate_icc(uregs[0]); if (uregs[0] & PSR_SYSCALL) tstate |= TSTATE_SYSCALL; regs->tstate = tstate; regs->tpc = uregs[1]; regs->tnpc = uregs[2]; regs->y = uregs[3]; for (i = 1; i < 15; i++) regs->u_regs[i] = uregs[3 + i]; return 0; } static int getfpregs_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, Loading Loading @@ -948,12 +1037,52 @@ static int getfpregs_get(struct task_struct *target, return ret; } static int setfpregs_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { unsigned long *fpregs = task_thread_info(target)->fpregs; unsigned long fprs; int ret; if (target == current) save_and_clear_fpu(); fprs = task_thread_info(target)->fpsaved[0]; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, fpregs, 0, 32 * sizeof(u32)); if (!ret) { compat_ulong_t fsr; unsigned long val; ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fsr, 32 * sizeof(u32), 33 * sizeof(u32)); if (!ret) { val = task_thread_info(target)->xfsr[0]; val &= 0xffffffff00000000UL; val |= fsr; task_thread_info(target)->xfsr[0] = val; } } fprs |= (FPRS_FEF | FPRS_DL); task_thread_info(target)->fpsaved[0] = fprs; return ret; } static const struct user_regset ptrace32_regsets[] = { [REGSET_GENERAL] = { .n = 19, .size = sizeof(u32), .get = getregs_get, .n = 19, .size = sizeof(u32), .get = getregs_get, .set = setregs_set, }, [REGSET_FP] = { .n = 68, .size = sizeof(u32), .get = getfpregs_get, .n = 68, .size = sizeof(u32), .get = getfpregs_get, .set = setfpregs_set, }, }; Loading Loading @@ -992,7 +1121,6 @@ struct compat_fps { long compat_arch_ptrace(struct task_struct *child, compat_long_t request, compat_ulong_t caddr, compat_ulong_t cdata) { const struct user_regset_view *view = task_user_regset_view(current); compat_ulong_t caddr2 = task_pt_regs(current)->u_regs[UREG_I4]; struct pt_regs32 __user *pregs; struct compat_fps __user *fps; Loading @@ -1017,15 +1145,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, break; case PTRACE_SETREGS: ret = copy_regset_from_user(child, view, REGSET_GENERAL, 32 * sizeof(u32), 4 * sizeof(u32), &pregs->psr); if (!ret) ret = copy_regset_from_user(child, view, REGSET_GENERAL, 1 * sizeof(u32), 15 * sizeof(u32), &pregs->u_regs[0]); ret = copy_regset_from_user(child, &ptrace32_view, REGSET_GENERAL, 0, 19 * sizeof(u32), pregs); break; case PTRACE_GETFPREGS: Loading @@ -1036,15 +1159,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, break; case PTRACE_SETFPREGS: ret = copy_regset_from_user(child, view, REGSET_FP, 0 * sizeof(u32), 32 * sizeof(u32), &fps->regs[0]); if (!ret) ret = copy_regset_from_user(child, view, REGSET_FP, ret = copy_regset_from_user(child, &ptrace32_view, REGSET_FP, 0, 33 * sizeof(u32), 1 * sizeof(u32), &fps->fsr); fps); break; case PTRACE_READTEXT: Loading Loading @@ -1110,17 +1228,10 @@ long arch_ptrace(struct task_struct *child, long request, break; case PTRACE_SETREGS64: ret = copy_regset_from_user(child, view, REGSET_GENERAL, 1 * sizeof(u64), 15 * sizeof(u64), &pregs->u_regs[0]); if (!ret) { /* XXX doesn't handle 'y' register correctly XXX */ ret = copy_regset_from_user(child, view, REGSET_GENERAL, 32 * sizeof(u64), 4 * sizeof(u64), &pregs->tstate); } ret = copy_regset_from_user(child, &ptrace64_view, REGSET_GENERAL, 0, 19 * sizeof(u64), pregs); break; case PTRACE_GETFPREGS64: Loading