^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * linux/arch/h8300/kernel/ptrace.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file is subject to the terms and conditions of the GNU General
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Public License. See the file COPYING in the main directory of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * this archive for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/tracehook.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/regset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define CCR_MASK 0x6f /* mode/imask not set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define EXR_MASK 0x80 /* modify only T */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PT_REG(r) offsetof(struct pt_regs, r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) extern void user_disable_single_step(struct task_struct *child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* Mapping from PT_xxx to the stack offset at which the register is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) saved. Notice that usp has no stack-slot and needs to be treated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) specially (see get_reg/put_reg below). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static const int register_offset[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) PT_REG(er5), PT_REG(er6), PT_REG(er0), -1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) PT_REG(orig_er0), PT_REG(ccr), PT_REG(pc),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #if defined(CONFIG_CPU_H8S)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) PT_REG(exr),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) /* read register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) long h8300_get_reg(struct task_struct *task, int regno)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) switch (regno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) case PT_USP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) return task->thread.usp + sizeof(long)*2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) case PT_CCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) case PT_EXR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) return *(unsigned short *)(task->thread.esp0 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) register_offset[regno]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) return *(unsigned long *)(task->thread.esp0 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) register_offset[regno]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^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) int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned short oldccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned short oldexr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) switch (regno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) case PT_USP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) task->thread.usp = data - sizeof(long)*2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) case PT_CCR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) oldccr = *(unsigned short *)(task->thread.esp0 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) register_offset[regno]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) oldccr &= ~CCR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) data &= CCR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) data |= oldccr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *(unsigned short *)(task->thread.esp0 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) register_offset[regno]) = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) case PT_EXR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) oldexr = *(unsigned short *)(task->thread.esp0 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) register_offset[regno]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) oldccr &= ~EXR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) data &= EXR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) data |= oldexr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *(unsigned short *)(task->thread.esp0 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) register_offset[regno]) = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *(unsigned long *)(task->thread.esp0 +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) register_offset[regno]) = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) static int regs_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) BUILD_BUG_ON(sizeof(struct user_regs_struct) % sizeof(long) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) for (r = 0; r < ELF_NGREG; r++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) membuf_store(&to, h8300_get_reg(target, r));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int regs_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) struct user_regs_struct regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) long *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* build user regs in buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) for (reg = (long *)®s, r = 0; r < sizeof(regs) / sizeof(long); r++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) *reg++ = h8300_get_reg(target, r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) ®s, 0, sizeof(regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) /* write back to pt_regs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) for (reg = (long *)®s, r = 0; r < sizeof(regs) / sizeof(long); r++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) h8300_put_reg(target, r, *reg++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) enum h8300_regset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) REGSET_GENERAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static const struct user_regset h8300_regsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) [REGSET_GENERAL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) .core_note_type = NT_PRSTATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .n = ELF_NGREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .size = sizeof(long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .align = sizeof(long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .regset_get = regs_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .set = regs_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) static const struct user_regset_view user_h8300_native_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .name = "h8300",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) .e_machine = EM_H8_300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) .regsets = h8300_regsets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) .n = ARRAY_SIZE(h8300_regsets),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) const struct user_regset_view *task_user_regset_view(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) return &user_h8300_native_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) void ptrace_disable(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) user_disable_single_step(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) long arch_ptrace(struct task_struct *child, long request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) unsigned long addr, unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) switch (request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ret = ptrace_request(child, request, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) long ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) if (test_thread_flag(TIF_SYSCALL_TRACE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) tracehook_report_syscall_entry(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) * Tracing decided this syscall should not happen.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) * We'll return a bogus call number to get an ENOSYS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) * error, but leave the original number in regs->regs[0].
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ret = -1L;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) audit_syscall_entry(regs->er1, regs->er2, regs->er3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) regs->er4, regs->er5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return ret ?: regs->er0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) audit_syscall_exit(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) step = test_thread_flag(TIF_SINGLESTEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (step || test_thread_flag(TIF_SYSCALL_TRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) tracehook_report_syscall_exit(regs, step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }