^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2001 - 2007 Tensilica Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Chris Zankel <chris@zankel.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Scott Foehner<sfoehner@yahoo.com>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Kevin Chea
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Marc Gauthier<marc@tensilica.com> <marc@alumni.uwaterloo.ca>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/audit.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/hw_breakpoint.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/perf_event.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/regset.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/seccomp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/smp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/tracehook.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define CREATE_TRACE_POINTS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <trace/events/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <asm/coprocessor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <asm/elf.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int gpr_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct user_pt_regs newregs = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) .pc = regs->pc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) .ps = regs->ps & ~(1 << PS_EXCM_BIT),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) .lbeg = regs->lbeg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) .lend = regs->lend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) .lcount = regs->lcount,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) .sar = regs->sar,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) .threadptr = regs->threadptr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .windowbase = regs->windowbase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .windowstart = regs->windowstart,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .syscall = regs->syscall,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) memcpy(newregs.a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) regs->areg + XCHAL_NUM_AREGS - regs->windowbase * 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) regs->windowbase * 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) memcpy(newregs.a + regs->windowbase * 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) regs->areg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) (WSBITS - regs->windowbase) * 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return membuf_write(&to, &newregs, sizeof(newregs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int gpr_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct user_pt_regs newregs = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct pt_regs *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) const u32 ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (newregs.windowbase >= XCHAL_NUM_AREGS / 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) regs->pc = newregs.pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) regs->ps = (regs->ps & ~ps_mask) | (newregs.ps & ps_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) regs->lbeg = newregs.lbeg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) regs->lend = newregs.lend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) regs->lcount = newregs.lcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) regs->sar = newregs.sar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) regs->threadptr = newregs.threadptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (newregs.syscall)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) regs->syscall = newregs.syscall;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (newregs.windowbase != regs->windowbase ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) newregs.windowstart != regs->windowstart) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) u32 rotws, wmask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) rotws = (((newregs.windowstart |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) (newregs.windowstart << WSBITS)) >>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) newregs.windowbase) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ((1 << WSBITS) - 1)) & ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) wmask = ((rotws ? WSBITS + 1 - ffs(rotws) : 0) << 4) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) (rotws & 0xF) | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) regs->windowbase = newregs.windowbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) regs->windowstart = newregs.windowstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) regs->wmask = wmask;
^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) memcpy(regs->areg + XCHAL_NUM_AREGS - newregs.windowbase * 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) newregs.a, newregs.windowbase * 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) memcpy(regs->areg, newregs.a + newregs.windowbase * 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) (WSBITS - newregs.windowbase) * 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static int tie_get(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) struct membuf to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) struct thread_info *ti = task_thread_info(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) elf_xtregs_t *newregs = kzalloc(sizeof(elf_xtregs_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) if (!newregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) newregs->opt = regs->xtregs_opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) newregs->user = ti->xtregs_user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #if XTENSA_HAVE_COPROCESSORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /* Flush all coprocessor registers to memory. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) coprocessor_flush_all(ti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) newregs->cp0 = ti->xtregs_cp.cp0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) newregs->cp1 = ti->xtregs_cp.cp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) newregs->cp2 = ti->xtregs_cp.cp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) newregs->cp3 = ti->xtregs_cp.cp3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) newregs->cp4 = ti->xtregs_cp.cp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) newregs->cp5 = ti->xtregs_cp.cp5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) newregs->cp6 = ti->xtregs_cp.cp6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) newregs->cp7 = ti->xtregs_cp.cp7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) ret = membuf_write(&to, newregs, sizeof(*newregs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) kfree(newregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static int tie_set(struct task_struct *target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) const struct user_regset *regset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) unsigned int pos, unsigned int count,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) const void *kbuf, const void __user *ubuf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct pt_regs *regs = task_pt_regs(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct thread_info *ti = task_thread_info(target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) elf_xtregs_t *newregs = kzalloc(sizeof(elf_xtregs_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (!newregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) newregs, 0, -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) regs->xtregs_opt = newregs->opt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) ti->xtregs_user = newregs->user;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #if XTENSA_HAVE_COPROCESSORS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) /* Flush all coprocessors before we overwrite them. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) coprocessor_flush_all(ti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) coprocessor_release_all(ti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) ti->xtregs_cp.cp0 = newregs->cp0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ti->xtregs_cp.cp1 = newregs->cp1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ti->xtregs_cp.cp2 = newregs->cp2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ti->xtregs_cp.cp3 = newregs->cp3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ti->xtregs_cp.cp4 = newregs->cp4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ti->xtregs_cp.cp5 = newregs->cp5;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ti->xtregs_cp.cp6 = newregs->cp6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ti->xtregs_cp.cp7 = newregs->cp7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) kfree(newregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) return ret;
^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) enum xtensa_regset {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) REGSET_GPR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) REGSET_TIE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static const struct user_regset xtensa_regsets[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) [REGSET_GPR] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) .core_note_type = NT_PRSTATUS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) .n = sizeof(struct user_pt_regs) / sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) .size = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) .align = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) .regset_get = gpr_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) .set = gpr_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) [REGSET_TIE] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) .core_note_type = NT_PRFPREG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) .n = sizeof(elf_xtregs_t) / sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) .size = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) .align = sizeof(u32),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .regset_get = tie_get,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .set = tie_set,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static const struct user_regset_view user_xtensa_view = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .name = "xtensa",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .e_machine = EM_XTENSA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) .regsets = xtensa_regsets,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) .n = ARRAY_SIZE(xtensa_regsets)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) const struct user_regset_view *task_user_regset_view(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return &user_xtensa_view;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) void user_enable_single_step(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) child->ptrace |= PT_SINGLESTEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) void user_disable_single_step(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) child->ptrace &= ~PT_SINGLESTEP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) * Called by kernel/ptrace.c when detaching to disable single stepping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) void ptrace_disable(struct task_struct *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) /* Nothing to do.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) static int ptrace_getregs(struct task_struct *child, void __user *uregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) return copy_regset_to_user(child, &user_xtensa_view, REGSET_GPR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 0, sizeof(xtensa_gregset_t), uregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) static int ptrace_setregs(struct task_struct *child, void __user *uregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return copy_regset_from_user(child, &user_xtensa_view, REGSET_GPR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 0, sizeof(xtensa_gregset_t), uregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int ptrace_getxregs(struct task_struct *child, void __user *uregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) return copy_regset_to_user(child, &user_xtensa_view, REGSET_TIE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 0, sizeof(elf_xtregs_t), uregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) static int ptrace_setxregs(struct task_struct *child, void __user *uregs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return copy_regset_from_user(child, &user_xtensa_view, REGSET_TIE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 0, sizeof(elf_xtregs_t), uregs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static int ptrace_peekusr(struct task_struct *child, long regno,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) long __user *ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct pt_regs *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) unsigned long tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) regs = task_pt_regs(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) tmp = 0; /* Default return value. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) switch(regno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) tmp = regs->areg[regno - REG_AR_BASE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case REG_A_BASE ... REG_A_BASE + 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) tmp = regs->areg[regno - REG_A_BASE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) case REG_PC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) tmp = regs->pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) case REG_PS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) /* Note: PS.EXCM is not set while user task is running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) * its being set in regs is for exception handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) * convenience.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) tmp = (regs->ps & ~(1 << PS_EXCM_BIT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) case REG_WB:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) break; /* tmp = 0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case REG_WS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) unsigned long wb = regs->windowbase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) unsigned long ws = regs->windowstart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) tmp = ((ws >> wb) | (ws << (WSBITS - wb))) &
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ((1 << WSBITS) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) case REG_LBEG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) tmp = regs->lbeg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case REG_LEND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) tmp = regs->lend;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) case REG_LCOUNT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) tmp = regs->lcount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) case REG_SAR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) tmp = regs->sar;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) case SYSCALL_NR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) tmp = regs->syscall;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) return put_user(tmp, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static int ptrace_pokeusr(struct task_struct *child, long regno, long val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct pt_regs *regs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) regs = task_pt_regs(child);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) switch (regno) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) case REG_AR_BASE ... REG_AR_BASE + XCHAL_NUM_AREGS - 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) regs->areg[regno - REG_AR_BASE] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) case REG_A_BASE ... REG_A_BASE + 15:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) regs->areg[regno - REG_A_BASE] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) case REG_PC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) regs->pc = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case SYSCALL_NR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) regs->syscall = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) #ifdef CONFIG_HAVE_HW_BREAKPOINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) static void ptrace_hbptriggered(struct perf_event *bp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) struct perf_sample_data *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) struct arch_hw_breakpoint *bkpt = counter_arch_bp(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) if (bp->attr.bp_type & HW_BREAKPOINT_X) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) for (i = 0; i < XCHAL_NUM_IBREAK; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (current->thread.ptrace_bp[i] == bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) i <<= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) for (i = 0; i < XCHAL_NUM_DBREAK; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) if (current->thread.ptrace_wp[i] == bp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) i = (i << 1) | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) force_sig_ptrace_errno_trap(i, (void __user *)bkpt->address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) static struct perf_event *ptrace_hbp_create(struct task_struct *tsk, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) struct perf_event_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ptrace_breakpoint_init(&attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) /* Initialise fields to sane defaults. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) attr.bp_addr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) attr.bp_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) attr.bp_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) attr.disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return register_user_hw_breakpoint(&attr, ptrace_hbptriggered, NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) tsk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) * Address bit 0 choose instruction (0) or data (1) break register, bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) * 31..1 are the register number.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) * Both PTRACE_GETHBPREGS and PTRACE_SETHBPREGS transfer two 32-bit words:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) * address (0) and control (1).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) * Instruction breakpoint contorl word is 0 to clear breakpoint, 1 to set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) * Data breakpoint control word bit 31 is 'trigger on store', bit 30 is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) * 'trigger on load, bits 29..0 are length. Length 0 is used to clear a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * breakpoint. To set a breakpoint length must be a power of 2 in the range
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) * 1..64 and the address must be length-aligned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static long ptrace_gethbpregs(struct task_struct *child, long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) long __user *datap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct perf_event *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) u32 user_data[2] = {0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) bool dbreak = addr & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) unsigned idx = addr >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if ((!dbreak && idx >= XCHAL_NUM_IBREAK) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) (dbreak && idx >= XCHAL_NUM_DBREAK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) if (dbreak)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) bp = child->thread.ptrace_wp[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) bp = child->thread.ptrace_bp[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) user_data[0] = bp->attr.bp_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) user_data[1] = bp->attr.disabled ? 0 : bp->attr.bp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if (dbreak) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (bp->attr.bp_type & HW_BREAKPOINT_R)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) user_data[1] |= DBREAKC_LOAD_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) if (bp->attr.bp_type & HW_BREAKPOINT_W)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) user_data[1] |= DBREAKC_STOR_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (copy_to_user(datap, user_data, sizeof(user_data)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) static long ptrace_sethbpregs(struct task_struct *child, long addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) long __user *datap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct perf_event *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) struct perf_event_attr attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) u32 user_data[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) bool dbreak = addr & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) unsigned idx = addr >> 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) int bp_type = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if ((!dbreak && idx >= XCHAL_NUM_IBREAK) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) (dbreak && idx >= XCHAL_NUM_DBREAK))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) if (copy_from_user(user_data, datap, sizeof(user_data)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) if (dbreak) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) bp = child->thread.ptrace_wp[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) if (user_data[1] & DBREAKC_LOAD_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) bp_type |= HW_BREAKPOINT_R;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (user_data[1] & DBREAKC_STOR_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) bp_type |= HW_BREAKPOINT_W;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) bp = child->thread.ptrace_bp[idx];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) bp_type = HW_BREAKPOINT_X;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (!bp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) bp = ptrace_hbp_create(child,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) bp_type ? bp_type : HW_BREAKPOINT_RW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (IS_ERR(bp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return PTR_ERR(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (dbreak)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) child->thread.ptrace_wp[idx] = bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) child->thread.ptrace_bp[idx] = bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) attr = bp->attr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) attr.bp_addr = user_data[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) attr.bp_len = user_data[1] & ~(DBREAKC_LOAD_MASK | DBREAKC_STOR_MASK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) attr.bp_type = bp_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) attr.disabled = !attr.bp_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) return modify_user_hw_breakpoint(bp, &attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) long arch_ptrace(struct task_struct *child, long request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) unsigned long addr, unsigned long data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) int ret = -EPERM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) void __user *datap = (void __user *) data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) switch (request) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) case PTRACE_PEEKUSR: /* read register specified by addr. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) ret = ptrace_peekusr(child, addr, datap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) case PTRACE_POKEUSR: /* write register specified by addr. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) ret = ptrace_pokeusr(child, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) case PTRACE_GETREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) ret = ptrace_getregs(child, datap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) case PTRACE_SETREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ret = ptrace_setregs(child, datap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) case PTRACE_GETXTREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) ret = ptrace_getxregs(child, datap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) case PTRACE_SETXTREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) ret = ptrace_setxregs(child, datap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) #ifdef CONFIG_HAVE_HW_BREAKPOINT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) case PTRACE_GETHBPREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) ret = ptrace_gethbpregs(child, addr, datap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) case PTRACE_SETHBPREGS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) ret = ptrace_sethbpregs(child, addr, datap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) ret = ptrace_request(child, request, addr, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) void do_syscall_trace_leave(struct pt_regs *regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) int do_syscall_trace_enter(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (regs->syscall == NO_SYSCALL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) regs->areg[2] = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) if (test_thread_flag(TIF_SYSCALL_TRACE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) tracehook_report_syscall_entry(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) regs->areg[2] = -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) regs->syscall = NO_SYSCALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) if (regs->syscall == NO_SYSCALL ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) secure_computing() == -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) do_syscall_trace_leave(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) trace_sys_enter(regs, syscall_get_nr(current, regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) audit_syscall_entry(regs->syscall, regs->areg[6],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) regs->areg[3], regs->areg[4],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) regs->areg[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) void do_syscall_trace_leave(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) int step;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) audit_syscall_exit(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) trace_sys_exit(regs, regs_return_value(regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) step = test_thread_flag(TIF_SINGLESTEP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (step || test_thread_flag(TIF_SYSCALL_TRACE))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) tracehook_report_syscall_exit(regs, step);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }