linux/arch/nds32/kernel/ptrace.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2005-2017 Andes Technology Corporation
   3
   4#include <linux/ptrace.h>
   5#include <linux/regset.h>
   6#include <linux/tracehook.h>
   7#include <linux/elf.h>
   8#include <linux/sched/task_stack.h>
   9
  10enum nds32_regset {
  11        REGSET_GPR,
  12};
  13
  14static int gpr_get(struct task_struct *target,
  15                   const struct user_regset *regset,
  16                   struct membuf to)
  17{
  18        return membuf_write(&to, &task_pt_regs(target)->user_regs,
  19                                sizeof(struct user_pt_regs));
  20}
  21
  22static int gpr_set(struct task_struct *target, const struct user_regset *regset,
  23                   unsigned int pos, unsigned int count,
  24                   const void *kbuf, const void __user * ubuf)
  25{
  26        int err;
  27        struct user_pt_regs newregs = task_pt_regs(target)->user_regs;
  28
  29        err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
  30        if (err)
  31                return err;
  32
  33        task_pt_regs(target)->user_regs = newregs;
  34        return 0;
  35}
  36
  37static const struct user_regset nds32_regsets[] = {
  38        [REGSET_GPR] = {
  39                        .core_note_type = NT_PRSTATUS,
  40                        .n = sizeof(struct user_pt_regs) / sizeof(u32),
  41                        .size = sizeof(elf_greg_t),
  42                        .align = sizeof(elf_greg_t),
  43                        .regset_get = gpr_get,
  44                        .set = gpr_set}
  45};
  46
  47static const struct user_regset_view nds32_user_view = {
  48        .name = "nds32",
  49        .e_machine = EM_NDS32,
  50        .regsets = nds32_regsets,
  51        .n = ARRAY_SIZE(nds32_regsets)
  52};
  53
  54const struct user_regset_view *task_user_regset_view(struct task_struct *task)
  55{
  56        return &nds32_user_view;
  57}
  58
  59void ptrace_disable(struct task_struct *child)
  60{
  61        user_disable_single_step(child);
  62}
  63
  64/* do_ptrace()
  65 *
  66 * Provide ptrace defined service.
  67 */
  68long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
  69                 unsigned long data)
  70{
  71        int ret = -EIO;
  72
  73        switch (request) {
  74        default:
  75                ret = ptrace_request(child, request, addr, data);
  76                break;
  77        }
  78
  79        return ret;
  80}
  81
  82void user_enable_single_step(struct task_struct *child)
  83{
  84        struct pt_regs *regs;
  85        regs = task_pt_regs(child);
  86        regs->ipsw |= PSW_mskHSS;
  87        set_tsk_thread_flag(child, TIF_SINGLESTEP);
  88}
  89
  90void user_disable_single_step(struct task_struct *child)
  91{
  92        struct pt_regs *regs;
  93        regs = task_pt_regs(child);
  94        regs->ipsw &= ~PSW_mskHSS;
  95        clear_tsk_thread_flag(child, TIF_SINGLESTEP);
  96}
  97
  98/* sys_trace()
  99 *
 100 * syscall trace handler.
 101 */
 102
 103asmlinkage int syscall_trace_enter(struct pt_regs *regs)
 104{
 105        if (test_thread_flag(TIF_SYSCALL_TRACE)) {
 106                if (tracehook_report_syscall_entry(regs))
 107                        forget_syscall(regs);
 108        }
 109        return regs->syscallno;
 110}
 111
 112asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 113{
 114        int step = test_thread_flag(TIF_SINGLESTEP);
 115        if (step || test_thread_flag(TIF_SYSCALL_TRACE))
 116                tracehook_report_syscall_exit(regs, step);
 117
 118}
 119