[PATCH 2d] utrace: avr32 regset support From: Haavard Skinnemoen Rip out most of the ptrace code for AVR32 and replace it with the much nicer utrace stuff. CC: Haavard Skinnemoen Signed-off-by: Roland McGrath --- arch/avr32/kernel/ptrace.c | 111 +++++++++++++++++--------------------------- 1 files changed, 44 insertions(+), 67 deletions(-) --- linux-2.6/arch/avr32/kernel/ptrace.c +++ linux-2.6/arch/avr32/kernel/ptrace.c @@ -14,10 +14,14 @@ #include #include #include +#include +#include #include #include +#ifdef CONFIG_UTRACE + static struct pt_regs *get_user_regs(struct task_struct *tsk) { return (struct pt_regs *)((unsigned long)task_stack_page(tsk) + @@ -57,86 +61,59 @@ void ptrace_disable(struct task_struct * clear_tsk_thread_flag(child, TIF_BREAKPOINT); } -/* - * Read the word at offset "offset" into the task's "struct user". We - * actually access the pt_regs struct stored on the kernel stack. - */ -static int ptrace_read_user(struct task_struct *tsk, unsigned long offset, - unsigned long __user *data) +static int genregs_get(struct task_struct *target, + const struct utrace_regset *regset, + unsigned int pos, unsigned int count, + void *kbuf, void __user *ubuf) { - unsigned long *regs; - unsigned long value; - - if (offset & 3 || offset >= sizeof(struct user)) { - printk("ptrace_read_user: invalid offset 0x%08lx\n", offset); - return -EIO; - } - - regs = (unsigned long *)get_user_regs(tsk); - - value = 0; - if (offset < sizeof(struct pt_regs)) - value = regs[offset / sizeof(regs[0])]; + struct pt_regs *regs = get_user_regs(target); - pr_debug("ptrace_read_user(%s[%u], %#lx, %p) -> %#lx\n", - tsk->comm, tsk->pid, offset, data, value); - - return put_user(value, data); + return utrace_regset_copyout(&pos, &count, &kbuf, &ubuf, + regs, 0, -1); } -/* - * Write the word "value" to offset "offset" into the task's "struct - * user". We actually access the pt_regs struct stored on the kernel - * stack. - */ -static int ptrace_write_user(struct task_struct *tsk, unsigned long offset, - unsigned long value) +static int genregs_set(struct task_struct *target, + const struct utrace_regset *regset, + unsigned int pos, unsigned int count, + const void *kbuf, const void __user *ubuf) { - unsigned long *regs; - - pr_debug("ptrace_write_user(%s[%u], %#lx, %#lx)\n", - tsk->comm, tsk->pid, offset, value); - - if (offset & 3 || offset >= sizeof(struct user)) { - pr_debug(" invalid offset 0x%08lx\n", offset); - return -EIO; - } - - if (offset >= sizeof(struct pt_regs)) - return 0; + struct pt_regs *regs = get_user_regs(target); - regs = (unsigned long *)get_user_regs(tsk); - regs[offset / sizeof(regs[0])] = value; - - return 0; + return utrace_regset_copyin(&pos, &count, &kbuf, &ubuf, + regs, 0, -1); } -static int ptrace_getregs(struct task_struct *tsk, void __user *uregs) -{ - struct pt_regs *regs = get_user_regs(tsk); +static const struct utrace_regset native_regsets[] = { + { + .core_note_type = NT_PRSTATUS, + .n = ELF_NGREG, + .size = sizeof(long), + .align = sizeof(long), + .get = genregs_get, + .set = genregs_set, + }, + /* + * Other register sets that probably would make sense: + * - Coprocessor registers (8 coprocs with 16 registers each) + * - TLS stuff + */ +}; - return copy_to_user(uregs, regs, sizeof(*regs)) ? -EFAULT : 0; -} +static const struct utrace_regset_view utrace_avr32_native_view = { + .name = UTS_MACHINE, + .e_machine = ELF_ARCH, + .regsets = native_regsets, + .n = ARRAY_SIZE(native_regsets), +}; -static int ptrace_setregs(struct task_struct *tsk, const void __user *uregs) +const struct utrace_regset_view *utrace_native_view(struct task_struct *tsk) { - struct pt_regs newregs; - int ret; - - ret = -EFAULT; - if (copy_from_user(&newregs, uregs, sizeof(newregs)) == 0) { - struct pt_regs *regs = get_user_regs(tsk); - - ret = -EINVAL; - if (valid_user_regs(&newregs)) { - *regs = newregs; - ret = 0; - } - } - - return ret; + return &utrace_avr32_native_view; } +#endif /* CONFIG_UTRACE */ + +#if 0 long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret;