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