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