diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc/kernel/ptrace.c | 115 |
1 files changed, 47 insertions, 68 deletions
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c index 1c0d5363f72..5b54f11f4e5 100644 --- a/arch/sparc/kernel/ptrace.c +++ b/arch/sparc/kernel/ptrace.c @@ -322,54 +322,39 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task) long arch_ptrace(struct task_struct *child, long request, long addr, long data) { unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; - int i, ret; + const struct user_regset_view *view; + int ret; + + view = task_user_regset_view(child); switch(request) { case PTRACE_GETREGS: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; - struct pt_regs *cregs = child->thread.kregs; - - ret = -EFAULT; - if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs))) - break; - __put_user(cregs->psr, (&pregs->psr)); - __put_user(cregs->pc, (&pregs->pc)); - __put_user(cregs->npc, (&pregs->npc)); - __put_user(cregs->y, (&pregs->y)); - for (i = 1; i < 16; i++) - __put_user(cregs->u_regs[i], &pregs->u_regs[i - 1]); - ret = 0; + ret = copy_regset_to_user(child, view, REGSET_GENERAL, + 32 * sizeof(u32), + 4 * sizeof(u32), + &pregs->psr); + if (!ret) + copy_regset_to_user(child, view, REGSET_GENERAL, + 1 * sizeof(u32), + 15 * sizeof(u32), + &pregs->u_regs[0]); break; } case PTRACE_SETREGS: { struct pt_regs __user *pregs = (struct pt_regs __user *) addr; - struct pt_regs *cregs = child->thread.kregs; - unsigned long psr, pc, npc, y; - - /* Must be careful, tracing process can only set certain - * bits in the psr. - */ - ret = -EFAULT; - if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs))) - break; - __get_user(psr, (&pregs->psr)); - __get_user(pc, (&pregs->pc)); - __get_user(npc, (&pregs->npc)); - __get_user(y, (&pregs->y)); - psr &= PSR_ICC; - cregs->psr &= ~PSR_ICC; - cregs->psr |= psr; - if (!((pc | npc) & 3)) { - cregs->pc = pc; - cregs->npc =npc; - } - cregs->y = y; - for (i = 1; i < 16; i++) - __get_user(cregs->u_regs[i], &pregs->u_regs[i-1]); - ret = 0; + ret = copy_regset_from_user(child, view, REGSET_GENERAL, + 32 * sizeof(u32), + 4 * sizeof(u32), + &pregs->psr); + if (!ret) + copy_regset_from_user(child, view, REGSET_GENERAL, + 1 * sizeof(u32), + 15 * sizeof(u32), + &pregs->u_regs[0]); break; } @@ -387,23 +372,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) }; struct fps __user *fps = (struct fps __user *) addr; - ret = -EFAULT; - if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) - break; - - for (i = 0; i < 32; i++) - __put_user(child->thread.float_regs[i], &fps->regs[i]); - __put_user(child->thread.fsr, (&fps->fsr)); - __put_user(child->thread.fpqdepth, (&fps->fpqd)); - __put_user(0, (&fps->flags)); - __put_user(0, (&fps->extra)); - for (i = 0; i < 16; i++) { - __put_user(child->thread.fpqueue[i].insn_addr, - (&fps->fpq[i].insnaddr)); - __put_user(child->thread.fpqueue[i].insn, - &fps->fpq[i].insn); + ret = copy_regset_to_user(child, view, REGSET_FP, + 0 * sizeof(u32), + 32 * sizeof(u32), + &fps->regs[0]); + if (!ret) + ret = copy_regset_to_user(child, view, REGSET_FP, + 33 * sizeof(u32), + 1 * sizeof(u32), + &fps->fsr); + + if (!ret) { + if (__put_user(0, &fps->fpqd) || + __put_user(0, &fps->flags) || + __put_user(0, &fps->extra) || + clear_user(fps->fpq, sizeof(fps->fpq))) + ret = -EFAULT; } - ret = 0; break; } @@ -421,21 +406,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) }; struct fps __user *fps = (struct fps __user *) addr; - ret = -EFAULT; - if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) - break; - - copy_from_user(&child->thread.float_regs[0], &fps->regs[0], - (32 * sizeof(unsigned long))); - __get_user(child->thread.fsr, (&fps->fsr)); - __get_user(child->thread.fpqdepth, (&fps->fpqd)); - for (i = 0; i < 16; i++) { - __get_user(child->thread.fpqueue[i].insn_addr, - (&fps->fpq[i].insnaddr)); - __get_user(child->thread.fpqueue[i].insn, - &fps->fpq[i].insn); - } - ret = 0; + 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, + 33 * sizeof(u32), + 1 * sizeof(u32), + &fps->fsr); break; } |