1 /* 2 * ptrace for 32-bit processes running on a 64-bit kernel. 3 * 4 * PowerPC version 5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 6 * 7 * Derived from "arch/m68k/kernel/ptrace.c" 8 * Copyright (C) 1994 by Hamish Macdonald 9 * Taken from linux/kernel/ptrace.c and modified for M680x0. 10 * linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds 11 * 12 * Modified by Cort Dougan (cort@hq.fsmlabs.com) 13 * and Paul Mackerras (paulus@samba.org). 14 * 15 * This file is subject to the terms and conditions of the GNU General 16 * Public License. See the file COPYING in the main directory of 17 * this archive for more details. 18 */ 19 20 #include <linux/ptrace.h> 21 #include <linux/regset.h> 22 #include <linux/compat.h> 23 24 #include <asm/switch_to.h> 25 26 #include "ptrace-decl.h" 27 28 /* 29 * does not yet catch signals sent when the child dies. 30 * in exit.c or in signal.c. 31 */ 32 33 /* Macros to workout the correct index for the FPR in the thread struct */ 34 #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1) 35 #define FPRHALF(i) (((i) - PT_FPR0) & 1) 36 #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i) 37 38 long compat_arch_ptrace(struct task_struct *child, compat_long_t request, 39 compat_ulong_t caddr, compat_ulong_t cdata) 40 { 41 unsigned long addr = caddr; 42 unsigned long data = cdata; 43 int ret; 44 45 switch (request) { 46 /* 47 * Read 4 bytes of the other process' storage 48 * data is a pointer specifying where the user wants the 49 * 4 bytes copied into 50 * addr is a pointer in the user's storage that contains an 8 byte 51 * address in the other process of the 4 bytes that is to be read 52 * (this is run in a 32-bit process looking at a 64-bit process) 53 * when I and D space are separate, these will need to be fixed. 54 */ 55 case PPC_PTRACE_PEEKTEXT_3264: 56 case PPC_PTRACE_PEEKDATA_3264: { 57 u32 tmp; 58 int copied; 59 u32 __user * addrOthers; 60 61 ret = -EIO; 62 63 /* Get the addr in the other process that we want to read */ 64 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0) 65 break; 66 67 copied = ptrace_access_vm(child, (u64)addrOthers, &tmp, 68 sizeof(tmp), FOLL_FORCE); 69 if (copied != sizeof(tmp)) 70 break; 71 ret = put_user(tmp, (u32 __user *)data); 72 break; 73 } 74 75 /* Read a register (specified by ADDR) out of the "user area" */ 76 case PTRACE_PEEKUSR: { 77 int index; 78 unsigned long tmp; 79 80 ret = -EIO; 81 /* convert to index and check */ 82 index = (unsigned long) addr >> 2; 83 if ((addr & 3) || (index > PT_FPSCR32)) 84 break; 85 86 CHECK_FULL_REGS(child->thread.regs); 87 if (index < PT_FPR0) { 88 ret = ptrace_get_reg(child, index, &tmp); 89 if (ret) 90 break; 91 } else { 92 flush_fp_to_thread(child); 93 /* 94 * the user space code considers the floating point 95 * to be an array of unsigned int (32 bits) - the 96 * index passed in is based on this assumption. 97 */ 98 tmp = ((unsigned int *)child->thread.fp_state.fpr) 99 [FPRINDEX(index)]; 100 } 101 ret = put_user((unsigned int)tmp, (u32 __user *)data); 102 break; 103 } 104 105 /* 106 * Read 4 bytes out of the other process' pt_regs area 107 * data is a pointer specifying where the user wants the 108 * 4 bytes copied into 109 * addr is the offset into the other process' pt_regs structure 110 * that is to be read 111 * (this is run in a 32-bit process looking at a 64-bit process) 112 */ 113 case PPC_PTRACE_PEEKUSR_3264: { 114 u32 index; 115 u32 reg32bits; 116 u64 tmp; 117 u32 numReg; 118 u32 part; 119 120 ret = -EIO; 121 /* Determine which register the user wants */ 122 index = (u64)addr >> 2; 123 numReg = index / 2; 124 /* Determine which part of the register the user wants */ 125 if (index % 2) 126 part = 1; /* want the 2nd half of the register (right-most). */ 127 else 128 part = 0; /* want the 1st half of the register (left-most). */ 129 130 /* Validate the input - check to see if address is on the wrong boundary 131 * or beyond the end of the user area 132 */ 133 if ((addr & 3) || numReg > PT_FPSCR) 134 break; 135 136 CHECK_FULL_REGS(child->thread.regs); 137 if (numReg >= PT_FPR0) { 138 flush_fp_to_thread(child); 139 /* get 64 bit FPR */ 140 tmp = child->thread.fp_state.fpr[numReg - PT_FPR0][0]; 141 } else { /* register within PT_REGS struct */ 142 unsigned long tmp2; 143 ret = ptrace_get_reg(child, numReg, &tmp2); 144 if (ret) 145 break; 146 tmp = tmp2; 147 } 148 reg32bits = ((u32*)&tmp)[part]; 149 ret = put_user(reg32bits, (u32 __user *)data); 150 break; 151 } 152 153 /* 154 * Write 4 bytes into the other process' storage 155 * data is the 4 bytes that the user wants written 156 * addr is a pointer in the user's storage that contains an 157 * 8 byte address in the other process where the 4 bytes 158 * that is to be written 159 * (this is run in a 32-bit process looking at a 64-bit process) 160 * when I and D space are separate, these will need to be fixed. 161 */ 162 case PPC_PTRACE_POKETEXT_3264: 163 case PPC_PTRACE_POKEDATA_3264: { 164 u32 tmp = data; 165 u32 __user * addrOthers; 166 167 /* Get the addr in the other process that we want to write into */ 168 ret = -EIO; 169 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0) 170 break; 171 ret = 0; 172 if (ptrace_access_vm(child, (u64)addrOthers, &tmp, 173 sizeof(tmp), 174 FOLL_FORCE | FOLL_WRITE) == sizeof(tmp)) 175 break; 176 ret = -EIO; 177 break; 178 } 179 180 /* write the word at location addr in the USER area */ 181 case PTRACE_POKEUSR: { 182 unsigned long index; 183 184 ret = -EIO; 185 /* convert to index and check */ 186 index = (unsigned long) addr >> 2; 187 if ((addr & 3) || (index > PT_FPSCR32)) 188 break; 189 190 CHECK_FULL_REGS(child->thread.regs); 191 if (index < PT_FPR0) { 192 ret = ptrace_put_reg(child, index, data); 193 } else { 194 flush_fp_to_thread(child); 195 /* 196 * the user space code considers the floating point 197 * to be an array of unsigned int (32 bits) - the 198 * index passed in is based on this assumption. 199 */ 200 ((unsigned int *)child->thread.fp_state.fpr) 201 [FPRINDEX(index)] = data; 202 ret = 0; 203 } 204 break; 205 } 206 207 /* 208 * Write 4 bytes into the other process' pt_regs area 209 * data is the 4 bytes that the user wants written 210 * addr is the offset into the other process' pt_regs structure 211 * that is to be written into 212 * (this is run in a 32-bit process looking at a 64-bit process) 213 */ 214 case PPC_PTRACE_POKEUSR_3264: { 215 u32 index; 216 u32 numReg; 217 218 ret = -EIO; 219 /* Determine which register the user wants */ 220 index = (u64)addr >> 2; 221 numReg = index / 2; 222 223 /* 224 * Validate the input - check to see if address is on the 225 * wrong boundary or beyond the end of the user area 226 */ 227 if ((addr & 3) || (numReg > PT_FPSCR)) 228 break; 229 CHECK_FULL_REGS(child->thread.regs); 230 if (numReg < PT_FPR0) { 231 unsigned long freg; 232 ret = ptrace_get_reg(child, numReg, &freg); 233 if (ret) 234 break; 235 if (index % 2) 236 freg = (freg & ~0xfffffffful) | (data & 0xfffffffful); 237 else 238 freg = (freg & 0xfffffffful) | (data << 32); 239 ret = ptrace_put_reg(child, numReg, freg); 240 } else { 241 u64 *tmp; 242 flush_fp_to_thread(child); 243 /* get 64 bit FPR ... */ 244 tmp = &child->thread.fp_state.fpr[numReg - PT_FPR0][0]; 245 /* ... write the 32 bit part we want */ 246 ((u32 *)tmp)[index % 2] = data; 247 ret = 0; 248 } 249 break; 250 } 251 252 case PTRACE_GET_DEBUGREG: { 253 #ifndef CONFIG_PPC_ADV_DEBUG_REGS 254 unsigned long dabr_fake; 255 #endif 256 ret = -EINVAL; 257 /* We only support one DABR and no IABRS at the moment */ 258 if (addr > 0) 259 break; 260 #ifdef CONFIG_PPC_ADV_DEBUG_REGS 261 ret = put_user(child->thread.debug.dac1, (u32 __user *)data); 262 #else 263 dabr_fake = ( 264 (child->thread.hw_brk[0].address & (~HW_BRK_TYPE_DABR)) | 265 (child->thread.hw_brk[0].type & HW_BRK_TYPE_DABR)); 266 ret = put_user(dabr_fake, (u32 __user *)data); 267 #endif 268 break; 269 } 270 271 case PTRACE_GETREGS: /* Get all pt_regs from the child. */ 272 return copy_regset_to_user( 273 child, task_user_regset_view(current), 0, 274 0, PT_REGS_COUNT * sizeof(compat_long_t), 275 compat_ptr(data)); 276 277 case PTRACE_SETREGS: /* Set all gp regs in the child. */ 278 return copy_regset_from_user( 279 child, task_user_regset_view(current), 0, 280 0, PT_REGS_COUNT * sizeof(compat_long_t), 281 compat_ptr(data)); 282 283 case PTRACE_GETFPREGS: 284 case PTRACE_SETFPREGS: 285 case PTRACE_GETVRREGS: 286 case PTRACE_SETVRREGS: 287 case PTRACE_GETVSRREGS: 288 case PTRACE_SETVSRREGS: 289 case PTRACE_GETREGS64: 290 case PTRACE_SETREGS64: 291 case PTRACE_KILL: 292 case PTRACE_SINGLESTEP: 293 case PTRACE_DETACH: 294 case PTRACE_SET_DEBUGREG: 295 case PTRACE_SYSCALL: 296 case PTRACE_CONT: 297 case PPC_PTRACE_GETHWDBGINFO: 298 case PPC_PTRACE_SETHWDEBUG: 299 case PPC_PTRACE_DELHWDEBUG: 300 ret = arch_ptrace(child, request, addr, data); 301 break; 302 303 default: 304 ret = compat_ptrace_request(child, request, addr, data); 305 break; 306 } 307 308 return ret; 309 } 310