diff options
Diffstat (limited to 'arch/sparc64/kernel/signal32.c')
-rw-r--r-- | arch/sparc64/kernel/signal32.c | 300 |
1 files changed, 8 insertions, 292 deletions
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 8c1c121330fb..74e0512f135c 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c | |||
@@ -23,7 +23,6 @@ | |||
23 | 23 | ||
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/ptrace.h> | 25 | #include <asm/ptrace.h> |
26 | #include <asm/svr4.h> | ||
27 | #include <asm/pgtable.h> | 26 | #include <asm/pgtable.h> |
28 | #include <asm/psrcompat.h> | 27 | #include <asm/psrcompat.h> |
29 | #include <asm/fpumacro.h> | 28 | #include <asm/fpumacro.h> |
@@ -798,281 +797,6 @@ sigsegv: | |||
798 | force_sigsegv(signo, current); | 797 | force_sigsegv(signo, current); |
799 | } | 798 | } |
800 | 799 | ||
801 | /* Setup a Solaris stack frame */ | ||
802 | static void | ||
803 | setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, | ||
804 | struct pt_regs *regs, int signr, sigset_t *oldset) | ||
805 | { | ||
806 | svr4_signal_frame_t __user *sfp; | ||
807 | svr4_gregset_t __user *gr; | ||
808 | svr4_siginfo_t __user *si; | ||
809 | svr4_mcontext_t __user *mc; | ||
810 | svr4_gwindows_t __user *gw; | ||
811 | svr4_ucontext_t __user *uc; | ||
812 | svr4_sigset_t setv; | ||
813 | unsigned int psr; | ||
814 | int i, err; | ||
815 | |||
816 | synchronize_user_stack(); | ||
817 | save_and_clear_fpu(); | ||
818 | |||
819 | regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; | ||
820 | sfp = (svr4_signal_frame_t __user *) | ||
821 | get_sigframe(sa, regs, | ||
822 | sizeof(struct reg_window32) + SVR4_SF_ALIGNED); | ||
823 | |||
824 | if (invalid_frame_pointer(sfp, sizeof(*sfp))) | ||
825 | do_exit(SIGILL); | ||
826 | |||
827 | /* Start with a clean frame pointer and fill it */ | ||
828 | err = clear_user(sfp, sizeof(*sfp)); | ||
829 | |||
830 | /* Setup convenience variables */ | ||
831 | si = &sfp->si; | ||
832 | uc = &sfp->uc; | ||
833 | gw = &sfp->gw; | ||
834 | mc = &uc->mcontext; | ||
835 | gr = &mc->greg; | ||
836 | |||
837 | /* FIXME: where am I supposed to put this? | ||
838 | * sc->sigc_onstack = old_status; | ||
839 | * anyways, it does not look like it is used for anything at all. | ||
840 | */ | ||
841 | setv.sigbits[0] = oldset->sig[0]; | ||
842 | setv.sigbits[1] = (oldset->sig[0] >> 32); | ||
843 | if (_NSIG_WORDS >= 2) { | ||
844 | setv.sigbits[2] = oldset->sig[1]; | ||
845 | setv.sigbits[3] = (oldset->sig[1] >> 32); | ||
846 | err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); | ||
847 | } else | ||
848 | err |= __copy_to_user(&uc->sigmask, &setv, | ||
849 | 2 * sizeof(unsigned int)); | ||
850 | |||
851 | /* Store registers */ | ||
852 | if (test_thread_flag(TIF_32BIT)) { | ||
853 | regs->tpc &= 0xffffffff; | ||
854 | regs->tnpc &= 0xffffffff; | ||
855 | } | ||
856 | err |= __put_user(regs->tpc, &((*gr)[SVR4_PC])); | ||
857 | err |= __put_user(regs->tnpc, &((*gr)[SVR4_NPC])); | ||
858 | psr = tstate_to_psr(regs->tstate); | ||
859 | if (current_thread_info()->fpsaved[0] & FPRS_FEF) | ||
860 | psr |= PSR_EF; | ||
861 | err |= __put_user(psr, &((*gr)[SVR4_PSR])); | ||
862 | err |= __put_user(regs->y, &((*gr)[SVR4_Y])); | ||
863 | |||
864 | /* Copy g[1..7] and o[0..7] registers */ | ||
865 | for (i = 0; i < 7; i++) | ||
866 | err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); | ||
867 | for (i = 0; i < 8; i++) | ||
868 | err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); | ||
869 | |||
870 | /* Setup sigaltstack */ | ||
871 | err |= __put_user(current->sas_ss_sp, &uc->stack.sp); | ||
872 | err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); | ||
873 | err |= __put_user(current->sas_ss_size, &uc->stack.size); | ||
874 | |||
875 | /* Save the currently window file: */ | ||
876 | |||
877 | /* 1. Link sfp->uc->gwins to our windows */ | ||
878 | err |= __put_user(ptr_to_compat(gw), &mc->gwin); | ||
879 | |||
880 | /* 2. Number of windows to restore at setcontext (): */ | ||
881 | err |= __put_user(get_thread_wsaved(), &gw->count); | ||
882 | |||
883 | /* 3. We just pay attention to the gw->count field on setcontext */ | ||
884 | set_thread_wsaved(0); /* So process is allowed to execute. */ | ||
885 | |||
886 | /* Setup the signal information. Solaris expects a bunch of | ||
887 | * information to be passed to the signal handler, we don't provide | ||
888 | * that much currently, should use siginfo. | ||
889 | */ | ||
890 | err |= __put_user(signr, &si->siginfo.signo); | ||
891 | err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); | ||
892 | if (err) | ||
893 | goto sigsegv; | ||
894 | |||
895 | regs->u_regs[UREG_FP] = (unsigned long) sfp; | ||
896 | regs->tpc = (unsigned long) sa->sa_handler; | ||
897 | regs->tnpc = (regs->tpc + 4); | ||
898 | if (test_thread_flag(TIF_32BIT)) { | ||
899 | regs->tpc &= 0xffffffff; | ||
900 | regs->tnpc &= 0xffffffff; | ||
901 | } | ||
902 | |||
903 | /* Arguments passed to signal handler */ | ||
904 | if (regs->u_regs[14]){ | ||
905 | struct reg_window32 __user *rw = (struct reg_window32 __user *) | ||
906 | (regs->u_regs[14] & 0x00000000ffffffffUL); | ||
907 | |||
908 | err |= __put_user(signr, &rw->ins[0]); | ||
909 | err |= __put_user((u64)si, &rw->ins[1]); | ||
910 | err |= __put_user((u64)uc, &rw->ins[2]); | ||
911 | err |= __put_user((u64)sfp, &rw->ins[6]); /* frame pointer */ | ||
912 | if (err) | ||
913 | goto sigsegv; | ||
914 | |||
915 | regs->u_regs[UREG_I0] = signr; | ||
916 | regs->u_regs[UREG_I1] = (u32)(u64) si; | ||
917 | regs->u_regs[UREG_I2] = (u32)(u64) uc; | ||
918 | } | ||
919 | return; | ||
920 | |||
921 | sigsegv: | ||
922 | force_sigsegv(signr, current); | ||
923 | } | ||
924 | |||
925 | asmlinkage int | ||
926 | svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs) | ||
927 | { | ||
928 | svr4_gregset_t __user *gr; | ||
929 | svr4_mcontext_t __user *mc; | ||
930 | svr4_sigset_t setv; | ||
931 | int i, err; | ||
932 | u32 psr; | ||
933 | |||
934 | synchronize_user_stack(); | ||
935 | save_and_clear_fpu(); | ||
936 | |||
937 | if (get_thread_wsaved()) | ||
938 | do_exit(SIGSEGV); | ||
939 | |||
940 | err = clear_user(uc, sizeof(*uc)); | ||
941 | |||
942 | /* Setup convenience variables */ | ||
943 | mc = &uc->mcontext; | ||
944 | gr = &mc->greg; | ||
945 | |||
946 | setv.sigbits[0] = current->blocked.sig[0]; | ||
947 | setv.sigbits[1] = (current->blocked.sig[0] >> 32); | ||
948 | if (_NSIG_WORDS >= 2) { | ||
949 | setv.sigbits[2] = current->blocked.sig[1]; | ||
950 | setv.sigbits[3] = (current->blocked.sig[1] >> 32); | ||
951 | err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); | ||
952 | } else | ||
953 | err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned)); | ||
954 | |||
955 | /* Store registers */ | ||
956 | if (test_thread_flag(TIF_32BIT)) { | ||
957 | regs->tpc &= 0xffffffff; | ||
958 | regs->tnpc &= 0xffffffff; | ||
959 | } | ||
960 | err |= __put_user(regs->tpc, &uc->mcontext.greg[SVR4_PC]); | ||
961 | err |= __put_user(regs->tnpc, &uc->mcontext.greg[SVR4_NPC]); | ||
962 | |||
963 | psr = tstate_to_psr(regs->tstate) & ~PSR_EF; | ||
964 | if (current_thread_info()->fpsaved[0] & FPRS_FEF) | ||
965 | psr |= PSR_EF; | ||
966 | err |= __put_user(psr, &uc->mcontext.greg[SVR4_PSR]); | ||
967 | |||
968 | err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]); | ||
969 | |||
970 | /* Copy g[1..7] and o[0..7] registers */ | ||
971 | for (i = 0; i < 7; i++) | ||
972 | err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); | ||
973 | for (i = 0; i < 8; i++) | ||
974 | err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); | ||
975 | |||
976 | /* Setup sigaltstack */ | ||
977 | err |= __put_user(current->sas_ss_sp, &uc->stack.sp); | ||
978 | err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); | ||
979 | err |= __put_user(current->sas_ss_size, &uc->stack.size); | ||
980 | |||
981 | /* The register file is not saved | ||
982 | * we have already stuffed all of it with sync_user_stack | ||
983 | */ | ||
984 | return (err ? -EFAULT : 0); | ||
985 | } | ||
986 | |||
987 | |||
988 | /* Set the context for a svr4 application, this is Solaris way to sigreturn */ | ||
989 | asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs) | ||
990 | { | ||
991 | svr4_gregset_t __user *gr; | ||
992 | mm_segment_t old_fs; | ||
993 | u32 pc, npc, psr, u_ss_sp; | ||
994 | sigset_t set; | ||
995 | svr4_sigset_t setv; | ||
996 | int i, err; | ||
997 | stack_t st; | ||
998 | |||
999 | /* Fixme: restore windows, or is this already taken care of in | ||
1000 | * svr4_setup_frame when sync_user_windows is done? | ||
1001 | */ | ||
1002 | flush_user_windows(); | ||
1003 | |||
1004 | if (get_thread_wsaved()) | ||
1005 | goto sigsegv; | ||
1006 | |||
1007 | if (((unsigned long) c) & 3){ | ||
1008 | printk("Unaligned structure passed\n"); | ||
1009 | goto sigsegv; | ||
1010 | } | ||
1011 | |||
1012 | if (!__access_ok(c, sizeof(*c))) { | ||
1013 | /* Miguel, add nice debugging msg _here_. ;-) */ | ||
1014 | goto sigsegv; | ||
1015 | } | ||
1016 | |||
1017 | /* Check for valid PC and nPC */ | ||
1018 | gr = &c->mcontext.greg; | ||
1019 | err = __get_user(pc, &((*gr)[SVR4_PC])); | ||
1020 | err |= __get_user(npc, &((*gr)[SVR4_NPC])); | ||
1021 | if ((pc | npc) & 3) | ||
1022 | goto sigsegv; | ||
1023 | |||
1024 | /* Retrieve information from passed ucontext */ | ||
1025 | /* note that nPC is ored a 1, this is used to inform entry.S */ | ||
1026 | /* that we don't want it to mess with our PC and nPC */ | ||
1027 | |||
1028 | err |= copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t)); | ||
1029 | set.sig[0] = setv.sigbits[0] | (((long)setv.sigbits[1]) << 32); | ||
1030 | if (_NSIG_WORDS >= 2) | ||
1031 | set.sig[1] = setv.sigbits[2] | (((long)setv.sigbits[3]) << 32); | ||
1032 | |||
1033 | err |= __get_user(u_ss_sp, &c->stack.sp); | ||
1034 | st.ss_sp = compat_ptr(u_ss_sp); | ||
1035 | err |= __get_user(st.ss_flags, &c->stack.flags); | ||
1036 | err |= __get_user(st.ss_size, &c->stack.size); | ||
1037 | if (err) | ||
1038 | goto sigsegv; | ||
1039 | |||
1040 | /* It is more difficult to avoid calling this function than to | ||
1041 | call it and ignore errors. */ | ||
1042 | old_fs = get_fs(); | ||
1043 | set_fs(KERNEL_DS); | ||
1044 | do_sigaltstack((stack_t __user *) &st, NULL, regs->u_regs[UREG_I6]); | ||
1045 | set_fs(old_fs); | ||
1046 | |||
1047 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
1048 | spin_lock_irq(¤t->sighand->siglock); | ||
1049 | current->blocked = set; | ||
1050 | recalc_sigpending(); | ||
1051 | spin_unlock_irq(¤t->sighand->siglock); | ||
1052 | regs->tpc = pc; | ||
1053 | regs->tnpc = npc | 1; | ||
1054 | if (test_thread_flag(TIF_32BIT)) { | ||
1055 | regs->tpc &= 0xffffffff; | ||
1056 | regs->tnpc &= 0xffffffff; | ||
1057 | } | ||
1058 | err |= __get_user(regs->y, &((*gr)[SVR4_Y])); | ||
1059 | err |= __get_user(psr, &((*gr)[SVR4_PSR])); | ||
1060 | regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC); | ||
1061 | regs->tstate |= psr_to_tstate_icc(psr); | ||
1062 | |||
1063 | /* Restore g[1..7] and o[0..7] registers */ | ||
1064 | for (i = 0; i < 7; i++) | ||
1065 | err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); | ||
1066 | for (i = 0; i < 8; i++) | ||
1067 | err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); | ||
1068 | if (err) | ||
1069 | goto sigsegv; | ||
1070 | |||
1071 | return -EINTR; | ||
1072 | sigsegv: | ||
1073 | return -EFAULT; | ||
1074 | } | ||
1075 | |||
1076 | static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, | 800 | static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, |
1077 | unsigned long signr, sigset_t *oldset, | 801 | unsigned long signr, sigset_t *oldset, |
1078 | siginfo_t *info) | 802 | siginfo_t *info) |
@@ -1216,20 +940,14 @@ sigsegv: | |||
1216 | 940 | ||
1217 | static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, | 941 | static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, |
1218 | siginfo_t *info, | 942 | siginfo_t *info, |
1219 | sigset_t *oldset, struct pt_regs *regs, | 943 | sigset_t *oldset, struct pt_regs *regs) |
1220 | int svr4_signal) | ||
1221 | { | 944 | { |
1222 | if (svr4_signal) | 945 | if (ka->sa.sa_flags & SA_SIGINFO) |
1223 | setup_svr4_frame32(&ka->sa, regs->tpc, regs->tnpc, | 946 | setup_rt_frame32(ka, regs, signr, oldset, info); |
1224 | regs, signr, oldset); | 947 | else if (test_thread_flag(TIF_NEWSIGNALS)) |
1225 | else { | 948 | new_setup_frame32(ka, regs, signr, oldset); |
1226 | if (ka->sa.sa_flags & SA_SIGINFO) | 949 | else |
1227 | setup_rt_frame32(ka, regs, signr, oldset, info); | 950 | setup_frame32(&ka->sa, regs, signr, oldset, info); |
1228 | else if (test_thread_flag(TIF_NEWSIGNALS)) | ||
1229 | new_setup_frame32(ka, regs, signr, oldset); | ||
1230 | else | ||
1231 | setup_frame32(&ka->sa, regs, signr, oldset, info); | ||
1232 | } | ||
1233 | spin_lock_irq(¤t->sighand->siglock); | 951 | spin_lock_irq(¤t->sighand->siglock); |
1234 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | 952 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); |
1235 | if (!(ka->sa.sa_flags & SA_NOMASK)) | 953 | if (!(ka->sa.sa_flags & SA_NOMASK)) |
@@ -1270,7 +988,6 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, | |||
1270 | struct signal_deliver_cookie cookie; | 988 | struct signal_deliver_cookie cookie; |
1271 | struct k_sigaction ka; | 989 | struct k_sigaction ka; |
1272 | int signr; | 990 | int signr; |
1273 | int svr4_signal = current->personality == PER_SVR4; | ||
1274 | 991 | ||
1275 | cookie.restart_syscall = restart_syscall; | 992 | cookie.restart_syscall = restart_syscall; |
1276 | cookie.orig_i0 = orig_i0; | 993 | cookie.orig_i0 = orig_i0; |
@@ -1279,8 +996,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, | |||
1279 | if (signr > 0) { | 996 | if (signr > 0) { |
1280 | if (cookie.restart_syscall) | 997 | if (cookie.restart_syscall) |
1281 | syscall_restart32(orig_i0, regs, &ka.sa); | 998 | syscall_restart32(orig_i0, regs, &ka.sa); |
1282 | handle_signal32(signr, &ka, &info, oldset, | 999 | handle_signal32(signr, &ka, &info, oldset, regs); |
1283 | regs, svr4_signal); | ||
1284 | 1000 | ||
1285 | /* a signal was successfully delivered; the saved | 1001 | /* a signal was successfully delivered; the saved |
1286 | * sigmask will have been stored in the signal frame, | 1002 | * sigmask will have been stored in the signal frame, |