diff options
-rw-r--r-- | arch/mips/kernel/ptrace.c | 108 |
1 files changed, 83 insertions, 25 deletions
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index efbd8df8b665..62e8ffd9370a 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c | |||
@@ -419,25 +419,36 @@ static int gpr64_set(struct task_struct *target, | |||
419 | 419 | ||
420 | #endif /* CONFIG_64BIT */ | 420 | #endif /* CONFIG_64BIT */ |
421 | 421 | ||
422 | static int fpr_get(struct task_struct *target, | 422 | /* |
423 | const struct user_regset *regset, | 423 | * Copy the floating-point context to the supplied NT_PRFPREG buffer, |
424 | unsigned int pos, unsigned int count, | 424 | * !CONFIG_CPU_HAS_MSA variant. FP context's general register slots |
425 | void *kbuf, void __user *ubuf) | 425 | * correspond 1:1 to buffer slots. |
426 | */ | ||
427 | static int fpr_get_fpa(struct task_struct *target, | ||
428 | unsigned int *pos, unsigned int *count, | ||
429 | void **kbuf, void __user **ubuf) | ||
426 | { | 430 | { |
427 | unsigned i; | 431 | return user_regset_copyout(pos, count, kbuf, ubuf, |
428 | int err; | 432 | &target->thread.fpu, |
429 | u64 fpr_val; | 433 | 0, sizeof(elf_fpregset_t)); |
430 | 434 | } | |
431 | /* XXX fcr31 */ | ||
432 | 435 | ||
433 | if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) | 436 | /* |
434 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 437 | * Copy the floating-point context to the supplied NT_PRFPREG buffer, |
435 | &target->thread.fpu, | 438 | * CONFIG_CPU_HAS_MSA variant. Only lower 64 bits of FP context's |
436 | 0, sizeof(elf_fpregset_t)); | 439 | * general register slots are copied to buffer slots. |
440 | */ | ||
441 | static int fpr_get_msa(struct task_struct *target, | ||
442 | unsigned int *pos, unsigned int *count, | ||
443 | void **kbuf, void __user **ubuf) | ||
444 | { | ||
445 | unsigned int i; | ||
446 | u64 fpr_val; | ||
447 | int err; | ||
437 | 448 | ||
438 | for (i = 0; i < NUM_FPU_REGS; i++) { | 449 | for (i = 0; i < NUM_FPU_REGS; i++) { |
439 | fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0); | 450 | fpr_val = get_fpr64(&target->thread.fpu.fpr[i], 0); |
440 | err = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 451 | err = user_regset_copyout(pos, count, kbuf, ubuf, |
441 | &fpr_val, i * sizeof(elf_fpreg_t), | 452 | &fpr_val, i * sizeof(elf_fpreg_t), |
442 | (i + 1) * sizeof(elf_fpreg_t)); | 453 | (i + 1) * sizeof(elf_fpreg_t)); |
443 | if (err) | 454 | if (err) |
@@ -447,27 +458,54 @@ static int fpr_get(struct task_struct *target, | |||
447 | return 0; | 458 | return 0; |
448 | } | 459 | } |
449 | 460 | ||
450 | static int fpr_set(struct task_struct *target, | 461 | /* Copy the floating-point context to the supplied NT_PRFPREG buffer. */ |
462 | static int fpr_get(struct task_struct *target, | ||
451 | const struct user_regset *regset, | 463 | const struct user_regset *regset, |
452 | unsigned int pos, unsigned int count, | 464 | unsigned int pos, unsigned int count, |
453 | const void *kbuf, const void __user *ubuf) | 465 | void *kbuf, void __user *ubuf) |
454 | { | 466 | { |
455 | unsigned i; | ||
456 | int err; | 467 | int err; |
457 | u64 fpr_val; | ||
458 | 468 | ||
459 | /* XXX fcr31 */ | 469 | /* XXX fcr31 */ |
460 | 470 | ||
461 | init_fp_ctx(target); | 471 | if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t)) |
472 | err = fpr_get_fpa(target, &pos, &count, &kbuf, &ubuf); | ||
473 | else | ||
474 | err = fpr_get_msa(target, &pos, &count, &kbuf, &ubuf); | ||
475 | |||
476 | return err; | ||
477 | } | ||
462 | 478 | ||
463 | if (sizeof(target->thread.fpu.fpr[i]) == sizeof(elf_fpreg_t)) | 479 | /* |
464 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 480 | * Copy the supplied NT_PRFPREG buffer to the floating-point context, |
465 | &target->thread.fpu, | 481 | * !CONFIG_CPU_HAS_MSA variant. Buffer slots correspond 1:1 to FP |
466 | 0, sizeof(elf_fpregset_t)); | 482 | * context's general register slots. |
483 | */ | ||
484 | static int fpr_set_fpa(struct task_struct *target, | ||
485 | unsigned int *pos, unsigned int *count, | ||
486 | const void **kbuf, const void __user **ubuf) | ||
487 | { | ||
488 | return user_regset_copyin(pos, count, kbuf, ubuf, | ||
489 | &target->thread.fpu, | ||
490 | 0, sizeof(elf_fpregset_t)); | ||
491 | } | ||
492 | |||
493 | /* | ||
494 | * Copy the supplied NT_PRFPREG buffer to the floating-point context, | ||
495 | * CONFIG_CPU_HAS_MSA variant. Buffer slots are copied to lower 64 | ||
496 | * bits only of FP context's general register slots. | ||
497 | */ | ||
498 | static int fpr_set_msa(struct task_struct *target, | ||
499 | unsigned int *pos, unsigned int *count, | ||
500 | const void **kbuf, const void __user **ubuf) | ||
501 | { | ||
502 | unsigned int i; | ||
503 | u64 fpr_val; | ||
504 | int err; | ||
467 | 505 | ||
468 | BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t)); | 506 | BUILD_BUG_ON(sizeof(fpr_val) != sizeof(elf_fpreg_t)); |
469 | for (i = 0; i < NUM_FPU_REGS && count >= sizeof(elf_fpreg_t); i++) { | 507 | for (i = 0; i < NUM_FPU_REGS && *count >= sizeof(elf_fpreg_t); i++) { |
470 | err = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 508 | err = user_regset_copyin(pos, count, kbuf, ubuf, |
471 | &fpr_val, i * sizeof(elf_fpreg_t), | 509 | &fpr_val, i * sizeof(elf_fpreg_t), |
472 | (i + 1) * sizeof(elf_fpreg_t)); | 510 | (i + 1) * sizeof(elf_fpreg_t)); |
473 | if (err) | 511 | if (err) |
@@ -478,6 +516,26 @@ static int fpr_set(struct task_struct *target, | |||
478 | return 0; | 516 | return 0; |
479 | } | 517 | } |
480 | 518 | ||
519 | /* Copy the supplied NT_PRFPREG buffer to the floating-point context. */ | ||
520 | static int fpr_set(struct task_struct *target, | ||
521 | const struct user_regset *regset, | ||
522 | unsigned int pos, unsigned int count, | ||
523 | const void *kbuf, const void __user *ubuf) | ||
524 | { | ||
525 | int err; | ||
526 | |||
527 | /* XXX fcr31 */ | ||
528 | |||
529 | init_fp_ctx(target); | ||
530 | |||
531 | if (sizeof(target->thread.fpu.fpr[0]) == sizeof(elf_fpreg_t)) | ||
532 | err = fpr_set_fpa(target, &pos, &count, &kbuf, &ubuf); | ||
533 | else | ||
534 | err = fpr_set_msa(target, &pos, &count, &kbuf, &ubuf); | ||
535 | |||
536 | return err; | ||
537 | } | ||
538 | |||
481 | enum mips_regset { | 539 | enum mips_regset { |
482 | REGSET_GPR, | 540 | REGSET_GPR, |
483 | REGSET_FPR, | 541 | REGSET_FPR, |