aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sparc64/kernel/ptrace.c209
1 files changed, 77 insertions, 132 deletions
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index 7e28ee36419e..51f012410f9d 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -687,11 +687,14 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
687long arch_ptrace(struct task_struct *child, long request, long addr, long data) 687long arch_ptrace(struct task_struct *child, long request, long addr, long data)
688{ 688{
689 long addr2 = task_pt_regs(current)->u_regs[UREG_I4]; 689 long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
690 int i, ret; 690 const struct user_regset_view *view;
691 int ret;
691 692
692 if (test_thread_flag(TIF_32BIT)) 693 if (test_thread_flag(TIF_32BIT))
693 addr2 &= 0xffffffffUL; 694 addr2 &= 0xffffffffUL;
694 695
696 view = task_user_regset_view(child);
697
695 switch(request) { 698 switch(request) {
696 case PTRACE_PEEKUSR: 699 case PTRACE_PEEKUSR:
697 ret = (addr != 0) ? -EIO : 0; 700 ret = (addr != 0) ? -EIO : 0;
@@ -746,111 +749,66 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
746 case PTRACE_GETREGS: { 749 case PTRACE_GETREGS: {
747 struct pt_regs32 __user *pregs = 750 struct pt_regs32 __user *pregs =
748 (struct pt_regs32 __user *) addr; 751 (struct pt_regs32 __user *) addr;
749 struct pt_regs *cregs = task_pt_regs(child);
750 752
751 ret = -EFAULT; 753 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
752 if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || 754 32 * sizeof(u32),
753 __put_user(cregs->tpc, (&pregs->pc)) || 755 4 * sizeof(u32),
754 __put_user(cregs->tnpc, (&pregs->npc)) || 756 &pregs->psr);
755 __put_user(cregs->y, (&pregs->y))) 757 if (!ret)
756 break; 758 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
757 for (i = 1; i < 16; i++) { 759 1 * sizeof(u32),
758 if (__put_user(cregs->u_regs[i], 760 15 * sizeof(u32),
759 (&pregs->u_regs[i - 1]))) 761 &pregs->u_regs[0]);
760 break;
761 }
762 if (i == 16)
763 ret = 0;
764 break; 762 break;
765 } 763 }
766 764
767 case PTRACE_GETREGS64: { 765 case PTRACE_GETREGS64: {
768 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 766 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
769 struct pt_regs *cregs = task_pt_regs(child);
770 unsigned long tpc = cregs->tpc;
771
772 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
773 tpc &= 0xffffffff;
774 767
775 ret = -EFAULT; 768 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
776 if (__put_user(cregs->tstate, (&pregs->tstate)) || 769 1 * sizeof(u64),
777 __put_user(tpc, (&pregs->tpc)) || 770 15 * sizeof(u64),
778 __put_user(cregs->tnpc, (&pregs->tnpc)) || 771 &pregs->u_regs[0]);
779 __put_user(cregs->y, (&pregs->y))) 772 if (!ret) {
780 break; 773 /* XXX doesn't handle 'y' register correctly XXX */
781 for (i = 1; i < 16; i++) { 774 ret = copy_regset_to_user(child, view, REGSET_GENERAL,
782 if (__put_user(cregs->u_regs[i], 775 32 * sizeof(u64),
783 (&pregs->u_regs[i - 1]))) 776 4 * sizeof(u64),
784 break; 777 &pregs->tstate);
785 } 778 }
786 if (i == 16)
787 ret = 0;
788 break; 779 break;
789 } 780 }
790 781
791 case PTRACE_SETREGS: { 782 case PTRACE_SETREGS: {
792 struct pt_regs32 __user *pregs = 783 struct pt_regs32 __user *pregs =
793 (struct pt_regs32 __user *) addr; 784 (struct pt_regs32 __user *) addr;
794 struct pt_regs *cregs = task_pt_regs(child); 785
795 unsigned int psr, pc, npc, y; 786 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
796 787 32 * sizeof(u32),
797 /* Must be careful, tracing process can only set certain 788 4 * sizeof(u32),
798 * bits in the psr. 789 &pregs->psr);
799 */ 790 if (!ret)
800 ret = -EFAULT; 791 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
801 if (__get_user(psr, (&pregs->psr)) || 792 1 * sizeof(u32),
802 __get_user(pc, (&pregs->pc)) || 793 15 * sizeof(u32),
803 __get_user(npc, (&pregs->npc)) || 794 &pregs->u_regs[0]);
804 __get_user(y, (&pregs->y)))
805 break;
806 cregs->tstate &= ~(TSTATE_ICC);
807 cregs->tstate |= psr_to_tstate_icc(psr);
808 if (!((pc | npc) & 3)) {
809 cregs->tpc = pc;
810 cregs->tnpc = npc;
811 }
812 cregs->y = y;
813 for (i = 1; i < 16; i++) {
814 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])))
815 break;
816 }
817 if (i == 16)
818 ret = 0;
819 break; 795 break;
820 } 796 }
821 797
822 case PTRACE_SETREGS64: { 798 case PTRACE_SETREGS64: {
823 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 799 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
824 struct pt_regs *cregs = task_pt_regs(child); 800
825 unsigned long tstate, tpc, tnpc, y; 801 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
826 802 1 * sizeof(u64),
827 /* Must be careful, tracing process can only set certain 803 15 * sizeof(u64),
828 * bits in the psr. 804 &pregs->u_regs[0]);
829 */ 805 if (!ret) {
830 ret = -EFAULT; 806 /* XXX doesn't handle 'y' register correctly XXX */
831 if (__get_user(tstate, (&pregs->tstate)) || 807 ret = copy_regset_from_user(child, view, REGSET_GENERAL,
832 __get_user(tpc, (&pregs->tpc)) || 808 32 * sizeof(u64),
833 __get_user(tnpc, (&pregs->tnpc)) || 809 4 * sizeof(u64),
834 __get_user(y, (&pregs->y))) 810 &pregs->tstate);
835 break;
836 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
837 tpc &= 0xffffffff;
838 tnpc &= 0xffffffff;
839 }
840 tstate &= (TSTATE_ICC | TSTATE_XCC);
841 cregs->tstate &= ~(TSTATE_ICC | TSTATE_XCC);
842 cregs->tstate |= tstate;
843 if (!((tpc | tnpc) & 3)) {
844 cregs->tpc = tpc;
845 cregs->tnpc = tnpc;
846 }
847 cregs->y = y;
848 for (i = 1; i < 16; i++) {
849 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])))
850 break;
851 } 811 }
852 if (i == 16)
853 ret = 0;
854 break; 812 break;
855 } 813 }
856 814
@@ -867,19 +825,23 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
867 } fpq[16]; 825 } fpq[16];
868 }; 826 };
869 struct fps __user *fps = (struct fps __user *) addr; 827 struct fps __user *fps = (struct fps __user *) addr;
870 unsigned long *fpregs = task_thread_info(child)->fpregs;
871
872 ret = -EFAULT;
873 if (copy_to_user(&fps->regs[0], fpregs,
874 (32 * sizeof(unsigned int))) ||
875 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) ||
876 __put_user(0, (&fps->fpqd)) ||
877 __put_user(0, (&fps->flags)) ||
878 __put_user(0, (&fps->extra)) ||
879 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
880 break;
881 828
882 ret = 0; 829 ret = copy_regset_to_user(child, view, REGSET_FP,
830 0 * sizeof(u32),
831 32 * sizeof(u32),
832 &fps->regs[0]);
833 if (!ret)
834 ret = copy_regset_to_user(child, view, REGSET_FP,
835 33 * sizeof(u32),
836 1 * sizeof(u32),
837 &fps->fsr);
838 if (!ret) {
839 if (__put_user(0, &fps->flags) ||
840 __put_user(0, &fps->extra) ||
841 __put_user(0, &fps->fpqd) ||
842 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
843 ret = -EFAULT;
844 }
883 break; 845 break;
884 } 846 }
885 847
@@ -889,15 +851,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
889 unsigned long fsr; 851 unsigned long fsr;
890 }; 852 };
891 struct fps __user *fps = (struct fps __user *) addr; 853 struct fps __user *fps = (struct fps __user *) addr;
892 unsigned long *fpregs = task_thread_info(child)->fpregs;
893 854
894 ret = -EFAULT; 855 ret = copy_regset_to_user(child, view, REGSET_FP,
895 if (copy_to_user(&fps->regs[0], fpregs, 856 0 * sizeof(u64),
896 (64 * sizeof(unsigned int))) || 857 33 * sizeof(u64),
897 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) 858 fps);
898 break;
899
900 ret = 0;
901 break; 859 break;
902 } 860 }
903 861
@@ -914,21 +872,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
914 } fpq[16]; 872 } fpq[16];
915 }; 873 };
916 struct fps __user *fps = (struct fps __user *) addr; 874 struct fps __user *fps = (struct fps __user *) addr;
917 unsigned long *fpregs = task_thread_info(child)->fpregs;
918 unsigned fsr;
919
920 ret = -EFAULT;
921 if (copy_from_user(fpregs, &fps->regs[0],
922 (32 * sizeof(unsigned int))) ||
923 __get_user(fsr, (&fps->fsr)))
924 break;
925 875
926 task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL; 876 ret = copy_regset_from_user(child, view, REGSET_FP,
927 task_thread_info(child)->xfsr[0] |= fsr; 877 0 * sizeof(u32),
928 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) 878 32 * sizeof(u32),
929 task_thread_info(child)->gsr[0] = 0; 879 &fps->regs[0]);
930 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL); 880 if (!ret)
931 ret = 0; 881 ret = copy_regset_from_user(child, view, REGSET_FP,
882 33 * sizeof(u32),
883 1 * sizeof(u32),
884 &fps->fsr);
932 break; 885 break;
933 } 886 }
934 887
@@ -938,19 +891,11 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
938 unsigned long fsr; 891 unsigned long fsr;
939 }; 892 };
940 struct fps __user *fps = (struct fps __user *) addr; 893 struct fps __user *fps = (struct fps __user *) addr;
941 unsigned long *fpregs = task_thread_info(child)->fpregs;
942
943 ret = -EFAULT;
944 if (copy_from_user(fpregs, &fps->regs[0],
945 (64 * sizeof(unsigned int))) ||
946 __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr)))
947 break;
948 894
949 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) 895 ret = copy_regset_to_user(child, view, REGSET_FP,
950 task_thread_info(child)->gsr[0] = 0; 896 0 * sizeof(u64),
951 task_thread_info(child)->fpsaved[0] |= 897 33 * sizeof(u64),
952 (FPRS_FEF | FPRS_DL | FPRS_DU); 898 fps);
953 ret = 0;
954 break; 899 break;
955 } 900 }
956 901