0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/sched.h>
0015 #include <linux/mm.h>
0016 #include <linux/errno.h>
0017 #include <linux/ptrace.h>
0018 #include <linux/user.h>
0019 #include <linux/smp.h>
0020 #include <linux/security.h>
0021 #include <linux/signal.h>
0022 #include <linux/regset.h>
0023 #include <linux/elf.h>
0024
0025 #include <linux/uaccess.h>
0026 #include <asm/cacheflush.h>
0027
0028 #include "kernel.h"
0029
0030
0031
0032
0033
0034
0035
0036
0037 void ptrace_disable(struct task_struct *child)
0038 {
0039
0040 }
0041
0042 enum sparc_regset {
0043 REGSET_GENERAL,
0044 REGSET_FP,
0045 };
0046
0047 static int regwindow32_get(struct task_struct *target,
0048 const struct pt_regs *regs,
0049 u32 *uregs)
0050 {
0051 unsigned long reg_window = regs->u_regs[UREG_I6];
0052 int size = 16 * sizeof(u32);
0053
0054 if (target == current) {
0055 if (copy_from_user(uregs, (void __user *)reg_window, size))
0056 return -EFAULT;
0057 } else {
0058 if (access_process_vm(target, reg_window, uregs, size,
0059 FOLL_FORCE) != size)
0060 return -EFAULT;
0061 }
0062 return 0;
0063 }
0064
0065 static int regwindow32_set(struct task_struct *target,
0066 const struct pt_regs *regs,
0067 u32 *uregs)
0068 {
0069 unsigned long reg_window = regs->u_regs[UREG_I6];
0070 int size = 16 * sizeof(u32);
0071
0072 if (target == current) {
0073 if (copy_to_user((void __user *)reg_window, uregs, size))
0074 return -EFAULT;
0075 } else {
0076 if (access_process_vm(target, reg_window, uregs, size,
0077 FOLL_FORCE | FOLL_WRITE) != size)
0078 return -EFAULT;
0079 }
0080 return 0;
0081 }
0082
0083 static int genregs32_get(struct task_struct *target,
0084 const struct user_regset *regset,
0085 struct membuf to)
0086 {
0087 const struct pt_regs *regs = target->thread.kregs;
0088 u32 uregs[16];
0089
0090 if (target == current)
0091 flush_user_windows();
0092
0093 membuf_write(&to, regs->u_regs, 16 * sizeof(u32));
0094 if (!to.left)
0095 return 0;
0096 if (regwindow32_get(target, regs, uregs))
0097 return -EFAULT;
0098 membuf_write(&to, uregs, 16 * sizeof(u32));
0099 membuf_store(&to, regs->psr);
0100 membuf_store(&to, regs->pc);
0101 membuf_store(&to, regs->npc);
0102 membuf_store(&to, regs->y);
0103 return membuf_zero(&to, 2 * sizeof(u32));
0104 }
0105
0106 static int genregs32_set(struct task_struct *target,
0107 const struct user_regset *regset,
0108 unsigned int pos, unsigned int count,
0109 const void *kbuf, const void __user *ubuf)
0110 {
0111 struct pt_regs *regs = target->thread.kregs;
0112 u32 uregs[16];
0113 u32 psr;
0114 int ret;
0115
0116 if (target == current)
0117 flush_user_windows();
0118
0119 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0120 regs->u_regs,
0121 0, 16 * sizeof(u32));
0122 if (ret || !count)
0123 return ret;
0124
0125 if (regwindow32_get(target, regs, uregs))
0126 return -EFAULT;
0127 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0128 uregs,
0129 16 * sizeof(u32), 32 * sizeof(u32));
0130 if (ret)
0131 return ret;
0132 if (regwindow32_set(target, regs, uregs))
0133 return -EFAULT;
0134 if (!count)
0135 return 0;
0136
0137 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0138 &psr,
0139 32 * sizeof(u32), 33 * sizeof(u32));
0140 if (ret)
0141 return ret;
0142 regs->psr = (regs->psr & ~(PSR_ICC | PSR_SYSCALL)) |
0143 (psr & (PSR_ICC | PSR_SYSCALL));
0144 if (!count)
0145 return 0;
0146 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0147 ®s->pc,
0148 33 * sizeof(u32), 34 * sizeof(u32));
0149 if (ret || !count)
0150 return ret;
0151 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0152 ®s->npc,
0153 34 * sizeof(u32), 35 * sizeof(u32));
0154 if (ret || !count)
0155 return ret;
0156 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0157 ®s->y,
0158 35 * sizeof(u32), 36 * sizeof(u32));
0159 if (ret || !count)
0160 return ret;
0161 return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0162 36 * sizeof(u32), 38 * sizeof(u32));
0163 }
0164
0165 static int fpregs32_get(struct task_struct *target,
0166 const struct user_regset *regset,
0167 struct membuf to)
0168 {
0169 #if 0
0170 if (target == current)
0171 save_and_clear_fpu();
0172 #endif
0173
0174 membuf_write(&to, target->thread.float_regs, 32 * sizeof(u32));
0175 membuf_zero(&to, sizeof(u32));
0176 membuf_write(&to, &target->thread.fsr, sizeof(u32));
0177 membuf_store(&to, (u32)((1 << 8) | (8 << 16)));
0178 return membuf_zero(&to, 64 * sizeof(u32));
0179 }
0180
0181 static int fpregs32_set(struct task_struct *target,
0182 const struct user_regset *regset,
0183 unsigned int pos, unsigned int count,
0184 const void *kbuf, const void __user *ubuf)
0185 {
0186 unsigned long *fpregs = target->thread.float_regs;
0187 int ret;
0188
0189 #if 0
0190 if (target == current)
0191 save_and_clear_fpu();
0192 #endif
0193 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0194 fpregs,
0195 0, 32 * sizeof(u32));
0196 if (!ret)
0197 user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0198 32 * sizeof(u32),
0199 33 * sizeof(u32));
0200 if (!ret)
0201 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0202 &target->thread.fsr,
0203 33 * sizeof(u32),
0204 34 * sizeof(u32));
0205 if (!ret)
0206 ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
0207 34 * sizeof(u32), -1);
0208 return ret;
0209 }
0210
0211 static const struct user_regset sparc32_regsets[] = {
0212
0213
0214
0215
0216
0217
0218
0219 [REGSET_GENERAL] = {
0220 .core_note_type = NT_PRSTATUS,
0221 .n = 38,
0222 .size = sizeof(u32), .align = sizeof(u32),
0223 .regset_get = genregs32_get, .set = genregs32_set
0224 },
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235 [REGSET_FP] = {
0236 .core_note_type = NT_PRFPREG,
0237 .n = 99,
0238 .size = sizeof(u32), .align = sizeof(u32),
0239 .regset_get = fpregs32_get, .set = fpregs32_set
0240 },
0241 };
0242
0243 static int getregs_get(struct task_struct *target,
0244 const struct user_regset *regset,
0245 struct membuf to)
0246 {
0247 const struct pt_regs *regs = target->thread.kregs;
0248
0249 if (target == current)
0250 flush_user_windows();
0251
0252 membuf_store(&to, regs->psr);
0253 membuf_store(&to, regs->pc);
0254 membuf_store(&to, regs->npc);
0255 membuf_store(&to, regs->y);
0256 return membuf_write(&to, regs->u_regs + 1, 15 * sizeof(u32));
0257 }
0258
0259 static int setregs_set(struct task_struct *target,
0260 const struct user_regset *regset,
0261 unsigned int pos, unsigned int count,
0262 const void *kbuf, const void __user *ubuf)
0263 {
0264 struct pt_regs *regs = target->thread.kregs;
0265 u32 v[4];
0266 int ret;
0267
0268 if (target == current)
0269 flush_user_windows();
0270
0271 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0272 v,
0273 0, 4 * sizeof(u32));
0274 if (ret)
0275 return ret;
0276 regs->psr = (regs->psr & ~(PSR_ICC | PSR_SYSCALL)) |
0277 (v[0] & (PSR_ICC | PSR_SYSCALL));
0278 regs->pc = v[1];
0279 regs->npc = v[2];
0280 regs->y = v[3];
0281 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0282 regs->u_regs + 1,
0283 4 * sizeof(u32) , 19 * sizeof(u32));
0284 }
0285
0286 static int getfpregs_get(struct task_struct *target,
0287 const struct user_regset *regset,
0288 struct membuf to)
0289 {
0290 #if 0
0291 if (target == current)
0292 save_and_clear_fpu();
0293 #endif
0294 membuf_write(&to, &target->thread.float_regs, 32 * sizeof(u32));
0295 membuf_write(&to, &target->thread.fsr, sizeof(u32));
0296 return membuf_zero(&to, 35 * sizeof(u32));
0297 }
0298
0299 static int setfpregs_set(struct task_struct *target,
0300 const struct user_regset *regset,
0301 unsigned int pos, unsigned int count,
0302 const void *kbuf, const void __user *ubuf)
0303 {
0304 unsigned long *fpregs = target->thread.float_regs;
0305 int ret;
0306
0307 #if 0
0308 if (target == current)
0309 save_and_clear_fpu();
0310 #endif
0311 ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0312 fpregs,
0313 0, 32 * sizeof(u32));
0314 if (ret)
0315 return ret;
0316 return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
0317 &target->thread.fsr,
0318 32 * sizeof(u32),
0319 33 * sizeof(u32));
0320 }
0321
0322 static const struct user_regset ptrace32_regsets[] = {
0323 [REGSET_GENERAL] = {
0324 .n = 19, .size = sizeof(u32),
0325 .regset_get = getregs_get, .set = setregs_set,
0326 },
0327 [REGSET_FP] = {
0328 .n = 68, .size = sizeof(u32),
0329 .regset_get = getfpregs_get, .set = setfpregs_set,
0330 },
0331 };
0332
0333 static const struct user_regset_view ptrace32_view = {
0334 .regsets = ptrace32_regsets, .n = ARRAY_SIZE(ptrace32_regsets)
0335 };
0336
0337 static const struct user_regset_view user_sparc32_view = {
0338 .name = "sparc", .e_machine = EM_SPARC,
0339 .regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
0340 };
0341
0342 const struct user_regset_view *task_user_regset_view(struct task_struct *task)
0343 {
0344 return &user_sparc32_view;
0345 }
0346
0347 struct fps {
0348 unsigned long regs[32];
0349 unsigned long fsr;
0350 unsigned long flags;
0351 unsigned long extra;
0352 unsigned long fpqd;
0353 struct fq {
0354 unsigned long *insnaddr;
0355 unsigned long insn;
0356 } fpq[16];
0357 };
0358
0359 long arch_ptrace(struct task_struct *child, long request,
0360 unsigned long addr, unsigned long data)
0361 {
0362 unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
0363 void __user *addr2p;
0364 struct pt_regs __user *pregs;
0365 struct fps __user *fps;
0366 int ret;
0367
0368 addr2p = (void __user *) addr2;
0369 pregs = (struct pt_regs __user *) addr;
0370 fps = (struct fps __user *) addr;
0371
0372 switch(request) {
0373 case PTRACE_GETREGS: {
0374 ret = copy_regset_to_user(child, &ptrace32_view,
0375 REGSET_GENERAL, 0,
0376 19 * sizeof(u32),
0377 pregs);
0378 break;
0379 }
0380
0381 case PTRACE_SETREGS: {
0382 ret = copy_regset_from_user(child, &ptrace32_view,
0383 REGSET_GENERAL, 0,
0384 19 * sizeof(u32),
0385 pregs);
0386 break;
0387 }
0388
0389 case PTRACE_GETFPREGS: {
0390 ret = copy_regset_to_user(child, &ptrace32_view,
0391 REGSET_FP, 0,
0392 68 * sizeof(u32),
0393 fps);
0394 break;
0395 }
0396
0397 case PTRACE_SETFPREGS: {
0398 ret = copy_regset_from_user(child, &ptrace32_view,
0399 REGSET_FP, 0,
0400 33 * sizeof(u32),
0401 fps);
0402 break;
0403 }
0404
0405 case PTRACE_READTEXT:
0406 case PTRACE_READDATA:
0407 ret = ptrace_readdata(child, addr, addr2p, data);
0408
0409 if (ret == data)
0410 ret = 0;
0411 else if (ret >= 0)
0412 ret = -EIO;
0413 break;
0414
0415 case PTRACE_WRITETEXT:
0416 case PTRACE_WRITEDATA:
0417 ret = ptrace_writedata(child, addr2p, addr, data);
0418
0419 if (ret == data)
0420 ret = 0;
0421 else if (ret >= 0)
0422 ret = -EIO;
0423 break;
0424
0425 default:
0426 if (request == PTRACE_SPARC_DETACH)
0427 request = PTRACE_DETACH;
0428 ret = ptrace_request(child, request, addr, data);
0429 break;
0430 }
0431
0432 return ret;
0433 }
0434
0435 asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p)
0436 {
0437 int ret = 0;
0438
0439 if (test_thread_flag(TIF_SYSCALL_TRACE)) {
0440 if (syscall_exit_p)
0441 ptrace_report_syscall_exit(regs, 0);
0442 else
0443 ret = ptrace_report_syscall_entry(regs);
0444 }
0445
0446 return ret;
0447 }