diff options
author | Roland McGrath <roland@redhat.com> | 2007-12-20 06:58:36 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-02-07 04:40:18 -0500 |
commit | c391cd0093a2c86a6d1bc256198caad29fff0f60 (patch) | |
tree | 69673f98aaed497023446be1634bcb05c3431209 /arch/powerpc | |
parent | 01e31dbabc020bf82e7e5359c031a550daafb8ff (diff) |
[POWERPC] Use regset code for PTRACE_*REGS* requests
This replaces all the code for powerpc PTRACE_*REGS* requests with
simple calls to copy_regset_from_user and copy_regset_to_user. All
the ptrace formats are either the whole corresponding user_regset
format (core dump format) or a leading subset of it, so we can get
rid of all the remaining embedded knowledge of both those layouts
and of the internal data structures they correspond to. Only the
user_regset accessors need to implement that.
Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/ptrace.c | 234 |
1 files changed, 59 insertions, 175 deletions
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 60de9ee3701d..2c1ee2cf9419 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -237,24 +237,6 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset, | |||
237 | &target->thread.fpr, 0, -1); | 237 | &target->thread.fpr, 0, -1); |
238 | } | 238 | } |
239 | 239 | ||
240 | static int get_fpregs(void __user *data, struct task_struct *task, | ||
241 | int has_fpscr) | ||
242 | { | ||
243 | unsigned int count = has_fpscr ? 33 : 32; | ||
244 | if (!access_ok(VERIFY_WRITE, data, count * sizeof(double))) | ||
245 | return -EFAULT; | ||
246 | return fpr_get(task, NULL, 0, count * sizeof(double), NULL, data); | ||
247 | } | ||
248 | |||
249 | static int set_fpregs(void __user *data, struct task_struct *task, | ||
250 | int has_fpscr) | ||
251 | { | ||
252 | unsigned int count = has_fpscr ? 33 : 32; | ||
253 | if (!access_ok(VERIFY_READ, data, count * sizeof(double))) | ||
254 | return -EFAULT; | ||
255 | return fpr_set(task, NULL, 0, count * sizeof(double), NULL, data); | ||
256 | } | ||
257 | |||
258 | 240 | ||
259 | #ifdef CONFIG_ALTIVEC | 241 | #ifdef CONFIG_ALTIVEC |
260 | /* | 242 | /* |
@@ -339,31 +321,6 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset, | |||
339 | 321 | ||
340 | return ret; | 322 | return ret; |
341 | } | 323 | } |
342 | |||
343 | /* | ||
344 | * Get contents of AltiVec register state in task TASK | ||
345 | */ | ||
346 | static int get_vrregs(unsigned long __user *data, struct task_struct *task) | ||
347 | { | ||
348 | if (!access_ok(VERIFY_WRITE, data, | ||
349 | 33 * sizeof(vector128) + sizeof(u32))) | ||
350 | return -EFAULT; | ||
351 | |||
352 | return vr_get(task, NULL, 0, 33 * sizeof(vector128) + sizeof(u32), | ||
353 | NULL, data); | ||
354 | } | ||
355 | |||
356 | /* | ||
357 | * Write contents of AltiVec register state into task TASK. | ||
358 | */ | ||
359 | static int set_vrregs(struct task_struct *task, unsigned long __user *data) | ||
360 | { | ||
361 | if (!access_ok(VERIFY_READ, data, 33 * sizeof(vector128) + sizeof(u32))) | ||
362 | return -EFAULT; | ||
363 | |||
364 | return vr_set(task, NULL, 0, 33 * sizeof(vector128) + sizeof(u32), | ||
365 | NULL, data); | ||
366 | } | ||
367 | #endif /* CONFIG_ALTIVEC */ | 324 | #endif /* CONFIG_ALTIVEC */ |
368 | 325 | ||
369 | #ifdef CONFIG_SPE | 326 | #ifdef CONFIG_SPE |
@@ -430,28 +387,6 @@ static int evr_set(struct task_struct *target, const struct user_regset *regset, | |||
430 | 387 | ||
431 | return ret; | 388 | return ret; |
432 | } | 389 | } |
433 | |||
434 | /* | ||
435 | * Get contents of SPE register state in task TASK. | ||
436 | */ | ||
437 | static int get_evrregs(unsigned long __user *data, struct task_struct *task) | ||
438 | { | ||
439 | if (!access_ok(VERIFY_WRITE, data, 35 * sizeof(u32))) | ||
440 | return -EFAULT; | ||
441 | |||
442 | return evr_get(task, NULL, 0, 35 * sizeof(u32), NULL, data); | ||
443 | } | ||
444 | |||
445 | /* | ||
446 | * Write contents of SPE register state into task TASK. | ||
447 | */ | ||
448 | static int set_evrregs(struct task_struct *task, unsigned long *data) | ||
449 | { | ||
450 | if (!access_ok(VERIFY_READ, data, 35 * sizeof(u32))) | ||
451 | return -EFAULT; | ||
452 | |||
453 | return evr_set(task, NULL, 0, 35 * sizeof(u32), NULL, data); | ||
454 | } | ||
455 | #endif /* CONFIG_SPE */ | 390 | #endif /* CONFIG_SPE */ |
456 | 391 | ||
457 | 392 | ||
@@ -736,55 +671,29 @@ void ptrace_disable(struct task_struct *child) | |||
736 | static long arch_ptrace_old(struct task_struct *child, long request, long addr, | 671 | static long arch_ptrace_old(struct task_struct *child, long request, long addr, |
737 | long data) | 672 | long data) |
738 | { | 673 | { |
739 | int ret = -EPERM; | 674 | switch (request) { |
740 | 675 | case PPC_PTRACE_GETREGS: /* Get GPRs 0 - 31. */ | |
741 | switch(request) { | 676 | return copy_regset_to_user(child, &user_ppc_native_view, |
742 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 677 | REGSET_GPR, 0, 32 * sizeof(long), |
743 | int i; | 678 | (void __user *) data); |
744 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 679 | |
745 | unsigned long __user *tmp = (unsigned long __user *)addr; | 680 | case PPC_PTRACE_SETREGS: /* Set GPRs 0 - 31. */ |
746 | 681 | return copy_regset_from_user(child, &user_ppc_native_view, | |
747 | CHECK_FULL_REGS(child->thread.regs); | 682 | REGSET_GPR, 0, 32 * sizeof(long), |
748 | for (i = 0; i < 32; i++) { | 683 | (const void __user *) data); |
749 | ret = put_user(*reg, tmp); | 684 | |
750 | if (ret) | 685 | case PPC_PTRACE_GETFPREGS: /* Get FPRs 0 - 31. */ |
751 | break; | 686 | return copy_regset_to_user(child, &user_ppc_native_view, |
752 | reg++; | 687 | REGSET_FPR, 0, 32 * sizeof(double), |
753 | tmp++; | 688 | (void __user *) data); |
754 | } | 689 | |
755 | break; | 690 | case PPC_PTRACE_SETFPREGS: /* Set FPRs 0 - 31. */ |
756 | } | 691 | return copy_regset_from_user(child, &user_ppc_native_view, |
757 | 692 | REGSET_FPR, 0, 32 * sizeof(double), | |
758 | case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */ | 693 | (const void __user *) data); |
759 | int i; | ||
760 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | ||
761 | unsigned long __user *tmp = (unsigned long __user *)addr; | ||
762 | |||
763 | CHECK_FULL_REGS(child->thread.regs); | ||
764 | for (i = 0; i < 32; i++) { | ||
765 | ret = get_user(*reg, tmp); | ||
766 | if (ret) | ||
767 | break; | ||
768 | reg++; | ||
769 | tmp++; | ||
770 | } | ||
771 | break; | ||
772 | } | ||
773 | |||
774 | case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */ | ||
775 | flush_fp_to_thread(child); | ||
776 | ret = get_fpregs((void __user *)addr, child, 0); | ||
777 | break; | ||
778 | } | ||
779 | |||
780 | case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */ | ||
781 | flush_fp_to_thread(child); | ||
782 | ret = set_fpregs((void __user *)addr, child, 0); | ||
783 | break; | ||
784 | } | 694 | } |
785 | 695 | ||
786 | } | 696 | return -EPERM; |
787 | return ret; | ||
788 | } | 697 | } |
789 | 698 | ||
790 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) | 699 | long arch_ptrace(struct task_struct *child, long request, long addr, long data) |
@@ -875,85 +784,60 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
875 | #ifdef CONFIG_PPC64 | 784 | #ifdef CONFIG_PPC64 |
876 | case PTRACE_GETREGS64: | 785 | case PTRACE_GETREGS64: |
877 | #endif | 786 | #endif |
878 | case PTRACE_GETREGS: { /* Get all pt_regs from the child. */ | 787 | case PTRACE_GETREGS: /* Get all pt_regs from the child. */ |
879 | int ui; | 788 | return copy_regset_to_user(child, &user_ppc_native_view, |
880 | if (!access_ok(VERIFY_WRITE, (void __user *)data, | 789 | REGSET_GPR, |
881 | sizeof(struct pt_regs))) { | 790 | 0, sizeof(struct pt_regs), |
882 | ret = -EIO; | 791 | (void __user *) data); |
883 | break; | ||
884 | } | ||
885 | CHECK_FULL_REGS(child->thread.regs); | ||
886 | ret = 0; | ||
887 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | ||
888 | ret |= __put_user(ptrace_get_reg(child, ui), | ||
889 | (unsigned long __user *) data); | ||
890 | data += sizeof(long); | ||
891 | } | ||
892 | break; | ||
893 | } | ||
894 | 792 | ||
895 | #ifdef CONFIG_PPC64 | 793 | #ifdef CONFIG_PPC64 |
896 | case PTRACE_SETREGS64: | 794 | case PTRACE_SETREGS64: |
897 | #endif | 795 | #endif |
898 | case PTRACE_SETREGS: { /* Set all gp regs in the child. */ | 796 | case PTRACE_SETREGS: /* Set all gp regs in the child. */ |
899 | unsigned long tmp; | 797 | return copy_regset_from_user(child, &user_ppc_native_view, |
900 | int ui; | 798 | REGSET_GPR, |
901 | if (!access_ok(VERIFY_READ, (void __user *)data, | 799 | 0, sizeof(struct pt_regs), |
902 | sizeof(struct pt_regs))) { | 800 | (const void __user *) data); |
903 | ret = -EIO; | 801 | |
904 | break; | 802 | case PTRACE_GETFPREGS: /* Get the child FPU state (FPR0...31 + FPSCR) */ |
905 | } | 803 | return copy_regset_to_user(child, &user_ppc_native_view, |
906 | CHECK_FULL_REGS(child->thread.regs); | 804 | REGSET_FPR, |
907 | ret = 0; | 805 | 0, sizeof(elf_fpregset_t), |
908 | for (ui = 0; ui < PT_REGS_COUNT; ui ++) { | 806 | (void __user *) data); |
909 | ret = __get_user(tmp, (unsigned long __user *) data); | 807 | |
910 | if (ret) | 808 | case PTRACE_SETFPREGS: /* Set the child FPU state (FPR0...31 + FPSCR) */ |
911 | break; | 809 | return copy_regset_from_user(child, &user_ppc_native_view, |
912 | ptrace_put_reg(child, ui, tmp); | 810 | REGSET_FPR, |
913 | data += sizeof(long); | 811 | 0, sizeof(elf_fpregset_t), |
914 | } | 812 | (const void __user *) data); |
915 | break; | ||
916 | } | ||
917 | |||
918 | case PTRACE_GETFPREGS: { /* Get the child FPU state (FPR0...31 + FPSCR) */ | ||
919 | flush_fp_to_thread(child); | ||
920 | ret = get_fpregs((void __user *)data, child, 1); | ||
921 | break; | ||
922 | } | ||
923 | |||
924 | case PTRACE_SETFPREGS: { /* Set the child FPU state (FPR0...31 + FPSCR) */ | ||
925 | flush_fp_to_thread(child); | ||
926 | ret = set_fpregs((void __user *)data, child, 1); | ||
927 | break; | ||
928 | } | ||
929 | 813 | ||
930 | #ifdef CONFIG_ALTIVEC | 814 | #ifdef CONFIG_ALTIVEC |
931 | case PTRACE_GETVRREGS: | 815 | case PTRACE_GETVRREGS: |
932 | /* Get the child altivec register state. */ | 816 | return copy_regset_to_user(child, &user_ppc_native_view, |
933 | flush_altivec_to_thread(child); | 817 | REGSET_VMX, |
934 | ret = get_vrregs((unsigned long __user *)data, child); | 818 | 0, (33 * sizeof(vector128) + |
935 | break; | 819 | sizeof(u32)), |
820 | (void __user *) data); | ||
936 | 821 | ||
937 | case PTRACE_SETVRREGS: | 822 | case PTRACE_SETVRREGS: |
938 | /* Set the child altivec register state. */ | 823 | return copy_regset_from_user(child, &user_ppc_native_view, |
939 | flush_altivec_to_thread(child); | 824 | REGSET_VMX, |
940 | ret = set_vrregs(child, (unsigned long __user *)data); | 825 | 0, (33 * sizeof(vector128) + |
941 | break; | 826 | sizeof(u32)), |
827 | (const void __user *) data); | ||
942 | #endif | 828 | #endif |
943 | #ifdef CONFIG_SPE | 829 | #ifdef CONFIG_SPE |
944 | case PTRACE_GETEVRREGS: | 830 | case PTRACE_GETEVRREGS: |
945 | /* Get the child spe register state. */ | 831 | /* Get the child spe register state. */ |
946 | flush_spe_to_thread(child); | 832 | return copy_regset_to_user(child, &user_ppc_native_view, |
947 | ret = get_evrregs((unsigned long __user *)data, child); | 833 | REGSET_SPE, 0, 35 * sizeof(u32), |
948 | break; | 834 | (void __user *) data); |
949 | 835 | ||
950 | case PTRACE_SETEVRREGS: | 836 | case PTRACE_SETEVRREGS: |
951 | /* Set the child spe register state. */ | 837 | /* Set the child spe register state. */ |
952 | /* this is to clear the MSR_SPE bit to force a reload | 838 | return copy_regset_from_user(child, &user_ppc_native_view, |
953 | * of register state from memory */ | 839 | REGSET_SPE, 0, 35 * sizeof(u32), |
954 | flush_spe_to_thread(child); | 840 | (const void __user *) data); |
955 | ret = set_evrregs(child, (unsigned long __user *)data); | ||
956 | break; | ||
957 | #endif | 841 | #endif |
958 | 842 | ||
959 | /* Old reverse args ptrace callss */ | 843 | /* Old reverse args ptrace callss */ |