diff options
author | Maciej W. Rozycki <macro@mips.com> | 2017-12-11 17:51:35 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2017-12-12 13:11:26 -0500 |
commit | a03fe72572c12e98f4173f8a535f32468e48b6ec (patch) | |
tree | 2361d979b2baec7d3bb0e05273ae7e065f71ad82 | |
parent | 17278a91e04f858155d54bee5528ba4fbcec6f87 (diff) |
MIPS: Factor out NT_PRFPREG regset access helpers
In preparation to fix a commit 72b22bbad1e7 ("MIPS: Don't assume 64-bit
FP registers for FP regset") FCSR access regression factor out
NT_PRFPREG regset access helpers for the non-MSA and the MSA variants
respectively, to avoid having to deal with excessive indentation in the
actual fix.
No functional change, however use `target->thread.fpu.fpr[0]' rather
than `target->thread.fpu.fpr[i]' for FGR holding type size determination
as there's no `i' variable to refer to anymore, and for the factored out
`i' variable declaration use `unsigned int' rather than `unsigned' as
its type, following the common style.
Signed-off-by: Maciej W. Rozycki <macro@mips.com>
Fixes: 72b22bbad1e7 ("MIPS: Don't assume 64-bit FP registers for FP regset")
Cc: James Hogan <james.hogan@mips.com>
Cc: Paul Burton <Paul.Burton@mips.com>
Cc: Alex Smith <alex@alex-smith.me.uk>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org # v3.15+
Patchwork: https://patchwork.linux-mips.org/patch/17925/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-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, |