aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc')
-rw-r--r--arch/sparc/kernel/ptrace.c115
1 files changed, 47 insertions, 68 deletions
diff --git a/arch/sparc/kernel/ptrace.c b/arch/sparc/kernel/ptrace.c
index 1c0d5363f720..5b54f11f4e59 100644
--- a/arch/sparc/kernel/ptrace.c
+++ b/arch/sparc/kernel/ptrace.c
@@ -322,54 +322,39 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
322long arch_ptrace(struct task_struct *child, long request, long addr, long data) 322long arch_ptrace(struct task_struct *child, long request, long addr, long data)
323{ 323{
324 unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4]; 324 unsigned long addr2 = current->thread.kregs->u_regs[UREG_I4];
325 int i, ret; 325 const struct user_regset_view *view;
326 int ret;
327
328 view = task_user_regset_view(child);
326 329
327 switch(request) { 330 switch(request) {
328 case PTRACE_GETREGS: { 331 case PTRACE_GETREGS: {
329 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 332 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
330 struct pt_regs *cregs = child->thread.kregs;
331
332 ret = -EFAULT;
333 if (!access_ok(VERIFY_WRITE, pregs, sizeof(struct pt_regs)))
334 break;
335 333
336 __put_user(cregs->psr, (&pregs->psr)); 334 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
337 __put_user(cregs->pc, (&pregs->pc)); 335 32 * sizeof(u32),
338 __put_user(cregs->npc, (&pregs->npc)); 336 4 * sizeof(u32),
339 __put_user(cregs->y, (&pregs->y)); 337 &pregs->psr);
340 for (i = 1; i < 16; i++) 338 if (!ret)
341 __put_user(cregs->u_regs[i], &pregs->u_regs[i - 1]); 339 copy_regset_to_user(child, view, REGSET_GENERAL,
342 ret = 0; 340 1 * sizeof(u32),
341 15 * sizeof(u32),
342 &pregs->u_regs[0]);
343 break; 343 break;
344 } 344 }
345 345
346 case PTRACE_SETREGS: { 346 case PTRACE_SETREGS: {
347 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 347 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
348 struct pt_regs *cregs = child->thread.kregs;
349 unsigned long psr, pc, npc, y;
350
351 /* Must be careful, tracing process can only set certain
352 * bits in the psr.
353 */
354 ret = -EFAULT;
355 if (!access_ok(VERIFY_READ, pregs, sizeof(struct pt_regs)))
356 break;
357 348
358 __get_user(psr, (&pregs->psr)); 349 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
359 __get_user(pc, (&pregs->pc)); 350 32 * sizeof(u32),
360 __get_user(npc, (&pregs->npc)); 351 4 * sizeof(u32),
361 __get_user(y, (&pregs->y)); 352 &pregs->psr);
362 psr &= PSR_ICC; 353 if (!ret)
363 cregs->psr &= ~PSR_ICC; 354 copy_regset_from_user(child, view, REGSET_GENERAL,
364 cregs->psr |= psr; 355 1 * sizeof(u32),
365 if (!((pc | npc) & 3)) { 356 15 * sizeof(u32),
366 cregs->pc = pc; 357 &pregs->u_regs[0]);
367 cregs->npc =npc;
368 }
369 cregs->y = y;
370 for (i = 1; i < 16; i++)
371 __get_user(cregs->u_regs[i], &pregs->u_regs[i-1]);
372 ret = 0;
373 break; 358 break;
374 } 359 }
375 360
@@ -387,23 +372,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
387 }; 372 };
388 struct fps __user *fps = (struct fps __user *) addr; 373 struct fps __user *fps = (struct fps __user *) addr;
389 374
390 ret = -EFAULT; 375 ret = copy_regset_to_user(child, view, REGSET_FP,
391 if (!access_ok(VERIFY_WRITE, fps, sizeof(struct fps))) 376 0 * sizeof(u32),
392 break; 377 32 * sizeof(u32),
393 378 &fps->regs[0]);
394 for (i = 0; i < 32; i++) 379 if (!ret)
395 __put_user(child->thread.float_regs[i], &fps->regs[i]); 380 ret = copy_regset_to_user(child, view, REGSET_FP,
396 __put_user(child->thread.fsr, (&fps->fsr)); 381 33 * sizeof(u32),
397 __put_user(child->thread.fpqdepth, (&fps->fpqd)); 382 1 * sizeof(u32),
398 __put_user(0, (&fps->flags)); 383 &fps->fsr);
399 __put_user(0, (&fps->extra)); 384
400 for (i = 0; i < 16; i++) { 385 if (!ret) {
401 __put_user(child->thread.fpqueue[i].insn_addr, 386 if (__put_user(0, &fps->fpqd) ||
402 (&fps->fpq[i].insnaddr)); 387 __put_user(0, &fps->flags) ||
403 __put_user(child->thread.fpqueue[i].insn, 388 __put_user(0, &fps->extra) ||
404 &fps->fpq[i].insn); 389 clear_user(fps->fpq, sizeof(fps->fpq)))
390 ret = -EFAULT;
405 } 391 }
406 ret = 0;
407 break; 392 break;
408 } 393 }
409 394
@@ -421,21 +406,15 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
421 }; 406 };
422 struct fps __user *fps = (struct fps __user *) addr; 407 struct fps __user *fps = (struct fps __user *) addr;
423 408
424 ret = -EFAULT; 409 ret = copy_regset_from_user(child, view, REGSET_FP,
425 if (!access_ok(VERIFY_READ, fps, sizeof(struct fps))) 410 0 * sizeof(u32),
426 break; 411 32 * sizeof(u32),
427 412 &fps->regs[0]);
428 copy_from_user(&child->thread.float_regs[0], &fps->regs[0], 413 if (!ret)
429 (32 * sizeof(unsigned long))); 414 ret = copy_regset_from_user(child, view, REGSET_FP,
430 __get_user(child->thread.fsr, (&fps->fsr)); 415 33 * sizeof(u32),
431 __get_user(child->thread.fpqdepth, (&fps->fpqd)); 416 1 * sizeof(u32),
432 for (i = 0; i < 16; i++) { 417 &fps->fsr);
433 __get_user(child->thread.fpqueue[i].insn_addr,
434 (&fps->fpq[i].insnaddr));
435 __get_user(child->thread.fpqueue[i].insn,
436 &fps->fpq[i].insn);
437 }
438 ret = 0;
439 break; 418 break;
440 } 419 }
441 420