aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kernel/ptrace.c')
-rw-r--r--arch/powerpc/kernel/ptrace.c234
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
240static 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
249static 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 */
346static 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 */
359static 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 */
437static 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 */
448static 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)
736static long arch_ptrace_old(struct task_struct *child, long request, long addr, 671static 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
790long arch_ptrace(struct task_struct *child, long request, long addr, long data) 699long 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 */