aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2008-02-07 06:00:17 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-07 06:00:17 -0500
commit9775369ec06bad8edb2fbd8c77316f49b439c225 (patch)
tree14b0cb23d5fad3dbd99da0e21cf1b7e3db92595f /arch/sparc64
parent190aa9f60f9575d1b7382cd1ee33e2589208c514 (diff)
[SPARC]: Move over to arch_ptrace().
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/kernel/entry.S4
-rw-r--r--arch/sparc64/kernel/ptrace.c389
2 files changed, 109 insertions, 284 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
index ea257e828364..6be4d2d2904e 100644
--- a/arch/sparc64/kernel/entry.S
+++ b/arch/sparc64/kernel/entry.S
@@ -1477,10 +1477,6 @@ sys32_rt_sigreturn:
1477 add %o7, 1f-.-4, %o7 1477 add %o7, 1f-.-4, %o7
1478 nop 1478 nop
1479#endif 1479#endif
1480sys_ptrace: add %sp, PTREGS_OFF, %o0
1481 call do_ptrace
1482 add %o7, 1f-.-4, %o7
1483 nop
1484 .align 32 1480 .align 32
14851: ldx [%curptr + TI_FLAGS], %l5 14811: ldx [%curptr + TI_FLAGS], %l5
1486 andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 1482 andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
index e881dbbd2c49..c831d426c4ac 100644
--- a/arch/sparc64/kernel/ptrace.c
+++ b/arch/sparc64/kernel/ptrace.c
@@ -36,56 +36,6 @@
36#include <asm/page.h> 36#include <asm/page.h>
37#include <asm/cpudata.h> 37#include <asm/cpudata.h>
38 38
39/* Returning from ptrace is a bit tricky because the syscall return
40 * low level code assumes any value returned which is negative and
41 * is a valid errno will mean setting the condition codes to indicate
42 * an error return. This doesn't work, so we have this hook.
43 */
44static inline void pt_error_return(struct pt_regs *regs, unsigned long error)
45{
46 regs->u_regs[UREG_I0] = error;
47 regs->tstate |= (TSTATE_ICARRY | TSTATE_XCARRY);
48 regs->tpc = regs->tnpc;
49 regs->tnpc += 4;
50}
51
52static inline void pt_succ_return(struct pt_regs *regs, unsigned long value)
53{
54 regs->u_regs[UREG_I0] = value;
55 regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
56 regs->tpc = regs->tnpc;
57 regs->tnpc += 4;
58}
59
60static inline void
61pt_succ_return_linux(struct pt_regs *regs, unsigned long value, void __user *addr)
62{
63 if (test_thread_flag(TIF_32BIT)) {
64 if (put_user(value, (unsigned int __user *) addr)) {
65 pt_error_return(regs, EFAULT);
66 return;
67 }
68 } else {
69 if (put_user(value, (long __user *) addr)) {
70 pt_error_return(regs, EFAULT);
71 return;
72 }
73 }
74 regs->u_regs[UREG_I0] = 0;
75 regs->tstate &= ~(TSTATE_ICARRY | TSTATE_XCARRY);
76 regs->tpc = regs->tnpc;
77 regs->tnpc += 4;
78}
79
80static void
81pt_os_succ_return (struct pt_regs *regs, unsigned long val, void __user *addr)
82{
83 if (current->personality == PER_SUNOS)
84 pt_succ_return (regs, val);
85 else
86 pt_succ_return_linux (regs, val, addr);
87}
88
89/* #define ALLOW_INIT_TRACING */ 39/* #define ALLOW_INIT_TRACING */
90 40
91/* 41/*
@@ -734,171 +684,113 @@ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
734 return &user_sparc64_view; 684 return &user_sparc64_view;
735} 685}
736 686
737asmlinkage void do_ptrace(struct pt_regs *regs) 687long arch_ptrace(struct task_struct *child, long request, long addr, long data)
738{ 688{
739 int request = regs->u_regs[UREG_I0]; 689 long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
740 pid_t pid = regs->u_regs[UREG_I1]; 690 int i, ret;
741 unsigned long addr = regs->u_regs[UREG_I2];
742 unsigned long data = regs->u_regs[UREG_I3];
743 unsigned long addr2 = regs->u_regs[UREG_I4];
744 struct task_struct *child;
745 int ret;
746 691
747 if (test_thread_flag(TIF_32BIT)) { 692#if 1
748 addr &= 0xffffffffUL; 693 printk(KERN_INFO
749 data &= 0xffffffffUL; 694 "arch_ptrace: request[%ld] addr[%lx] data[%lx] addr2[%lx]\n",
695 request, addr, data, addr2);
696#endif
697 if (test_thread_flag(TIF_32BIT))
750 addr2 &= 0xffffffffUL; 698 addr2 &= 0xffffffffUL;
751 }
752 lock_kernel();
753 if (request == PTRACE_TRACEME) {
754 ret = ptrace_traceme();
755 if (ret < 0)
756 pt_error_return(regs, -ret);
757 else
758 pt_succ_return(regs, 0);
759 goto out;
760 }
761
762 child = ptrace_get_task_struct(pid);
763 if (IS_ERR(child)) {
764 ret = PTR_ERR(child);
765 pt_error_return(regs, -ret);
766 goto out;
767 }
768
769 if (request == PTRACE_ATTACH) {
770 if (ptrace_attach(child)) {
771 pt_error_return(regs, EPERM);
772 goto out_tsk;
773 }
774 pt_succ_return(regs, 0);
775 goto out_tsk;
776 }
777
778 ret = ptrace_check_attach(child, request == PTRACE_KILL);
779 if (ret < 0) {
780 pt_error_return(regs, -ret);
781 goto out_tsk;
782 }
783
784 if (!(test_thread_flag(TIF_32BIT)) &&
785 ((request == PTRACE_READDATA64) ||
786 (request == PTRACE_WRITEDATA64) ||
787 (request == PTRACE_READTEXT64) ||
788 (request == PTRACE_WRITETEXT64) ||
789 (request == PTRACE_PEEKTEXT64) ||
790 (request == PTRACE_POKETEXT64) ||
791 (request == PTRACE_PEEKDATA64) ||
792 (request == PTRACE_POKEDATA64))) {
793 addr = regs->u_regs[UREG_G2];
794 addr2 = regs->u_regs[UREG_G3];
795 request -= 30; /* wheee... */
796 }
797 699
798 switch(request) { 700 switch(request) {
799 case PTRACE_PEEKUSR: 701 case PTRACE_PEEKUSR:
800 if (addr != 0) 702 ret = (addr != 0) ? -EIO : 0;
801 pt_error_return(regs, EIO); 703 break;
802 else
803 pt_succ_return(regs, 0);
804 goto out_tsk;
805 704
806 case PTRACE_PEEKTEXT: /* read word at location addr. */ 705 case PTRACE_PEEKTEXT: /* read word at location addr. */
807 case PTRACE_PEEKDATA: { 706 case PTRACE_PEEKDATA: {
808 unsigned long tmp64; 707 unsigned long tmp64;
809 unsigned int tmp32; 708 unsigned int tmp32;
810 int res, copied; 709 int copied;
811 710
812 res = -EIO; 711 ret = -EIO;
813 if (test_thread_flag(TIF_32BIT)) { 712 if (test_thread_flag(TIF_32BIT)) {
814 copied = access_process_vm(child, addr, 713 copied = access_process_vm(child, addr,
815 &tmp32, sizeof(tmp32), 0); 714 &tmp32, sizeof(tmp32), 0);
816 tmp64 = (unsigned long) tmp32;
817 if (copied == sizeof(tmp32)) 715 if (copied == sizeof(tmp32))
818 res = 0; 716 ret = put_user(tmp32,
717 (unsigned int __user *) data);
819 } else { 718 } else {
820 copied = access_process_vm(child, addr, 719 copied = access_process_vm(child, addr,
821 &tmp64, sizeof(tmp64), 0); 720 &tmp64, sizeof(tmp64), 0);
822 if (copied == sizeof(tmp64)) 721 if (copied == sizeof(tmp64))
823 res = 0; 722 ret = put_user(tmp64,
723 (unsigned long __user *) data);
824 } 724 }
825 if (res < 0) 725 break;
826 pt_error_return(regs, -res);
827 else
828 pt_os_succ_return(regs, tmp64, (void __user *) data);
829 goto out_tsk;
830 } 726 }
831 727
832 case PTRACE_POKETEXT: /* write the word at location addr. */ 728 case PTRACE_POKETEXT: /* write the word at location addr. */
833 case PTRACE_POKEDATA: { 729 case PTRACE_POKEDATA: {
834 unsigned long tmp64; 730 unsigned long tmp64;
835 unsigned int tmp32; 731 unsigned int tmp32;
836 int copied, res = -EIO; 732 int copied;
837 733
734 ret = -EIO;
838 if (test_thread_flag(TIF_32BIT)) { 735 if (test_thread_flag(TIF_32BIT)) {
839 tmp32 = data; 736 tmp32 = data;
840 copied = access_process_vm(child, addr, 737 copied = access_process_vm(child, addr,
841 &tmp32, sizeof(tmp32), 1); 738 &tmp32, sizeof(tmp32), 1);
842 if (copied == sizeof(tmp32)) 739 if (copied == sizeof(tmp32))
843 res = 0; 740 ret = 0;
844 } else { 741 } else {
845 tmp64 = data; 742 tmp64 = data;
846 copied = access_process_vm(child, addr, 743 copied = access_process_vm(child, addr,
847 &tmp64, sizeof(tmp64), 1); 744 &tmp64, sizeof(tmp64), 1);
848 if (copied == sizeof(tmp64)) 745 if (copied == sizeof(tmp64))
849 res = 0; 746 ret = 0;
850 } 747 }
851 if (res < 0) 748 break;
852 pt_error_return(regs, -res);
853 else
854 pt_succ_return(regs, res);
855 goto out_tsk;
856 } 749 }
857 750
858 case PTRACE_GETREGS: { 751 case PTRACE_GETREGS: {
859 struct pt_regs32 __user *pregs = 752 struct pt_regs32 __user *pregs =
860 (struct pt_regs32 __user *) addr; 753 (struct pt_regs32 __user *) addr;
861 struct pt_regs *cregs = task_pt_regs(child); 754 struct pt_regs *cregs = task_pt_regs(child);
862 int rval;
863 755
756 ret = -EFAULT;
864 if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) || 757 if (__put_user(tstate_to_psr(cregs->tstate), (&pregs->psr)) ||
865 __put_user(cregs->tpc, (&pregs->pc)) || 758 __put_user(cregs->tpc, (&pregs->pc)) ||
866 __put_user(cregs->tnpc, (&pregs->npc)) || 759 __put_user(cregs->tnpc, (&pregs->npc)) ||
867 __put_user(cregs->y, (&pregs->y))) { 760 __put_user(cregs->y, (&pregs->y)))
868 pt_error_return(regs, EFAULT); 761 break;
869 goto out_tsk; 762 for (i = 1; i < 16; i++) {
763 if (__put_user(cregs->u_regs[i],
764 (&pregs->u_regs[i - 1])))
765 break;
870 } 766 }
871 for (rval = 1; rval < 16; rval++) 767 if (i == 16)
872 if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { 768 ret = 0;
873 pt_error_return(regs, EFAULT); 769 break;
874 goto out_tsk;
875 }
876 pt_succ_return(regs, 0);
877 goto out_tsk;
878 } 770 }
879 771
880 case PTRACE_GETREGS64: { 772 case PTRACE_GETREGS64: {
881 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 773 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
882 struct pt_regs *cregs = task_pt_regs(child); 774 struct pt_regs *cregs = task_pt_regs(child);
883 unsigned long tpc = cregs->tpc; 775 unsigned long tpc = cregs->tpc;
884 int rval;
885 776
886 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) 777 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0)
887 tpc &= 0xffffffff; 778 tpc &= 0xffffffff;
779
780 ret = -EFAULT;
888 if (__put_user(cregs->tstate, (&pregs->tstate)) || 781 if (__put_user(cregs->tstate, (&pregs->tstate)) ||
889 __put_user(tpc, (&pregs->tpc)) || 782 __put_user(tpc, (&pregs->tpc)) ||
890 __put_user(cregs->tnpc, (&pregs->tnpc)) || 783 __put_user(cregs->tnpc, (&pregs->tnpc)) ||
891 __put_user(cregs->y, (&pregs->y))) { 784 __put_user(cregs->y, (&pregs->y)))
892 pt_error_return(regs, EFAULT); 785 break;
893 goto out_tsk; 786 for (i = 1; i < 16; i++) {
787 if (__put_user(cregs->u_regs[i],
788 (&pregs->u_regs[i - 1])))
789 break;
894 } 790 }
895 for (rval = 1; rval < 16; rval++) 791 if (i == 16)
896 if (__put_user(cregs->u_regs[rval], (&pregs->u_regs[rval - 1]))) { 792 ret = 0;
897 pt_error_return(regs, EFAULT); 793 break;
898 goto out_tsk;
899 }
900 pt_succ_return(regs, 0);
901 goto out_tsk;
902 } 794 }
903 795
904 case PTRACE_SETREGS: { 796 case PTRACE_SETREGS: {
@@ -906,18 +798,16 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
906 (struct pt_regs32 __user *) addr; 798 (struct pt_regs32 __user *) addr;
907 struct pt_regs *cregs = task_pt_regs(child); 799 struct pt_regs *cregs = task_pt_regs(child);
908 unsigned int psr, pc, npc, y; 800 unsigned int psr, pc, npc, y;
909 int i;
910 801
911 /* Must be careful, tracing process can only set certain 802 /* Must be careful, tracing process can only set certain
912 * bits in the psr. 803 * bits in the psr.
913 */ 804 */
805 ret = -EFAULT;
914 if (__get_user(psr, (&pregs->psr)) || 806 if (__get_user(psr, (&pregs->psr)) ||
915 __get_user(pc, (&pregs->pc)) || 807 __get_user(pc, (&pregs->pc)) ||
916 __get_user(npc, (&pregs->npc)) || 808 __get_user(npc, (&pregs->npc)) ||
917 __get_user(y, (&pregs->y))) { 809 __get_user(y, (&pregs->y)))
918 pt_error_return(regs, EFAULT); 810 break;
919 goto out_tsk;
920 }
921 cregs->tstate &= ~(TSTATE_ICC); 811 cregs->tstate &= ~(TSTATE_ICC);
922 cregs->tstate |= psr_to_tstate_icc(psr); 812 cregs->tstate |= psr_to_tstate_icc(psr);
923 if (!((pc | npc) & 3)) { 813 if (!((pc | npc) & 3)) {
@@ -926,31 +816,28 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
926 } 816 }
927 cregs->y = y; 817 cregs->y = y;
928 for (i = 1; i < 16; i++) { 818 for (i = 1; i < 16; i++) {
929 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { 819 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])))
930 pt_error_return(regs, EFAULT); 820 break;
931 goto out_tsk;
932 }
933 } 821 }
934 pt_succ_return(regs, 0); 822 if (i == 16)
935 goto out_tsk; 823 ret = 0;
824 break;
936 } 825 }
937 826
938 case PTRACE_SETREGS64: { 827 case PTRACE_SETREGS64: {
939 struct pt_regs __user *pregs = (struct pt_regs __user *) addr; 828 struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
940 struct pt_regs *cregs = task_pt_regs(child); 829 struct pt_regs *cregs = task_pt_regs(child);
941 unsigned long tstate, tpc, tnpc, y; 830 unsigned long tstate, tpc, tnpc, y;
942 int i;
943 831
944 /* Must be careful, tracing process can only set certain 832 /* Must be careful, tracing process can only set certain
945 * bits in the psr. 833 * bits in the psr.
946 */ 834 */
835 ret = -EFAULT;
947 if (__get_user(tstate, (&pregs->tstate)) || 836 if (__get_user(tstate, (&pregs->tstate)) ||
948 __get_user(tpc, (&pregs->tpc)) || 837 __get_user(tpc, (&pregs->tpc)) ||
949 __get_user(tnpc, (&pregs->tnpc)) || 838 __get_user(tnpc, (&pregs->tnpc)) ||
950 __get_user(y, (&pregs->y))) { 839 __get_user(y, (&pregs->y)))
951 pt_error_return(regs, EFAULT); 840 break;
952 goto out_tsk;
953 }
954 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) { 841 if ((task_thread_info(child)->flags & _TIF_32BIT) != 0) {
955 tpc &= 0xffffffff; 842 tpc &= 0xffffffff;
956 tnpc &= 0xffffffff; 843 tnpc &= 0xffffffff;
@@ -964,13 +851,12 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
964 } 851 }
965 cregs->y = y; 852 cregs->y = y;
966 for (i = 1; i < 16; i++) { 853 for (i = 1; i < 16; i++) {
967 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1]))) { 854 if (__get_user(cregs->u_regs[i], (&pregs->u_regs[i-1])))
968 pt_error_return(regs, EFAULT); 855 break;
969 goto out_tsk;
970 }
971 } 856 }
972 pt_succ_return(regs, 0); 857 if (i == 16)
973 goto out_tsk; 858 ret = 0;
859 break;
974 } 860 }
975 861
976 case PTRACE_GETFPREGS: { 862 case PTRACE_GETFPREGS: {
@@ -988,18 +874,18 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
988 struct fps __user *fps = (struct fps __user *) addr; 874 struct fps __user *fps = (struct fps __user *) addr;
989 unsigned long *fpregs = task_thread_info(child)->fpregs; 875 unsigned long *fpregs = task_thread_info(child)->fpregs;
990 876
877 ret = -EFAULT;
991 if (copy_to_user(&fps->regs[0], fpregs, 878 if (copy_to_user(&fps->regs[0], fpregs,
992 (32 * sizeof(unsigned int))) || 879 (32 * sizeof(unsigned int))) ||
993 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) || 880 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)) ||
994 __put_user(0, (&fps->fpqd)) || 881 __put_user(0, (&fps->fpqd)) ||
995 __put_user(0, (&fps->flags)) || 882 __put_user(0, (&fps->flags)) ||
996 __put_user(0, (&fps->extra)) || 883 __put_user(0, (&fps->extra)) ||
997 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int))) { 884 clear_user(&fps->fpq[0], 32 * sizeof(unsigned int)))
998 pt_error_return(regs, EFAULT); 885 break;
999 goto out_tsk; 886
1000 } 887 ret = 0;
1001 pt_succ_return(regs, 0); 888 break;
1002 goto out_tsk;
1003 } 889 }
1004 890
1005 case PTRACE_GETFPREGS64: { 891 case PTRACE_GETFPREGS64: {
@@ -1010,14 +896,14 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
1010 struct fps __user *fps = (struct fps __user *) addr; 896 struct fps __user *fps = (struct fps __user *) addr;
1011 unsigned long *fpregs = task_thread_info(child)->fpregs; 897 unsigned long *fpregs = task_thread_info(child)->fpregs;
1012 898
899 ret = -EFAULT;
1013 if (copy_to_user(&fps->regs[0], fpregs, 900 if (copy_to_user(&fps->regs[0], fpregs,
1014 (64 * sizeof(unsigned int))) || 901 (64 * sizeof(unsigned int))) ||
1015 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { 902 __put_user(task_thread_info(child)->xfsr[0], (&fps->fsr)))
1016 pt_error_return(regs, EFAULT); 903 break;
1017 goto out_tsk; 904
1018 } 905 ret = 0;
1019 pt_succ_return(regs, 0); 906 break;
1020 goto out_tsk;
1021 } 907 }
1022 908
1023 case PTRACE_SETFPREGS: { 909 case PTRACE_SETFPREGS: {
@@ -1036,19 +922,19 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
1036 unsigned long *fpregs = task_thread_info(child)->fpregs; 922 unsigned long *fpregs = task_thread_info(child)->fpregs;
1037 unsigned fsr; 923 unsigned fsr;
1038 924
925 ret = -EFAULT;
1039 if (copy_from_user(fpregs, &fps->regs[0], 926 if (copy_from_user(fpregs, &fps->regs[0],
1040 (32 * sizeof(unsigned int))) || 927 (32 * sizeof(unsigned int))) ||
1041 __get_user(fsr, (&fps->fsr))) { 928 __get_user(fsr, (&fps->fsr)))
1042 pt_error_return(regs, EFAULT); 929 break;
1043 goto out_tsk; 930
1044 }
1045 task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL; 931 task_thread_info(child)->xfsr[0] &= 0xffffffff00000000UL;
1046 task_thread_info(child)->xfsr[0] |= fsr; 932 task_thread_info(child)->xfsr[0] |= fsr;
1047 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) 933 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
1048 task_thread_info(child)->gsr[0] = 0; 934 task_thread_info(child)->gsr[0] = 0;
1049 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL); 935 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL);
1050 pt_succ_return(regs, 0); 936 ret = 0;
1051 goto out_tsk; 937 break;
1052 } 938 }
1053 939
1054 case PTRACE_SETFPREGS64: { 940 case PTRACE_SETFPREGS64: {
@@ -1059,113 +945,56 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
1059 struct fps __user *fps = (struct fps __user *) addr; 945 struct fps __user *fps = (struct fps __user *) addr;
1060 unsigned long *fpregs = task_thread_info(child)->fpregs; 946 unsigned long *fpregs = task_thread_info(child)->fpregs;
1061 947
948 ret = -EFAULT;
1062 if (copy_from_user(fpregs, &fps->regs[0], 949 if (copy_from_user(fpregs, &fps->regs[0],
1063 (64 * sizeof(unsigned int))) || 950 (64 * sizeof(unsigned int))) ||
1064 __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr))) { 951 __get_user(task_thread_info(child)->xfsr[0], (&fps->fsr)))
1065 pt_error_return(regs, EFAULT); 952 break;
1066 goto out_tsk; 953
1067 }
1068 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF)) 954 if (!(task_thread_info(child)->fpsaved[0] & FPRS_FEF))
1069 task_thread_info(child)->gsr[0] = 0; 955 task_thread_info(child)->gsr[0] = 0;
1070 task_thread_info(child)->fpsaved[0] |= (FPRS_FEF | FPRS_DL | FPRS_DU); 956 task_thread_info(child)->fpsaved[0] |=
1071 pt_succ_return(regs, 0); 957 (FPRS_FEF | FPRS_DL | FPRS_DU);
1072 goto out_tsk; 958 ret = 0;
959 break;
1073 } 960 }
1074 961
1075 case PTRACE_READTEXT: 962 case PTRACE_READTEXT:
1076 case PTRACE_READDATA: { 963 case PTRACE_READDATA:
1077 int res = ptrace_readdata(child, addr, 964 ret = ptrace_readdata(child, addr,
1078 (char __user *)addr2, data); 965 (char __user *)addr2, data);
1079 if (res == data) { 966 if (ret == data)
1080 pt_succ_return(regs, 0); 967 ret = 0;
1081 goto out_tsk; 968 else if (ret >= 0)
1082 } 969 ret = -EIO;
1083 if (res >= 0) 970 break;
1084 res = -EIO;
1085 pt_error_return(regs, -res);
1086 goto out_tsk;
1087 }
1088 971
1089 case PTRACE_WRITETEXT: 972 case PTRACE_WRITETEXT:
1090 case PTRACE_WRITEDATA: { 973 case PTRACE_WRITEDATA:
1091 int res = ptrace_writedata(child, (char __user *) addr2, 974 ret = ptrace_writedata(child, (char __user *) addr2,
1092 addr, data); 975 addr, data);
1093 if (res == data) { 976 if (ret == data)
1094 pt_succ_return(regs, 0); 977 ret = 0;
1095 goto out_tsk; 978 else if (ret >= 0)
1096 } 979 ret = -EIO;
1097 if (res >= 0) 980 break;
1098 res = -EIO;
1099 pt_error_return(regs, -res);
1100 goto out_tsk;
1101 }
1102 case PTRACE_SYSCALL: /* continue and stop at (return from) syscall */
1103 addr = 1;
1104
1105 case PTRACE_CONT: { /* restart after signal. */
1106 if (!valid_signal(data)) {
1107 pt_error_return(regs, EIO);
1108 goto out_tsk;
1109 }
1110
1111 if (request == PTRACE_SYSCALL) {
1112 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1113 } else {
1114 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
1115 }
1116
1117 child->exit_code = data;
1118 wake_up_process(child);
1119 pt_succ_return(regs, 0);
1120 goto out_tsk;
1121 }
1122
1123/*
1124 * make the child exit. Best I can do is send it a sigkill.
1125 * perhaps it should be put in the status that it wants to
1126 * exit.
1127 */
1128 case PTRACE_KILL: {
1129 if (child->exit_state == EXIT_ZOMBIE) { /* already dead */
1130 pt_succ_return(regs, 0);
1131 goto out_tsk;
1132 }
1133 child->exit_code = SIGKILL;
1134 wake_up_process(child);
1135 pt_succ_return(regs, 0);
1136 goto out_tsk;
1137 }
1138 981
1139 case PTRACE_GETEVENTMSG: { 982 case PTRACE_GETEVENTMSG: {
1140 int err;
1141
1142 if (test_thread_flag(TIF_32BIT)) 983 if (test_thread_flag(TIF_32BIT))
1143 err = put_user(child->ptrace_message, 984 ret = put_user(child->ptrace_message,
1144 (unsigned int __user *) data); 985 (unsigned int __user *) data);
1145 else 986 else
1146 err = put_user(child->ptrace_message, 987 ret = put_user(child->ptrace_message,
1147 (unsigned long __user *) data); 988 (unsigned long __user *) data);
1148 if (err)
1149 pt_error_return(regs, -err);
1150 else
1151 pt_succ_return(regs, 0);
1152 break; 989 break;
1153 } 990 }
1154 991
1155 default: { 992 default:
1156 int err = ptrace_request(child, request, addr, data); 993 ret = ptrace_request(child, request, addr, data);
1157 if (err) 994 break;
1158 pt_error_return(regs, -err);
1159 else
1160 pt_succ_return(regs, 0);
1161 goto out_tsk;
1162 }
1163 } 995 }
1164out_tsk: 996
1165 if (child) 997 return ret;
1166 put_task_struct(child);
1167out:
1168 unlock_kernel();
1169} 998}
1170 999
1171asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p) 1000asmlinkage void syscall_trace(struct pt_regs *regs, int syscall_exit_p)