0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/ptrace.h>
0021 #include <linux/regset.h>
0022 #include <linux/compat.h>
0023
0024 #include <asm/switch_to.h>
0025
0026 #include "ptrace-decl.h"
0027
0028
0029
0030
0031
0032
0033
0034 #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1)
0035 #define FPRHALF(i) (((i) - PT_FPR0) & 1)
0036 #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i)
0037
0038 long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
0039 compat_ulong_t caddr, compat_ulong_t cdata)
0040 {
0041 unsigned long addr = caddr;
0042 unsigned long data = cdata;
0043 int ret;
0044
0045 switch (request) {
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055 case PPC_PTRACE_PEEKTEXT_3264:
0056 case PPC_PTRACE_PEEKDATA_3264: {
0057 u32 tmp;
0058 int copied;
0059 u32 __user * addrOthers;
0060
0061 ret = -EIO;
0062
0063
0064 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
0065 break;
0066
0067 copied = ptrace_access_vm(child, (u64)addrOthers, &tmp,
0068 sizeof(tmp), FOLL_FORCE);
0069 if (copied != sizeof(tmp))
0070 break;
0071 ret = put_user(tmp, (u32 __user *)data);
0072 break;
0073 }
0074
0075
0076 case PTRACE_PEEKUSR: {
0077 int index;
0078 unsigned long tmp;
0079
0080 ret = -EIO;
0081
0082 index = (unsigned long) addr >> 2;
0083 if ((addr & 3) || (index > PT_FPSCR32))
0084 break;
0085
0086 if (index < PT_FPR0) {
0087 ret = ptrace_get_reg(child, index, &tmp);
0088 if (ret)
0089 break;
0090 } else {
0091 flush_fp_to_thread(child);
0092
0093
0094
0095
0096
0097 tmp = ((unsigned int *)child->thread.fp_state.fpr)
0098 [FPRINDEX(index)];
0099 }
0100 ret = put_user((unsigned int)tmp, (u32 __user *)data);
0101 break;
0102 }
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 case PPC_PTRACE_PEEKUSR_3264: {
0113 u32 index;
0114 u32 reg32bits;
0115 u64 tmp;
0116 u32 numReg;
0117 u32 part;
0118
0119 ret = -EIO;
0120
0121 index = (u64)addr >> 2;
0122 numReg = index / 2;
0123
0124 if (index % 2)
0125 part = 1;
0126 else
0127 part = 0;
0128
0129
0130
0131
0132 if ((addr & 3) || numReg > PT_FPSCR)
0133 break;
0134
0135 if (numReg >= PT_FPR0) {
0136 flush_fp_to_thread(child);
0137
0138 tmp = child->thread.fp_state.fpr[numReg - PT_FPR0][0];
0139 } else {
0140 unsigned long tmp2;
0141 ret = ptrace_get_reg(child, numReg, &tmp2);
0142 if (ret)
0143 break;
0144 tmp = tmp2;
0145 }
0146 reg32bits = ((u32*)&tmp)[part];
0147 ret = put_user(reg32bits, (u32 __user *)data);
0148 break;
0149 }
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160 case PPC_PTRACE_POKETEXT_3264:
0161 case PPC_PTRACE_POKEDATA_3264: {
0162 u32 tmp = data;
0163 u32 __user * addrOthers;
0164
0165
0166 ret = -EIO;
0167 if (get_user(addrOthers, (u32 __user * __user *)addr) != 0)
0168 break;
0169 ret = 0;
0170 if (ptrace_access_vm(child, (u64)addrOthers, &tmp,
0171 sizeof(tmp),
0172 FOLL_FORCE | FOLL_WRITE) == sizeof(tmp))
0173 break;
0174 ret = -EIO;
0175 break;
0176 }
0177
0178
0179 case PTRACE_POKEUSR: {
0180 unsigned long index;
0181
0182 ret = -EIO;
0183
0184 index = (unsigned long) addr >> 2;
0185 if ((addr & 3) || (index > PT_FPSCR32))
0186 break;
0187
0188 if (index < PT_FPR0) {
0189 ret = ptrace_put_reg(child, index, data);
0190 } else {
0191 flush_fp_to_thread(child);
0192
0193
0194
0195
0196
0197 ((unsigned int *)child->thread.fp_state.fpr)
0198 [FPRINDEX(index)] = data;
0199 ret = 0;
0200 }
0201 break;
0202 }
0203
0204
0205
0206
0207
0208
0209
0210
0211 case PPC_PTRACE_POKEUSR_3264: {
0212 u32 index;
0213 u32 numReg;
0214
0215 ret = -EIO;
0216
0217 index = (u64)addr >> 2;
0218 numReg = index / 2;
0219
0220
0221
0222
0223
0224 if ((addr & 3) || (numReg > PT_FPSCR))
0225 break;
0226 if (numReg < PT_FPR0) {
0227 unsigned long freg;
0228 ret = ptrace_get_reg(child, numReg, &freg);
0229 if (ret)
0230 break;
0231 if (index % 2)
0232 freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
0233 else
0234 freg = (freg & 0xfffffffful) | (data << 32);
0235 ret = ptrace_put_reg(child, numReg, freg);
0236 } else {
0237 u64 *tmp;
0238 flush_fp_to_thread(child);
0239
0240 tmp = &child->thread.fp_state.fpr[numReg - PT_FPR0][0];
0241
0242 ((u32 *)tmp)[index % 2] = data;
0243 ret = 0;
0244 }
0245 break;
0246 }
0247
0248 case PTRACE_GET_DEBUGREG: {
0249 #ifndef CONFIG_PPC_ADV_DEBUG_REGS
0250 unsigned long dabr_fake;
0251 #endif
0252 ret = -EINVAL;
0253
0254 if (addr > 0)
0255 break;
0256 #ifdef CONFIG_PPC_ADV_DEBUG_REGS
0257 ret = put_user(child->thread.debug.dac1, (u32 __user *)data);
0258 #else
0259 dabr_fake = (
0260 (child->thread.hw_brk[0].address & (~HW_BRK_TYPE_DABR)) |
0261 (child->thread.hw_brk[0].type & HW_BRK_TYPE_DABR));
0262 ret = put_user(dabr_fake, (u32 __user *)data);
0263 #endif
0264 break;
0265 }
0266
0267 case PTRACE_GETREGS:
0268 return copy_regset_to_user(
0269 child, task_user_regset_view(current), 0,
0270 0, PT_REGS_COUNT * sizeof(compat_long_t),
0271 compat_ptr(data));
0272
0273 case PTRACE_SETREGS:
0274 return copy_regset_from_user(
0275 child, task_user_regset_view(current), 0,
0276 0, PT_REGS_COUNT * sizeof(compat_long_t),
0277 compat_ptr(data));
0278
0279 case PTRACE_GETFPREGS:
0280 case PTRACE_SETFPREGS:
0281 case PTRACE_GETVRREGS:
0282 case PTRACE_SETVRREGS:
0283 case PTRACE_GETVSRREGS:
0284 case PTRACE_SETVSRREGS:
0285 case PTRACE_GETREGS64:
0286 case PTRACE_SETREGS64:
0287 case PTRACE_KILL:
0288 case PTRACE_SINGLESTEP:
0289 case PTRACE_DETACH:
0290 case PTRACE_SET_DEBUGREG:
0291 case PTRACE_SYSCALL:
0292 case PTRACE_CONT:
0293 case PPC_PTRACE_GETHWDBGINFO:
0294 case PPC_PTRACE_SETHWDEBUG:
0295 case PPC_PTRACE_DELHWDEBUG:
0296 ret = arch_ptrace(child, request, addr, data);
0297 break;
0298
0299 default:
0300 ret = compat_ptrace_request(child, request, addr, data);
0301 break;
0302 }
0303
0304 return ret;
0305 }