diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sparc/kernel/ptrace.c | 115 |
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) | |||
322 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 322 | long 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 | ||