diff options
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-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 */ |