aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2007-12-20 06:58:36 -0500
committerPaul Mackerras <paulus@samba.org>2008-02-07 04:40:18 -0500
commitc391cd0093a2c86a6d1bc256198caad29fff0f60 (patch)
tree69673f98aaed497023446be1634bcb05c3431209 /arch/powerpc
parent01e31dbabc020bf82e7e5359c031a550daafb8ff (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.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 */