diff options
Diffstat (limited to 'arch/sparc')
| -rw-r--r-- | arch/sparc/kernel/entry.S | 56 | ||||
| -rw-r--r-- | arch/sparc/kernel/rtrap.S | 9 | ||||
| -rw-r--r-- | arch/sparc/kernel/signal.c | 117 | ||||
| -rw-r--r-- | arch/sparc/kernel/sparc_ksyms.c | 2 | ||||
| -rw-r--r-- | arch/sparc/kernel/systbls.S | 10 |
5 files changed, 44 insertions, 150 deletions
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 03ecb4e4614e..c51d08d218ef 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
| @@ -1277,62 +1277,6 @@ sys_sigstack: | |||
| 1277 | mov %l5, %o7 | 1277 | mov %l5, %o7 |
| 1278 | 1278 | ||
| 1279 | .align 4 | 1279 | .align 4 |
| 1280 | .globl sys_sigpause | ||
| 1281 | sys_sigpause: | ||
| 1282 | /* Note: %o0 already has correct value... */ | ||
| 1283 | call do_sigpause | ||
| 1284 | add %sp, STACKFRAME_SZ, %o1 | ||
| 1285 | |||
| 1286 | ld [%curptr + TI_FLAGS], %l5 | ||
| 1287 | andcc %l5, _TIF_SYSCALL_TRACE, %g0 | ||
| 1288 | be 1f | ||
| 1289 | nop | ||
| 1290 | |||
| 1291 | call syscall_trace | ||
| 1292 | nop | ||
| 1293 | |||
| 1294 | 1: | ||
| 1295 | /* We are returning to a signal handler. */ | ||
| 1296 | RESTORE_ALL | ||
| 1297 | |||
| 1298 | .align 4 | ||
| 1299 | .globl sys_sigsuspend | ||
| 1300 | sys_sigsuspend: | ||
| 1301 | call do_sigsuspend | ||
| 1302 | add %sp, STACKFRAME_SZ, %o0 | ||
| 1303 | |||
| 1304 | ld [%curptr + TI_FLAGS], %l5 | ||
| 1305 | andcc %l5, _TIF_SYSCALL_TRACE, %g0 | ||
| 1306 | be 1f | ||
| 1307 | nop | ||
| 1308 | |||
| 1309 | call syscall_trace | ||
| 1310 | nop | ||
| 1311 | |||
| 1312 | 1: | ||
| 1313 | /* We are returning to a signal handler. */ | ||
| 1314 | RESTORE_ALL | ||
| 1315 | |||
| 1316 | .align 4 | ||
| 1317 | .globl sys_rt_sigsuspend | ||
| 1318 | sys_rt_sigsuspend: | ||
| 1319 | /* Note: %o0, %o1 already have correct value... */ | ||
| 1320 | call do_rt_sigsuspend | ||
| 1321 | add %sp, STACKFRAME_SZ, %o2 | ||
| 1322 | |||
| 1323 | ld [%curptr + TI_FLAGS], %l5 | ||
| 1324 | andcc %l5, _TIF_SYSCALL_TRACE, %g0 | ||
| 1325 | be 1f | ||
| 1326 | nop | ||
| 1327 | |||
| 1328 | call syscall_trace | ||
| 1329 | nop | ||
| 1330 | |||
| 1331 | 1: | ||
| 1332 | /* We are returning to a signal handler. */ | ||
| 1333 | RESTORE_ALL | ||
| 1334 | |||
| 1335 | .align 4 | ||
| 1336 | .globl sys_sigreturn | 1280 | .globl sys_sigreturn |
| 1337 | sys_sigreturn: | 1281 | sys_sigreturn: |
| 1338 | call do_sigreturn | 1282 | call do_sigreturn |
diff --git a/arch/sparc/kernel/rtrap.S b/arch/sparc/kernel/rtrap.S index f7460d897e79..77ca6fd81253 100644 --- a/arch/sparc/kernel/rtrap.S +++ b/arch/sparc/kernel/rtrap.S | |||
| @@ -68,15 +68,14 @@ ret_trap_lockless_ipi: | |||
| 68 | 68 | ||
| 69 | ld [%curptr + TI_FLAGS], %g2 | 69 | ld [%curptr + TI_FLAGS], %g2 |
| 70 | signal_p: | 70 | signal_p: |
| 71 | andcc %g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0 | 71 | andcc %g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0 |
| 72 | bz,a ret_trap_continue | 72 | bz,a ret_trap_continue |
| 73 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr | 73 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr |
| 74 | 74 | ||
| 75 | clr %o0 | 75 | mov %l5, %o1 |
| 76 | mov %l5, %o2 | 76 | mov %l6, %o2 |
| 77 | mov %l6, %o3 | ||
| 78 | call do_signal | 77 | call do_signal |
| 79 | add %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr | 78 | add %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr |
| 80 | 79 | ||
| 81 | /* Fall through. */ | 80 | /* Fall through. */ |
| 82 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr | 81 | ld [%sp + STACKFRAME_SZ + PT_PSR], %t_psr |
diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 5f34d7dc2b89..0748d8147bbf 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c | |||
| @@ -35,9 +35,6 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, | |||
| 35 | void *fpqueue, unsigned long *fpqdepth); | 35 | void *fpqueue, unsigned long *fpqdepth); |
| 36 | extern void fpload(unsigned long *fpregs, unsigned long *fsr); | 36 | extern void fpload(unsigned long *fpregs, unsigned long *fsr); |
| 37 | 37 | ||
| 38 | asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, | ||
| 39 | unsigned long orig_o0, int restart_syscall); | ||
| 40 | |||
| 41 | /* Signal frames: the original one (compatible with SunOS): | 38 | /* Signal frames: the original one (compatible with SunOS): |
| 42 | * | 39 | * |
| 43 | * Set up a signal frame... Make the stack look the way SunOS | 40 | * Set up a signal frame... Make the stack look the way SunOS |
| @@ -95,98 +92,30 @@ struct rt_signal_frame { | |||
| 95 | #define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7))) | 92 | #define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame) + 7) & (~7))) |
| 96 | #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) | 93 | #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) |
| 97 | 94 | ||
| 98 | /* | 95 | static int _sigpause_common(old_sigset_t set) |
| 99 | * atomically swap in the new signal mask, and wait for a signal. | ||
| 100 | * This is really tricky on the Sparc, watch out... | ||
| 101 | */ | ||
| 102 | asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs) | ||
| 103 | { | 96 | { |
| 104 | sigset_t saveset; | ||
| 105 | |||
| 106 | set &= _BLOCKABLE; | 97 | set &= _BLOCKABLE; |
| 107 | spin_lock_irq(¤t->sighand->siglock); | 98 | spin_lock_irq(¤t->sighand->siglock); |
| 108 | saveset = current->blocked; | 99 | current->saved_sigmask = current->blocked; |
| 109 | siginitset(¤t->blocked, set); | 100 | siginitset(¤t->blocked, set); |
| 110 | recalc_sigpending(); | 101 | recalc_sigpending(); |
| 111 | spin_unlock_irq(¤t->sighand->siglock); | 102 | spin_unlock_irq(¤t->sighand->siglock); |
| 112 | 103 | ||
| 113 | regs->pc = regs->npc; | 104 | current->state = TASK_INTERRUPTIBLE; |
| 114 | regs->npc += 4; | 105 | schedule(); |
| 115 | 106 | set_thread_flag(TIF_RESTORE_SIGMASK); | |
| 116 | /* Condition codes and return value where set here for sigpause, | ||
| 117 | * and so got used by setup_frame, which again causes sigreturn() | ||
| 118 | * to return -EINTR. | ||
| 119 | */ | ||
| 120 | while (1) { | ||
| 121 | current->state = TASK_INTERRUPTIBLE; | ||
| 122 | schedule(); | ||
| 123 | /* | ||
| 124 | * Return -EINTR and set condition code here, | ||
| 125 | * so the interrupted system call actually returns | ||
| 126 | * these. | ||
| 127 | */ | ||
| 128 | regs->psr |= PSR_C; | ||
| 129 | regs->u_regs[UREG_I0] = EINTR; | ||
| 130 | if (do_signal(&saveset, regs, 0, 0)) | ||
| 131 | return; | ||
| 132 | } | ||
| 133 | } | ||
| 134 | 107 | ||
| 135 | asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs) | 108 | return -ERESTARTNOHAND; |
| 136 | { | ||
| 137 | _sigpause_common(set, regs); | ||
| 138 | } | 109 | } |
| 139 | 110 | ||
| 140 | asmlinkage void do_sigsuspend (struct pt_regs *regs) | 111 | asmlinkage int sys_sigpause(unsigned int set) |
| 141 | { | 112 | { |
| 142 | _sigpause_common(regs->u_regs[UREG_I0], regs); | 113 | return _sigpause_common(set); |
| 143 | } | 114 | } |
| 144 | 115 | ||
| 145 | asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, | 116 | asmlinkage int sys_sigsuspend(old_sigset_t set) |
| 146 | struct pt_regs *regs) | ||
| 147 | { | 117 | { |
| 148 | sigset_t oldset, set; | 118 | return _sigpause_common(set); |
| 149 | |||
| 150 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
| 151 | if (sigsetsize != sizeof(sigset_t)) { | ||
| 152 | regs->psr |= PSR_C; | ||
| 153 | regs->u_regs[UREG_I0] = EINVAL; | ||
| 154 | return; | ||
| 155 | } | ||
| 156 | |||
| 157 | if (copy_from_user(&set, uset, sizeof(set))) { | ||
| 158 | regs->psr |= PSR_C; | ||
| 159 | regs->u_regs[UREG_I0] = EFAULT; | ||
| 160 | return; | ||
| 161 | } | ||
| 162 | |||
| 163 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
| 164 | spin_lock_irq(¤t->sighand->siglock); | ||
| 165 | oldset = current->blocked; | ||
| 166 | current->blocked = set; | ||
| 167 | recalc_sigpending(); | ||
| 168 | spin_unlock_irq(¤t->sighand->siglock); | ||
| 169 | |||
| 170 | regs->pc = regs->npc; | ||
| 171 | regs->npc += 4; | ||
| 172 | |||
| 173 | /* Condition codes and return value where set here for sigpause, | ||
| 174 | * and so got used by setup_frame, which again causes sigreturn() | ||
| 175 | * to return -EINTR. | ||
| 176 | */ | ||
| 177 | while (1) { | ||
| 178 | current->state = TASK_INTERRUPTIBLE; | ||
| 179 | schedule(); | ||
| 180 | /* | ||
| 181 | * Return -EINTR and set condition code here, | ||
| 182 | * so the interrupted system call actually returns | ||
| 183 | * these. | ||
| 184 | */ | ||
| 185 | regs->psr |= PSR_C; | ||
| 186 | regs->u_regs[UREG_I0] = EINTR; | ||
| 187 | if (do_signal(&oldset, regs, 0, 0)) | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | } | 119 | } |
| 191 | 120 | ||
| 192 | static inline int | 121 | static inline int |
| @@ -1067,13 +996,13 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, | |||
| 1067 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 996 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
| 1068 | * mistake. | 997 | * mistake. |
| 1069 | */ | 998 | */ |
| 1070 | asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, | 999 | asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall) |
| 1071 | unsigned long orig_i0, int restart_syscall) | ||
| 1072 | { | 1000 | { |
| 1073 | siginfo_t info; | 1001 | siginfo_t info; |
| 1074 | struct sparc_deliver_cookie cookie; | 1002 | struct sparc_deliver_cookie cookie; |
| 1075 | struct k_sigaction ka; | 1003 | struct k_sigaction ka; |
| 1076 | int signr; | 1004 | int signr; |
| 1005 | sigset_t *oldset; | ||
| 1077 | 1006 | ||
| 1078 | /* | 1007 | /* |
| 1079 | * XXX Disable svr4 signal handling until solaris emulation works. | 1008 | * XXX Disable svr4 signal handling until solaris emulation works. |
| @@ -1089,7 +1018,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, | |||
| 1089 | cookie.restart_syscall = restart_syscall; | 1018 | cookie.restart_syscall = restart_syscall; |
| 1090 | cookie.orig_i0 = orig_i0; | 1019 | cookie.orig_i0 = orig_i0; |
| 1091 | 1020 | ||
| 1092 | if (!oldset) | 1021 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
| 1022 | oldset = ¤t->saved_sigmask; | ||
| 1023 | else | ||
| 1093 | oldset = ¤t->blocked; | 1024 | oldset = ¤t->blocked; |
| 1094 | 1025 | ||
| 1095 | signr = get_signal_to_deliver(&info, &ka, regs, &cookie); | 1026 | signr = get_signal_to_deliver(&info, &ka, regs, &cookie); |
| @@ -1098,7 +1029,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, | |||
| 1098 | syscall_restart(cookie.orig_i0, regs, &ka.sa); | 1029 | syscall_restart(cookie.orig_i0, regs, &ka.sa); |
| 1099 | handle_signal(signr, &ka, &info, oldset, | 1030 | handle_signal(signr, &ka, &info, oldset, |
| 1100 | regs, svr4_signal); | 1031 | regs, svr4_signal); |
| 1101 | return 1; | 1032 | /* a signal was successfully delivered; the saved |
| 1033 | * sigmask will have been stored in the signal frame, | ||
| 1034 | * and will be restored by sigreturn, so we can simply | ||
| 1035 | * clear the TIF_RESTORE_SIGMASK flag. | ||
| 1036 | */ | ||
| 1037 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
| 1038 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 1039 | return; | ||
| 1102 | } | 1040 | } |
| 1103 | if (cookie.restart_syscall && | 1041 | if (cookie.restart_syscall && |
| 1104 | (regs->u_regs[UREG_I0] == ERESTARTNOHAND || | 1042 | (regs->u_regs[UREG_I0] == ERESTARTNOHAND || |
| @@ -1115,7 +1053,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs, | |||
| 1115 | regs->pc -= 4; | 1053 | regs->pc -= 4; |
| 1116 | regs->npc -= 4; | 1054 | regs->npc -= 4; |
| 1117 | } | 1055 | } |
| 1118 | return 0; | 1056 | |
| 1057 | /* if there's no signal to deliver, we just put the saved sigmask | ||
| 1058 | * back | ||
| 1059 | */ | ||
| 1060 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
| 1061 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
| 1062 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
| 1063 | } | ||
| 1119 | } | 1064 | } |
| 1120 | 1065 | ||
| 1121 | asmlinkage int | 1066 | asmlinkage int |
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 0b0d492c953b..19b25399d7e4 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c | |||
| @@ -66,7 +66,6 @@ struct poll { | |||
| 66 | 66 | ||
| 67 | extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *); | 67 | extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *); |
| 68 | extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *); | 68 | extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *); |
| 69 | void _sigpause_common (unsigned int set, struct pt_regs *); | ||
| 70 | extern void (*__copy_1page)(void *, const void *); | 69 | extern void (*__copy_1page)(void *, const void *); |
| 71 | extern void __memmove(void *, const void *, __kernel_size_t); | 70 | extern void __memmove(void *, const void *, __kernel_size_t); |
| 72 | extern void (*bzero_1page)(void *); | 71 | extern void (*bzero_1page)(void *); |
| @@ -227,7 +226,6 @@ EXPORT_SYMBOL(kunmap_atomic); | |||
| 227 | /* Solaris/SunOS binary compatibility */ | 226 | /* Solaris/SunOS binary compatibility */ |
| 228 | EXPORT_SYMBOL(svr4_setcontext); | 227 | EXPORT_SYMBOL(svr4_setcontext); |
| 229 | EXPORT_SYMBOL(svr4_getcontext); | 228 | EXPORT_SYMBOL(svr4_getcontext); |
| 230 | EXPORT_SYMBOL(_sigpause_common); | ||
| 231 | 229 | ||
| 232 | EXPORT_SYMBOL(dump_thread); | 230 | EXPORT_SYMBOL(dump_thread); |
| 233 | 231 | ||
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index e457a40838fc..6877ae4cd1d9 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S | |||
| @@ -75,7 +75,10 @@ sys_call_table: | |||
| 75 | /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy | 75 | /*265*/ .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy |
| 76 | /*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink | 76 | /*270*/ .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink |
| 77 | /*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid | 77 | /*275*/ .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid |
| 78 | /*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl | 78 | /*280*/ .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat |
| 79 | /*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_newfstatat | ||
| 80 | /*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat | ||
| 81 | /*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll | ||
| 79 | 82 | ||
| 80 | #ifdef CONFIG_SUNOS_EMUL | 83 | #ifdef CONFIG_SUNOS_EMUL |
| 81 | /* Now the SunOS syscall table. */ | 84 | /* Now the SunOS syscall table. */ |
| @@ -181,6 +184,11 @@ sunos_sys_table: | |||
| 181 | .long sunos_nosys, sunos_nosys, sunos_nosys | 184 | .long sunos_nosys, sunos_nosys, sunos_nosys |
| 182 | .long sunos_nosys | 185 | .long sunos_nosys |
| 183 | /*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys | 186 | /*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys |
| 187 | .long sunos_nosys, sunos_nosys, sunos_nosys | ||
| 188 | .long sunos_nosys, sunos_nosys, sunos_nosys | ||
| 184 | .long sunos_nosys | 189 | .long sunos_nosys |
| 190 | /*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys | ||
| 191 | .long sunos_nosys, sunos_nosys, sunos_nosys | ||
| 192 | .long sunos_nosys, sunos_nosys, sunos_nosys | ||
| 185 | 193 | ||
| 186 | #endif | 194 | #endif |
