^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Ptrace support for Hexagon
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/regset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/user.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) #include <asm/user.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #if arch_has_single_step()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* Both called from ptrace_resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) void user_enable_single_step(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) pt_set_singlestep(task_pt_regs(child));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) set_tsk_thread_flag(child, TIF_SINGLESTEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) void user_disable_single_step(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) pt_clr_singlestep(task_pt_regs(child));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) clear_tsk_thread_flag(child, TIF_SINGLESTEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static int genregs_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /* The general idea here is that the copyout must happen in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * exactly the same order in which the userspace expects these
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * regs. Now, the sequence in userspace does not match the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * sequence in the kernel, so everything past the 32 gprs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * happens one at a time.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) membuf_write(&to, ®s->r00, 32*sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /* Must be exactly same sequence as struct user_regs_struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) membuf_store(&to, regs->sa0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) membuf_store(&to, regs->lc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) membuf_store(&to, regs->sa1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) membuf_store(&to, regs->lc1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) membuf_store(&to, regs->m0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) membuf_store(&to, regs->m1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) membuf_store(&to, regs->usr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) membuf_store(&to, regs->preds);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) membuf_store(&to, regs->gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) membuf_store(&to, regs->ugp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) membuf_store(&to, pt_elr(regs)); // pc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) membuf_store(&to, (unsigned long)pt_cause(regs)); // cause
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) membuf_store(&to, pt_badva(regs)); // badva
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #if CONFIG_HEXAGON_ARCH_VERSION >=4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) membuf_store(&to, regs->cs0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) membuf_store(&to, regs->cs1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) return membuf_zero(&to, sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return membuf_zero(&to, 3 * sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static int genregs_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) unsigned long bucket;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (!regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) ®s->r00, 0, 32*sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define INEXT(KPT_REG, USR_REG) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (!ret) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) KPT_REG, offsetof(struct user_regs_struct, USR_REG), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) offsetof(struct user_regs_struct, USR_REG) + \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) sizeof(unsigned long));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Must be exactly same sequence as struct user_regs_struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) INEXT(®s->sa0, sa0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) INEXT(®s->lc0, lc0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) INEXT(®s->sa1, sa1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) INEXT(®s->lc1, lc1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) INEXT(®s->m0, m0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) INEXT(®s->m1, m1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) INEXT(®s->usr, usr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) INEXT(®s->preds, p3_0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) INEXT(®s->gp, gp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) INEXT(®s->ugp, ugp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) INEXT(&pt_elr(regs), pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* CAUSE and BADVA aren't writeable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) INEXT(&bucket, cause);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) INEXT(&bucket, badva);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #if CONFIG_HEXAGON_ARCH_VERSION >=4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) INEXT(®s->cs0, cs0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) INEXT(®s->cs1, cs1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Ignore the rest, if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) offsetof(struct user_regs_struct, pad1), -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * This is special; SP is actually restored by the VM via the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * special event record which is set by the special trap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) regs->hvmer.vmpsp = regs->r29;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) enum hexagon_regset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) REGSET_GENERAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static const struct user_regset hexagon_regsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) [REGSET_GENERAL] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .core_note_type = NT_PRSTATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) .n = ELF_NGREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) .size = sizeof(unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) .align = sizeof(unsigned long),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) .regset_get = genregs_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) .set = genregs_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static const struct user_regset_view hexagon_user_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .name = "hexagon",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .e_machine = ELF_ARCH,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .ei_osabi = ELF_OSABI,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .regsets = hexagon_regsets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) .e_flags = ELF_CORE_EFLAGS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) .n = ARRAY_SIZE(hexagon_regsets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) const struct user_regset_view *task_user_regset_view(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return &hexagon_user_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) void ptrace_disable(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /* Boilerplate - resolves to null inline if no HW single-step */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) user_disable_single_step(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) long arch_ptrace(struct task_struct *child, long request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) unsigned long addr, unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) return ptrace_request(child, request, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }