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