1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * PowerPC version 4 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 5 * 6 * Derived from "arch/m68k/kernel/ptrace.c" 7 * Copyright (C) 1994 by Hamish Macdonald 8 * Taken from linux/kernel/ptrace.c and modified for M680x0. 9 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds 10 * 11 * Modified by Cort Dougan (cort@hq.fsmlabs.com) 12 * and Paul Mackerras (paulus@samba.org). 13 */ 14 15 #include <linux/regset.h> 16 #include <linux/ptrace.h> 17 #include <linux/audit.h> 18 #include <linux/context_tracking.h> 19 #include <linux/syscalls.h> 20 21 #include <asm/switch_to.h> 22 #include <asm/debug.h> 23 24 #include "ptrace-decl.h" 25 26 /* 27 * Called by kernel/ptrace.c when detaching.. 28 * 29 * Make sure single step bits etc are not set. 30 */ 31 void ptrace_disable(struct task_struct *child) 32 { 33 /* make sure the single step bit is not set. */ 34 user_disable_single_step(child); 35 } 36 37 long arch_ptrace(struct task_struct *child, long request, 38 unsigned long addr, unsigned long data) 39 { 40 int ret = -EPERM; 41 void __user *datavp = (void __user *) data; 42 unsigned long __user *datalp = datavp; 43 44 switch (request) { 45 /* read the word at location addr in the USER area. */ 46 case PTRACE_PEEKUSR: { 47 unsigned long index, tmp; 48 49 ret = -EIO; 50 /* convert to index and check */ 51 index = addr / sizeof(long); 52 if ((addr & (sizeof(long) - 1)) || !child->thread.regs) 53 break; 54 55 if (index < PT_FPR0) 56 ret = ptrace_get_reg(child, (int) index, &tmp); 57 else 58 ret = ptrace_get_fpr(child, index, &tmp); 59 60 if (ret) 61 break; 62 ret = put_user(tmp, datalp); 63 break; 64 } 65 66 /* write the word at location addr in the USER area */ 67 case PTRACE_POKEUSR: { 68 unsigned long index; 69 70 ret = -EIO; 71 /* convert to index and check */ 72 index = addr / sizeof(long); 73 if ((addr & (sizeof(long) - 1)) || !child->thread.regs) 74 break; 75 76 if (index < PT_FPR0) 77 ret = ptrace_put_reg(child, index, data); 78 else 79 ret = ptrace_put_fpr(child, index, data); 80 break; 81 } 82 83 case PPC_PTRACE_GETHWDBGINFO: { 84 struct ppc_debug_info dbginfo; 85 86 ppc_gethwdinfo(&dbginfo); 87 88 if (copy_to_user(datavp, &dbginfo, 89 sizeof(struct ppc_debug_info))) 90 return -EFAULT; 91 return 0; 92 } 93 94 case PPC_PTRACE_SETHWDEBUG: { 95 struct ppc_hw_breakpoint bp_info; 96 97 if (copy_from_user(&bp_info, datavp, 98 sizeof(struct ppc_hw_breakpoint))) 99 return -EFAULT; 100 return ppc_set_hwdebug(child, &bp_info); 101 } 102 103 case PPC_PTRACE_DELHWDEBUG: { 104 ret = ppc_del_hwdebug(child, data); 105 break; 106 } 107 108 case PTRACE_GET_DEBUGREG: 109 ret = ptrace_get_debugreg(child, addr, datalp); 110 break; 111 112 case PTRACE_SET_DEBUGREG: 113 ret = ptrace_set_debugreg(child, addr, data); 114 break; 115 116 #ifdef CONFIG_PPC64 117 case PTRACE_GETREGS64: 118 #endif 119 case PTRACE_GETREGS: /* Get all pt_regs from the child. */ 120 return copy_regset_to_user(child, &user_ppc_native_view, 121 REGSET_GPR, 122 0, sizeof(struct user_pt_regs), 123 datavp); 124 125 #ifdef CONFIG_PPC64 126 case PTRACE_SETREGS64: 127 #endif 128 case PTRACE_SETREGS: /* Set all gp regs in the child. */ 129 return copy_regset_from_user(child, &user_ppc_native_view, 130 REGSET_GPR, 131 0, sizeof(struct user_pt_regs), 132 datavp); 133 134 case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */ 135 return copy_regset_to_user(child, &user_ppc_native_view, 136 REGSET_FPR, 137 0, sizeof(elf_fpregset_t), 138 datavp); 139 140 case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */ 141 return copy_regset_from_user(child, &user_ppc_native_view, 142 REGSET_FPR, 143 0, sizeof(elf_fpregset_t), 144 datavp); 145 146 #ifdef CONFIG_ALTIVEC 147 case PTRACE_GETVRREGS: 148 return copy_regset_to_user(child, &user_ppc_native_view, 149 REGSET_VMX, 150 0, (33 * sizeof(vector128) + 151 sizeof(u32)), 152 datavp); 153 154 case PTRACE_SETVRREGS: 155 return copy_regset_from_user(child, &user_ppc_native_view, 156 REGSET_VMX, 157 0, (33 * sizeof(vector128) + 158 sizeof(u32)), 159 datavp); 160 #endif 161 #ifdef CONFIG_VSX 162 case PTRACE_GETVSRREGS: 163 return copy_regset_to_user(child, &user_ppc_native_view, 164 REGSET_VSX, 165 0, 32 * sizeof(double), 166 datavp); 167 168 case PTRACE_SETVSRREGS: 169 return copy_regset_from_user(child, &user_ppc_native_view, 170 REGSET_VSX, 171 0, 32 * sizeof(double), 172 datavp); 173 #endif 174 #ifdef CONFIG_SPE 175 case PTRACE_GETEVRREGS: 176 /* Get the child spe register state. */ 177 return copy_regset_to_user(child, &user_ppc_native_view, 178 REGSET_SPE, 0, 35 * sizeof(u32), 179 datavp); 180 181 case PTRACE_SETEVRREGS: 182 /* Set the child spe register state. */ 183 return copy_regset_from_user(child, &user_ppc_native_view, 184 REGSET_SPE, 0, 35 * sizeof(u32), 185 datavp); 186 #endif 187 188 default: 189 ret = ptrace_request(child, request, addr, data); 190 break; 191 } 192 return ret; 193 } 194 195 void __init pt_regs_check(void); 196 197 /* 198 * Dummy function, its purpose is to break the build if struct pt_regs and 199 * struct user_pt_regs don't match. 200 */ 201 void __init pt_regs_check(void) 202 { 203 BUILD_BUG_ON(offsetof(struct pt_regs, gpr) != 204 offsetof(struct user_pt_regs, gpr)); 205 BUILD_BUG_ON(offsetof(struct pt_regs, nip) != 206 offsetof(struct user_pt_regs, nip)); 207 BUILD_BUG_ON(offsetof(struct pt_regs, msr) != 208 offsetof(struct user_pt_regs, msr)); 209 BUILD_BUG_ON(offsetof(struct pt_regs, orig_gpr3) != 210 offsetof(struct user_pt_regs, orig_gpr3)); 211 BUILD_BUG_ON(offsetof(struct pt_regs, ctr) != 212 offsetof(struct user_pt_regs, ctr)); 213 BUILD_BUG_ON(offsetof(struct pt_regs, link) != 214 offsetof(struct user_pt_regs, link)); 215 BUILD_BUG_ON(offsetof(struct pt_regs, xer) != 216 offsetof(struct user_pt_regs, xer)); 217 BUILD_BUG_ON(offsetof(struct pt_regs, ccr) != 218 offsetof(struct user_pt_regs, ccr)); 219 #ifdef __powerpc64__ 220 BUILD_BUG_ON(offsetof(struct pt_regs, softe) != 221 offsetof(struct user_pt_regs, softe)); 222 #else 223 BUILD_BUG_ON(offsetof(struct pt_regs, mq) != 224 offsetof(struct user_pt_regs, mq)); 225 #endif 226 BUILD_BUG_ON(offsetof(struct pt_regs, trap) != 227 offsetof(struct user_pt_regs, trap)); 228 BUILD_BUG_ON(offsetof(struct pt_regs, dar) != 229 offsetof(struct user_pt_regs, dar)); 230 BUILD_BUG_ON(offsetof(struct pt_regs, dear) != 231 offsetof(struct user_pt_regs, dar)); 232 BUILD_BUG_ON(offsetof(struct pt_regs, dsisr) != 233 offsetof(struct user_pt_regs, dsisr)); 234 BUILD_BUG_ON(offsetof(struct pt_regs, esr) != 235 offsetof(struct user_pt_regs, dsisr)); 236 BUILD_BUG_ON(offsetof(struct pt_regs, result) != 237 offsetof(struct user_pt_regs, result)); 238 239 BUILD_BUG_ON(sizeof(struct user_pt_regs) > sizeof(struct pt_regs)); 240 241 // Now check that the pt_regs offsets match the uapi #defines 242 #define CHECK_REG(_pt, _reg) \ 243 BUILD_BUG_ON(_pt != (offsetof(struct user_pt_regs, _reg) / \ 244 sizeof(unsigned long))); 245 246 CHECK_REG(PT_R0, gpr[0]); 247 CHECK_REG(PT_R1, gpr[1]); 248 CHECK_REG(PT_R2, gpr[2]); 249 CHECK_REG(PT_R3, gpr[3]); 250 CHECK_REG(PT_R4, gpr[4]); 251 CHECK_REG(PT_R5, gpr[5]); 252 CHECK_REG(PT_R6, gpr[6]); 253 CHECK_REG(PT_R7, gpr[7]); 254 CHECK_REG(PT_R8, gpr[8]); 255 CHECK_REG(PT_R9, gpr[9]); 256 CHECK_REG(PT_R10, gpr[10]); 257 CHECK_REG(PT_R11, gpr[11]); 258 CHECK_REG(PT_R12, gpr[12]); 259 CHECK_REG(PT_R13, gpr[13]); 260 CHECK_REG(PT_R14, gpr[14]); 261 CHECK_REG(PT_R15, gpr[15]); 262 CHECK_REG(PT_R16, gpr[16]); 263 CHECK_REG(PT_R17, gpr[17]); 264 CHECK_REG(PT_R18, gpr[18]); 265 CHECK_REG(PT_R19, gpr[19]); 266 CHECK_REG(PT_R20, gpr[20]); 267 CHECK_REG(PT_R21, gpr[21]); 268 CHECK_REG(PT_R22, gpr[22]); 269 CHECK_REG(PT_R23, gpr[23]); 270 CHECK_REG(PT_R24, gpr[24]); 271 CHECK_REG(PT_R25, gpr[25]); 272 CHECK_REG(PT_R26, gpr[26]); 273 CHECK_REG(PT_R27, gpr[27]); 274 CHECK_REG(PT_R28, gpr[28]); 275 CHECK_REG(PT_R29, gpr[29]); 276 CHECK_REG(PT_R30, gpr[30]); 277 CHECK_REG(PT_R31, gpr[31]); 278 CHECK_REG(PT_NIP, nip); 279 CHECK_REG(PT_MSR, msr); 280 CHECK_REG(PT_ORIG_R3, orig_gpr3); 281 CHECK_REG(PT_CTR, ctr); 282 CHECK_REG(PT_LNK, link); 283 CHECK_REG(PT_XER, xer); 284 CHECK_REG(PT_CCR, ccr); 285 #ifdef CONFIG_PPC64 286 CHECK_REG(PT_SOFTE, softe); 287 #else 288 CHECK_REG(PT_MQ, mq); 289 #endif 290 CHECK_REG(PT_TRAP, trap); 291 CHECK_REG(PT_DAR, dar); 292 CHECK_REG(PT_DSISR, dsisr); 293 CHECK_REG(PT_RESULT, result); 294 CHECK_REG(PT_EXIT_FLAGS, exit_flags); 295 #undef CHECK_REG 296 297 BUILD_BUG_ON(PT_REGS_COUNT != sizeof(struct user_pt_regs) / sizeof(unsigned long)); 298 299 /* 300 * PT_DSCR isn't a real reg, but it's important that it doesn't overlap the 301 * real registers. 302 */ 303 BUILD_BUG_ON(PT_DSCR < sizeof(struct user_pt_regs) / sizeof(unsigned long)); 304 305 // ptrace_get/put_fpr() rely on PPC32 and VSX being incompatible 306 BUILD_BUG_ON(IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_VSX)); 307 } 308