15933f6d2SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0 248b22cf9SPaul Mundt /* 3934135c1SPaul Mundt * SuperH process tracing 448b22cf9SPaul Mundt * 5934135c1SPaul Mundt * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka 634d0b5afSPaul Mundt * Copyright (C) 2002 - 2009 Paul Mundt 748b22cf9SPaul Mundt * 8934135c1SPaul Mundt * Audit support by Yuichi Nakamura <ynakam@hitachisoft.jp> 948b22cf9SPaul Mundt */ 1048b22cf9SPaul Mundt #include <linux/kernel.h> 1148b22cf9SPaul Mundt #include <linux/sched.h> 1268db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 1348b22cf9SPaul Mundt #include <linux/mm.h> 1448b22cf9SPaul Mundt #include <linux/smp.h> 1548b22cf9SPaul Mundt #include <linux/errno.h> 1648b22cf9SPaul Mundt #include <linux/ptrace.h> 1748b22cf9SPaul Mundt #include <linux/user.h> 1848b22cf9SPaul Mundt #include <linux/security.h> 1948b22cf9SPaul Mundt #include <linux/signal.h> 2048b22cf9SPaul Mundt #include <linux/io.h> 211322b9deSYuichi Nakamura #include <linux/audit.h> 22c4637d47SPaul Mundt #include <linux/seccomp.h> 23ab99c733SPaul Mundt #include <linux/tracehook.h> 24934135c1SPaul Mundt #include <linux/elf.h> 25934135c1SPaul Mundt #include <linux/regset.h> 2634d0b5afSPaul Mundt #include <linux/hw_breakpoint.h> 277c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 2848b22cf9SPaul Mundt #include <asm/processor.h> 2948b22cf9SPaul Mundt #include <asm/mmu_context.h> 30fa43972fSPaul Mundt #include <asm/syscalls.h> 31e7ab3cd2SPaul Mundt #include <asm/fpu.h> 3248b22cf9SPaul Mundt 33a74f7e04SPaul Mundt #define CREATE_TRACE_POINTS 34a74f7e04SPaul Mundt #include <trace/events/syscalls.h> 35c652d780SMatt Fleming 3648b22cf9SPaul Mundt /* 3748b22cf9SPaul Mundt * This routine will get a word off of the process kernel stack. 3848b22cf9SPaul Mundt */ 3948b22cf9SPaul Mundt static inline int get_stack_long(struct task_struct *task, int offset) 4048b22cf9SPaul Mundt { 4148b22cf9SPaul Mundt unsigned char *stack; 4248b22cf9SPaul Mundt 4348b22cf9SPaul Mundt stack = (unsigned char *)task_pt_regs(task); 4448b22cf9SPaul Mundt stack += offset; 4548b22cf9SPaul Mundt return (*((int *)stack)); 4648b22cf9SPaul Mundt } 4748b22cf9SPaul Mundt 4848b22cf9SPaul Mundt /* 4948b22cf9SPaul Mundt * This routine will put a word on the process kernel stack. 5048b22cf9SPaul Mundt */ 5148b22cf9SPaul Mundt static inline int put_stack_long(struct task_struct *task, int offset, 5248b22cf9SPaul Mundt unsigned long data) 5348b22cf9SPaul Mundt { 5448b22cf9SPaul Mundt unsigned char *stack; 5548b22cf9SPaul Mundt 5648b22cf9SPaul Mundt stack = (unsigned char *)task_pt_regs(task); 5748b22cf9SPaul Mundt stack += offset; 5848b22cf9SPaul Mundt *(unsigned long *) stack = data; 5948b22cf9SPaul Mundt return 0; 6048b22cf9SPaul Mundt } 6148b22cf9SPaul Mundt 62a8b0ca17SPeter Zijlstra void ptrace_triggered(struct perf_event *bp, 6334d0b5afSPaul Mundt struct perf_sample_data *data, struct pt_regs *regs) 6434d0b5afSPaul Mundt { 6534d0b5afSPaul Mundt struct perf_event_attr attr; 6634d0b5afSPaul Mundt 6734d0b5afSPaul Mundt /* 6834d0b5afSPaul Mundt * Disable the breakpoint request here since ptrace has defined a 6934d0b5afSPaul Mundt * one-shot behaviour for breakpoint exceptions. 7034d0b5afSPaul Mundt */ 7134d0b5afSPaul Mundt attr = bp->attr; 7234d0b5afSPaul Mundt attr.disabled = true; 7334d0b5afSPaul Mundt modify_user_hw_breakpoint(bp, &attr); 7434d0b5afSPaul Mundt } 7534d0b5afSPaul Mundt 7634d0b5afSPaul Mundt static int set_single_step(struct task_struct *tsk, unsigned long addr) 7734d0b5afSPaul Mundt { 7834d0b5afSPaul Mundt struct thread_struct *thread = &tsk->thread; 7934d0b5afSPaul Mundt struct perf_event *bp; 8034d0b5afSPaul Mundt struct perf_event_attr attr; 8134d0b5afSPaul Mundt 8234d0b5afSPaul Mundt bp = thread->ptrace_bps[0]; 8334d0b5afSPaul Mundt if (!bp) { 8473266fc1SFrederic Weisbecker ptrace_breakpoint_init(&attr); 8534d0b5afSPaul Mundt 8634d0b5afSPaul Mundt attr.bp_addr = addr; 8734d0b5afSPaul Mundt attr.bp_len = HW_BREAKPOINT_LEN_2; 8834d0b5afSPaul Mundt attr.bp_type = HW_BREAKPOINT_R; 8934d0b5afSPaul Mundt 904dc0da86SAvi Kivity bp = register_user_hw_breakpoint(&attr, ptrace_triggered, 914dc0da86SAvi Kivity NULL, tsk); 9234d0b5afSPaul Mundt if (IS_ERR(bp)) 9334d0b5afSPaul Mundt return PTR_ERR(bp); 9434d0b5afSPaul Mundt 9534d0b5afSPaul Mundt thread->ptrace_bps[0] = bp; 9634d0b5afSPaul Mundt } else { 9734d0b5afSPaul Mundt int err; 9834d0b5afSPaul Mundt 9934d0b5afSPaul Mundt attr = bp->attr; 10034d0b5afSPaul Mundt attr.bp_addr = addr; 101fb7f045aSDavid Engraf /* reenable breakpoint */ 102fb7f045aSDavid Engraf attr.disabled = false; 10334d0b5afSPaul Mundt err = modify_user_hw_breakpoint(bp, &attr); 10434d0b5afSPaul Mundt if (unlikely(err)) 10534d0b5afSPaul Mundt return err; 10634d0b5afSPaul Mundt } 10734d0b5afSPaul Mundt 10834d0b5afSPaul Mundt return 0; 10934d0b5afSPaul Mundt } 11034d0b5afSPaul Mundt 111c459dbf2SPaul Mundt void user_enable_single_step(struct task_struct *child) 112c459dbf2SPaul Mundt { 11334d0b5afSPaul Mundt unsigned long pc = get_stack_long(child, offsetof(struct pt_regs, pc)); 114c459dbf2SPaul Mundt 115c459dbf2SPaul Mundt set_tsk_thread_flag(child, TIF_SINGLESTEP); 11634d0b5afSPaul Mundt 11734d0b5afSPaul Mundt set_single_step(child, pc); 118c459dbf2SPaul Mundt } 119c459dbf2SPaul Mundt 120c459dbf2SPaul Mundt void user_disable_single_step(struct task_struct *child) 12148b22cf9SPaul Mundt { 12248b22cf9SPaul Mundt clear_tsk_thread_flag(child, TIF_SINGLESTEP); 12348b22cf9SPaul Mundt } 12448b22cf9SPaul Mundt 12548b22cf9SPaul Mundt /* 12648b22cf9SPaul Mundt * Called by kernel/ptrace.c when detaching.. 12748b22cf9SPaul Mundt * 12848b22cf9SPaul Mundt * Make sure single step bits etc are not set. 12948b22cf9SPaul Mundt */ 13048b22cf9SPaul Mundt void ptrace_disable(struct task_struct *child) 13148b22cf9SPaul Mundt { 132c459dbf2SPaul Mundt user_disable_single_step(child); 13348b22cf9SPaul Mundt } 13448b22cf9SPaul Mundt 135934135c1SPaul Mundt static int genregs_get(struct task_struct *target, 136934135c1SPaul Mundt const struct user_regset *regset, 1373399d90cSAl Viro struct membuf to) 138934135c1SPaul Mundt { 139934135c1SPaul Mundt const struct pt_regs *regs = task_pt_regs(target); 140934135c1SPaul Mundt 1413399d90cSAl Viro return membuf_write(&to, regs, sizeof(struct pt_regs)); 142934135c1SPaul Mundt } 143934135c1SPaul Mundt 144934135c1SPaul Mundt static int genregs_set(struct task_struct *target, 145934135c1SPaul Mundt const struct user_regset *regset, 146934135c1SPaul Mundt unsigned int pos, unsigned int count, 147934135c1SPaul Mundt const void *kbuf, const void __user *ubuf) 148934135c1SPaul Mundt { 149934135c1SPaul Mundt struct pt_regs *regs = task_pt_regs(target); 150934135c1SPaul Mundt int ret; 151934135c1SPaul Mundt 152934135c1SPaul Mundt ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 153934135c1SPaul Mundt regs->regs, 154934135c1SPaul Mundt 0, 16 * sizeof(unsigned long)); 155934135c1SPaul Mundt if (!ret && count > 0) 156934135c1SPaul Mundt ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, 157934135c1SPaul Mundt ®s->pc, 158934135c1SPaul Mundt offsetof(struct pt_regs, pc), 159934135c1SPaul Mundt sizeof(struct pt_regs)); 160934135c1SPaul Mundt if (!ret) 161934135c1SPaul Mundt ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 162934135c1SPaul Mundt sizeof(struct pt_regs), -1); 163934135c1SPaul Mundt 164934135c1SPaul Mundt return ret; 165934135c1SPaul Mundt } 166934135c1SPaul Mundt 167e7ab3cd2SPaul Mundt #ifdef CONFIG_SH_FPU 168*bb1a773dSAl Viro static int fpregs_get(struct task_struct *target, 169e7ab3cd2SPaul Mundt const struct user_regset *regset, 1703399d90cSAl Viro struct membuf to) 171e7ab3cd2SPaul Mundt { 172e7ab3cd2SPaul Mundt int ret; 173e7ab3cd2SPaul Mundt 174e7ab3cd2SPaul Mundt ret = init_fpu(target); 175e7ab3cd2SPaul Mundt if (ret) 176e7ab3cd2SPaul Mundt return ret; 177e7ab3cd2SPaul Mundt 1783399d90cSAl Viro return membuf_write(&to, target->thread.xstate, 1793399d90cSAl Viro sizeof(struct user_fpu_struct)); 180e7ab3cd2SPaul Mundt } 181e7ab3cd2SPaul Mundt 182e7ab3cd2SPaul Mundt static int fpregs_set(struct task_struct *target, 183e7ab3cd2SPaul Mundt const struct user_regset *regset, 184e7ab3cd2SPaul Mundt unsigned int pos, unsigned int count, 185e7ab3cd2SPaul Mundt const void *kbuf, const void __user *ubuf) 186e7ab3cd2SPaul Mundt { 187e7ab3cd2SPaul Mundt int ret; 188e7ab3cd2SPaul Mundt 189e7ab3cd2SPaul Mundt ret = init_fpu(target); 190e7ab3cd2SPaul Mundt if (ret) 191e7ab3cd2SPaul Mundt return ret; 192e7ab3cd2SPaul Mundt 193e7ab3cd2SPaul Mundt set_stopped_child_used_math(target); 194e7ab3cd2SPaul Mundt 195e7ab3cd2SPaul Mundt if ((boot_cpu_data.flags & CPU_HAS_FPU)) 196e7ab3cd2SPaul Mundt return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 1970ea820cfSPaul Mundt &target->thread.xstate->hardfpu, 0, -1); 198e7ab3cd2SPaul Mundt 199e7ab3cd2SPaul Mundt return user_regset_copyin(&pos, &count, &kbuf, &ubuf, 2000ea820cfSPaul Mundt &target->thread.xstate->softfpu, 0, -1); 201e7ab3cd2SPaul Mundt } 202e7ab3cd2SPaul Mundt 203e7ab3cd2SPaul Mundt static int fpregs_active(struct task_struct *target, 204e7ab3cd2SPaul Mundt const struct user_regset *regset) 205e7ab3cd2SPaul Mundt { 206e7ab3cd2SPaul Mundt return tsk_used_math(target) ? regset->n : 0; 207e7ab3cd2SPaul Mundt } 208e7ab3cd2SPaul Mundt #endif 209e7ab3cd2SPaul Mundt 2105dadb343SPaul Mundt #ifdef CONFIG_SH_DSP 2115dadb343SPaul Mundt static int dspregs_get(struct task_struct *target, 2125dadb343SPaul Mundt const struct user_regset *regset, 2133399d90cSAl Viro struct membuf to) 2145dadb343SPaul Mundt { 21501ab1039SMichael Trimarchi const struct pt_dspregs *regs = 21601ab1039SMichael Trimarchi (struct pt_dspregs *)&target->thread.dsp_status.dsp_regs; 2175dadb343SPaul Mundt 2183399d90cSAl Viro return membuf_write(&to, regs, sizeof(struct pt_dspregs)); 2195dadb343SPaul Mundt } 2205dadb343SPaul Mundt 2215dadb343SPaul Mundt static int dspregs_set(struct task_struct *target, 2225dadb343SPaul Mundt const struct user_regset *regset, 2235dadb343SPaul Mundt unsigned int pos, unsigned int count, 2245dadb343SPaul Mundt const void *kbuf, const void __user *ubuf) 2255dadb343SPaul Mundt { 22601ab1039SMichael Trimarchi struct pt_dspregs *regs = 22701ab1039SMichael Trimarchi (struct pt_dspregs *)&target->thread.dsp_status.dsp_regs; 2285dadb343SPaul Mundt int ret; 2295dadb343SPaul Mundt 2305dadb343SPaul Mundt ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs, 2315dadb343SPaul Mundt 0, sizeof(struct pt_dspregs)); 2325dadb343SPaul Mundt if (!ret) 2335dadb343SPaul Mundt ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 2345dadb343SPaul Mundt sizeof(struct pt_dspregs), -1); 2355dadb343SPaul Mundt 2365dadb343SPaul Mundt return ret; 2375dadb343SPaul Mundt } 23872461997SPaul Mundt 23972461997SPaul Mundt static int dspregs_active(struct task_struct *target, 24072461997SPaul Mundt const struct user_regset *regset) 24172461997SPaul Mundt { 24272461997SPaul Mundt struct pt_regs *regs = task_pt_regs(target); 24372461997SPaul Mundt 24472461997SPaul Mundt return regs->sr & SR_DSP ? regset->n : 0; 24572461997SPaul Mundt } 2465dadb343SPaul Mundt #endif 2475dadb343SPaul Mundt 248eaaaeef3SPaul Mundt const struct pt_regs_offset regoffset_table[] = { 249eaaaeef3SPaul Mundt REGS_OFFSET_NAME(0), 250eaaaeef3SPaul Mundt REGS_OFFSET_NAME(1), 251eaaaeef3SPaul Mundt REGS_OFFSET_NAME(2), 252eaaaeef3SPaul Mundt REGS_OFFSET_NAME(3), 253eaaaeef3SPaul Mundt REGS_OFFSET_NAME(4), 254eaaaeef3SPaul Mundt REGS_OFFSET_NAME(5), 255eaaaeef3SPaul Mundt REGS_OFFSET_NAME(6), 256eaaaeef3SPaul Mundt REGS_OFFSET_NAME(7), 257eaaaeef3SPaul Mundt REGS_OFFSET_NAME(8), 258eaaaeef3SPaul Mundt REGS_OFFSET_NAME(9), 259eaaaeef3SPaul Mundt REGS_OFFSET_NAME(10), 260eaaaeef3SPaul Mundt REGS_OFFSET_NAME(11), 261eaaaeef3SPaul Mundt REGS_OFFSET_NAME(12), 262eaaaeef3SPaul Mundt REGS_OFFSET_NAME(13), 263eaaaeef3SPaul Mundt REGS_OFFSET_NAME(14), 264eaaaeef3SPaul Mundt REGS_OFFSET_NAME(15), 265eaaaeef3SPaul Mundt REG_OFFSET_NAME(pc), 266eaaaeef3SPaul Mundt REG_OFFSET_NAME(pr), 267eaaaeef3SPaul Mundt REG_OFFSET_NAME(sr), 268eaaaeef3SPaul Mundt REG_OFFSET_NAME(gbr), 269eaaaeef3SPaul Mundt REG_OFFSET_NAME(mach), 270eaaaeef3SPaul Mundt REG_OFFSET_NAME(macl), 271eaaaeef3SPaul Mundt REG_OFFSET_NAME(tra), 272eaaaeef3SPaul Mundt REG_OFFSET_END, 273eaaaeef3SPaul Mundt }; 274eaaaeef3SPaul Mundt 275934135c1SPaul Mundt /* 276934135c1SPaul Mundt * These are our native regset flavours. 277934135c1SPaul Mundt */ 278934135c1SPaul Mundt enum sh_regset { 279934135c1SPaul Mundt REGSET_GENERAL, 280e7ab3cd2SPaul Mundt #ifdef CONFIG_SH_FPU 281e7ab3cd2SPaul Mundt REGSET_FPU, 282e7ab3cd2SPaul Mundt #endif 2835dadb343SPaul Mundt #ifdef CONFIG_SH_DSP 2845dadb343SPaul Mundt REGSET_DSP, 2855dadb343SPaul Mundt #endif 286934135c1SPaul Mundt }; 287934135c1SPaul Mundt 288934135c1SPaul Mundt static const struct user_regset sh_regsets[] = { 289934135c1SPaul Mundt /* 290934135c1SPaul Mundt * Format is: 291934135c1SPaul Mundt * R0 --> R15 292934135c1SPaul Mundt * PC, PR, SR, GBR, MACH, MACL, TRA 293934135c1SPaul Mundt */ 294934135c1SPaul Mundt [REGSET_GENERAL] = { 295934135c1SPaul Mundt .core_note_type = NT_PRSTATUS, 296934135c1SPaul Mundt .n = ELF_NGREG, 297934135c1SPaul Mundt .size = sizeof(long), 298934135c1SPaul Mundt .align = sizeof(long), 2993399d90cSAl Viro .regset_get = genregs_get, 300934135c1SPaul Mundt .set = genregs_set, 301934135c1SPaul Mundt }, 3025dadb343SPaul Mundt 303e7ab3cd2SPaul Mundt #ifdef CONFIG_SH_FPU 304e7ab3cd2SPaul Mundt [REGSET_FPU] = { 305e7ab3cd2SPaul Mundt .core_note_type = NT_PRFPREG, 306e7ab3cd2SPaul Mundt .n = sizeof(struct user_fpu_struct) / sizeof(long), 307e7ab3cd2SPaul Mundt .size = sizeof(long), 308e7ab3cd2SPaul Mundt .align = sizeof(long), 3093399d90cSAl Viro .regset_get = fpregs_get, 310e7ab3cd2SPaul Mundt .set = fpregs_set, 311e7ab3cd2SPaul Mundt .active = fpregs_active, 312e7ab3cd2SPaul Mundt }, 313e7ab3cd2SPaul Mundt #endif 314e7ab3cd2SPaul Mundt 3155dadb343SPaul Mundt #ifdef CONFIG_SH_DSP 3165dadb343SPaul Mundt [REGSET_DSP] = { 3175dadb343SPaul Mundt .n = sizeof(struct pt_dspregs) / sizeof(long), 3185dadb343SPaul Mundt .size = sizeof(long), 3195dadb343SPaul Mundt .align = sizeof(long), 3203399d90cSAl Viro .regset_get = dspregs_get, 3215dadb343SPaul Mundt .set = dspregs_set, 32272461997SPaul Mundt .active = dspregs_active, 3235dadb343SPaul Mundt }, 3245dadb343SPaul Mundt #endif 325934135c1SPaul Mundt }; 326934135c1SPaul Mundt 327934135c1SPaul Mundt static const struct user_regset_view user_sh_native_view = { 328934135c1SPaul Mundt .name = "sh", 329934135c1SPaul Mundt .e_machine = EM_SH, 330934135c1SPaul Mundt .regsets = sh_regsets, 331934135c1SPaul Mundt .n = ARRAY_SIZE(sh_regsets), 332934135c1SPaul Mundt }; 333934135c1SPaul Mundt 334f9540eceSPaul Mundt const struct user_regset_view *task_user_regset_view(struct task_struct *task) 335f9540eceSPaul Mundt { 336f9540eceSPaul Mundt return &user_sh_native_view; 337f9540eceSPaul Mundt } 338f9540eceSPaul Mundt 3399b05a69eSNamhyung Kim long arch_ptrace(struct task_struct *child, long request, 3409b05a69eSNamhyung Kim unsigned long addr, unsigned long data) 34148b22cf9SPaul Mundt { 342fa43972fSPaul Mundt unsigned long __user *datap = (unsigned long __user *)data; 34348b22cf9SPaul Mundt int ret; 34448b22cf9SPaul Mundt 34548b22cf9SPaul Mundt switch (request) { 34648b22cf9SPaul Mundt /* read the word at location addr in the USER area. */ 34748b22cf9SPaul Mundt case PTRACE_PEEKUSR: { 34848b22cf9SPaul Mundt unsigned long tmp; 34948b22cf9SPaul Mundt 35048b22cf9SPaul Mundt ret = -EIO; 35148b22cf9SPaul Mundt if ((addr & 3) || addr < 0 || 35248b22cf9SPaul Mundt addr > sizeof(struct user) - 3) 35348b22cf9SPaul Mundt break; 35448b22cf9SPaul Mundt 35548b22cf9SPaul Mundt if (addr < sizeof(struct pt_regs)) 35648b22cf9SPaul Mundt tmp = get_stack_long(child, addr); 3579e1cb206SNamhyung Kim else if (addr >= offsetof(struct user, fpu) && 3589e1cb206SNamhyung Kim addr < offsetof(struct user, u_fpvalid)) { 35948b22cf9SPaul Mundt if (!tsk_used_math(child)) { 3609e1cb206SNamhyung Kim if (addr == offsetof(struct user, fpu.fpscr)) 36148b22cf9SPaul Mundt tmp = FPSCR_INIT; 36248b22cf9SPaul Mundt else 36348b22cf9SPaul Mundt tmp = 0; 3649e1cb206SNamhyung Kim } else { 3659e1cb206SNamhyung Kim unsigned long index; 366c49b6ecfSPhil Edworthy ret = init_fpu(child); 367c49b6ecfSPhil Edworthy if (ret) 368c49b6ecfSPhil Edworthy break; 3699e1cb206SNamhyung Kim index = addr - offsetof(struct user, fpu); 3709b05a69eSNamhyung Kim tmp = ((unsigned long *)child->thread.xstate) 3719e1cb206SNamhyung Kim [index >> 2]; 3729e1cb206SNamhyung Kim } 3739e1cb206SNamhyung Kim } else if (addr == offsetof(struct user, u_fpvalid)) 37448b22cf9SPaul Mundt tmp = !!tsk_used_math(child); 375ba0d4740SPeter Griffin else if (addr == PT_TEXT_ADDR) 376ba0d4740SPeter Griffin tmp = child->mm->start_code; 377ba0d4740SPeter Griffin else if (addr == PT_DATA_ADDR) 378ba0d4740SPeter Griffin tmp = child->mm->start_data; 379ba0d4740SPeter Griffin else if (addr == PT_TEXT_END_ADDR) 380ba0d4740SPeter Griffin tmp = child->mm->end_code; 381ba0d4740SPeter Griffin else if (addr == PT_TEXT_LEN) 382ba0d4740SPeter Griffin tmp = child->mm->end_code - child->mm->start_code; 38348b22cf9SPaul Mundt else 38448b22cf9SPaul Mundt tmp = 0; 385fa43972fSPaul Mundt ret = put_user(tmp, datap); 38648b22cf9SPaul Mundt break; 38748b22cf9SPaul Mundt } 38848b22cf9SPaul Mundt 38948b22cf9SPaul Mundt case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ 39048b22cf9SPaul Mundt ret = -EIO; 39148b22cf9SPaul Mundt if ((addr & 3) || addr < 0 || 39248b22cf9SPaul Mundt addr > sizeof(struct user) - 3) 39348b22cf9SPaul Mundt break; 39448b22cf9SPaul Mundt 39548b22cf9SPaul Mundt if (addr < sizeof(struct pt_regs)) 39648b22cf9SPaul Mundt ret = put_stack_long(child, addr, data); 3979e1cb206SNamhyung Kim else if (addr >= offsetof(struct user, fpu) && 3989e1cb206SNamhyung Kim addr < offsetof(struct user, u_fpvalid)) { 3999e1cb206SNamhyung Kim unsigned long index; 400c49b6ecfSPhil Edworthy ret = init_fpu(child); 401c49b6ecfSPhil Edworthy if (ret) 402c49b6ecfSPhil Edworthy break; 4039e1cb206SNamhyung Kim index = addr - offsetof(struct user, fpu); 40448b22cf9SPaul Mundt set_stopped_child_used_math(child); 4059b05a69eSNamhyung Kim ((unsigned long *)child->thread.xstate) 4069e1cb206SNamhyung Kim [index >> 2] = data; 40748b22cf9SPaul Mundt ret = 0; 4089e1cb206SNamhyung Kim } else if (addr == offsetof(struct user, u_fpvalid)) { 40948b22cf9SPaul Mundt conditional_stopped_child_used_math(data, child); 41048b22cf9SPaul Mundt ret = 0; 41148b22cf9SPaul Mundt } 41248b22cf9SPaul Mundt break; 41348b22cf9SPaul Mundt 414934135c1SPaul Mundt case PTRACE_GETREGS: 415934135c1SPaul Mundt return copy_regset_to_user(child, &user_sh_native_view, 416934135c1SPaul Mundt REGSET_GENERAL, 417934135c1SPaul Mundt 0, sizeof(struct pt_regs), 4189e1cb206SNamhyung Kim datap); 419934135c1SPaul Mundt case PTRACE_SETREGS: 420934135c1SPaul Mundt return copy_regset_from_user(child, &user_sh_native_view, 421934135c1SPaul Mundt REGSET_GENERAL, 422934135c1SPaul Mundt 0, sizeof(struct pt_regs), 4239e1cb206SNamhyung Kim datap); 424e7ab3cd2SPaul Mundt #ifdef CONFIG_SH_FPU 425e7ab3cd2SPaul Mundt case PTRACE_GETFPREGS: 426e7ab3cd2SPaul Mundt return copy_regset_to_user(child, &user_sh_native_view, 427e7ab3cd2SPaul Mundt REGSET_FPU, 428e7ab3cd2SPaul Mundt 0, sizeof(struct user_fpu_struct), 4299e1cb206SNamhyung Kim datap); 430e7ab3cd2SPaul Mundt case PTRACE_SETFPREGS: 431e7ab3cd2SPaul Mundt return copy_regset_from_user(child, &user_sh_native_view, 432e7ab3cd2SPaul Mundt REGSET_FPU, 433e7ab3cd2SPaul Mundt 0, sizeof(struct user_fpu_struct), 4349e1cb206SNamhyung Kim datap); 435e7ab3cd2SPaul Mundt #endif 43648b22cf9SPaul Mundt #ifdef CONFIG_SH_DSP 4375dadb343SPaul Mundt case PTRACE_GETDSPREGS: 4385dadb343SPaul Mundt return copy_regset_to_user(child, &user_sh_native_view, 4395dadb343SPaul Mundt REGSET_DSP, 4405dadb343SPaul Mundt 0, sizeof(struct pt_dspregs), 4419e1cb206SNamhyung Kim datap); 4425dadb343SPaul Mundt case PTRACE_SETDSPREGS: 4435dadb343SPaul Mundt return copy_regset_from_user(child, &user_sh_native_view, 4445dadb343SPaul Mundt REGSET_DSP, 4455dadb343SPaul Mundt 0, sizeof(struct pt_dspregs), 4469e1cb206SNamhyung Kim datap); 44748b22cf9SPaul Mundt #endif 44848b22cf9SPaul Mundt default: 44948b22cf9SPaul Mundt ret = ptrace_request(child, request, addr, data); 45048b22cf9SPaul Mundt break; 45148b22cf9SPaul Mundt } 45248b22cf9SPaul Mundt 45348b22cf9SPaul Mundt return ret; 45448b22cf9SPaul Mundt } 45548b22cf9SPaul Mundt 456ab99c733SPaul Mundt asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) 45748b22cf9SPaul Mundt { 458ab99c733SPaul Mundt long ret = 0; 45948b22cf9SPaul Mundt 460e4da89d0SWill Drewry secure_computing_strict(regs->regs[0]); 461c4637d47SPaul Mundt 462ab99c733SPaul Mundt if (test_thread_flag(TIF_SYSCALL_TRACE) && 463ab99c733SPaul Mundt tracehook_report_syscall_entry(regs)) 46448b22cf9SPaul Mundt /* 465ab99c733SPaul Mundt * Tracing decided this syscall should not happen. 466ab99c733SPaul Mundt * We'll return a bogus call number to get an ENOSYS 467ab99c733SPaul Mundt * error, but leave the original number in regs->regs[0]. 46848b22cf9SPaul Mundt */ 469ab99c733SPaul Mundt ret = -1L; 4701322b9deSYuichi Nakamura 471a74f7e04SPaul Mundt if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 472a74f7e04SPaul Mundt trace_sys_enter(regs, regs->regs[0]); 473c652d780SMatt Fleming 47491397401SEric Paris audit_syscall_entry(regs->regs[3], regs->regs[4], regs->regs[5], 4751322b9deSYuichi Nakamura regs->regs[6], regs->regs[7]); 4761322b9deSYuichi Nakamura 477ab99c733SPaul Mundt return ret ?: regs->regs[0]; 478ab99c733SPaul Mundt } 479ab99c733SPaul Mundt 480ab99c733SPaul Mundt asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) 481ab99c733SPaul Mundt { 482ab99c733SPaul Mundt int step; 483ab99c733SPaul Mundt 484d7e7528bSEric Paris audit_syscall_exit(regs); 485ab99c733SPaul Mundt 486a74f7e04SPaul Mundt if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) 487a74f7e04SPaul Mundt trace_sys_exit(regs, regs->regs[0]); 488c652d780SMatt Fleming 489ab99c733SPaul Mundt step = test_thread_flag(TIF_SINGLESTEP); 490ab99c733SPaul Mundt if (step || test_thread_flag(TIF_SYSCALL_TRACE)) 491ab99c733SPaul Mundt tracehook_report_syscall_exit(regs, step); 49248b22cf9SPaul Mundt } 493