diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2006-01-19 05:42:49 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-01-19 05:42:49 -0500 |
commit | 2d7d5f05111a9d913131a2764d8b20157f8f758d (patch) | |
tree | 792deb7a3b9f72894d16affff1569a15b35e428b /arch/sparc64 | |
parent | f7111ceb5266750db2a1d193b98fb6a3d9b5a56a (diff) |
[SPARC]: Add support for *at(), ppoll, and pselect syscalls.
This also includes by necessity _TIF_RESTORE_SIGMASK support,
which actually resulted in a lot of cleanups.
The sparc signal handling code is quite a mess and I should
clean it up some day.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64')
-rw-r--r-- | arch/sparc64/kernel/entry.S | 23 | ||||
-rw-r--r-- | arch/sparc64/kernel/rtrap.S | 33 | ||||
-rw-r--r-- | arch/sparc64/kernel/signal.c | 151 | ||||
-rw-r--r-- | arch/sparc64/kernel/signal32.c | 122 | ||||
-rw-r--r-- | arch/sparc64/kernel/sparc64_ksyms.c | 4 | ||||
-rw-r--r-- | arch/sparc64/kernel/systbls.S | 21 | ||||
-rw-r--r-- | arch/sparc64/solaris/entry64.S | 2 |
7 files changed, 95 insertions, 261 deletions
diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 710002991888..e50e56e4ab61 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S | |||
@@ -1416,7 +1416,6 @@ execve_merge: | |||
1416 | add %sp, PTREGS_OFF, %o0 | 1416 | add %sp, PTREGS_OFF, %o0 |
1417 | 1417 | ||
1418 | .globl sys_pipe, sys_sigpause, sys_nis_syscall | 1418 | .globl sys_pipe, sys_sigpause, sys_nis_syscall |
1419 | .globl sys_sigsuspend, sys_rt_sigsuspend | ||
1420 | .globl sys_rt_sigreturn | 1419 | .globl sys_rt_sigreturn |
1421 | .globl sys_ptrace | 1420 | .globl sys_ptrace |
1422 | .globl sys_sigaltstack | 1421 | .globl sys_sigaltstack |
@@ -1440,28 +1439,6 @@ sys32_sigaltstack: | |||
1440 | mov %i6, %o2 | 1439 | mov %i6, %o2 |
1441 | #endif | 1440 | #endif |
1442 | .align 32 | 1441 | .align 32 |
1443 | sys_sigsuspend: add %sp, PTREGS_OFF, %o0 | ||
1444 | call do_sigsuspend | ||
1445 | add %o7, 1f-.-4, %o7 | ||
1446 | nop | ||
1447 | sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */ | ||
1448 | add %sp, PTREGS_OFF, %o2 | ||
1449 | call do_rt_sigsuspend | ||
1450 | add %o7, 1f-.-4, %o7 | ||
1451 | nop | ||
1452 | #ifdef CONFIG_COMPAT | ||
1453 | .globl sys32_rt_sigsuspend | ||
1454 | sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */ | ||
1455 | srl %o0, 0, %o0 | ||
1456 | add %sp, PTREGS_OFF, %o2 | ||
1457 | call do_rt_sigsuspend32 | ||
1458 | add %o7, 1f-.-4, %o7 | ||
1459 | #endif | ||
1460 | /* NOTE: %o0 has a correct value already */ | ||
1461 | sys_sigpause: add %sp, PTREGS_OFF, %o1 | ||
1462 | call do_sigpause | ||
1463 | add %o7, 1f-.-4, %o7 | ||
1464 | nop | ||
1465 | #ifdef CONFIG_COMPAT | 1442 | #ifdef CONFIG_COMPAT |
1466 | .globl sys32_sigreturn | 1443 | .globl sys32_sigreturn |
1467 | sys32_sigreturn: | 1444 | sys32_sigreturn: |
diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index 090dcca00d2a..b80eba0081ca 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S | |||
@@ -53,14 +53,13 @@ __handle_user_windows: | |||
53 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate | 53 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate |
54 | ldx [%g6 + TI_FLAGS], %l0 | 54 | ldx [%g6 + TI_FLAGS], %l0 |
55 | 55 | ||
56 | 1: andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 | 56 | 1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 |
57 | be,pt %xcc, __handle_user_windows_continue | 57 | be,pt %xcc, __handle_user_windows_continue |
58 | nop | 58 | nop |
59 | clr %o0 | 59 | mov %l5, %o1 |
60 | mov %l5, %o2 | 60 | mov %l6, %o2 |
61 | mov %l6, %o3 | 61 | add %sp, PTREGS_OFF, %o0 |
62 | add %sp, PTREGS_OFF, %o1 | 62 | mov %l0, %o3 |
63 | mov %l0, %o4 | ||
64 | 63 | ||
65 | call do_notify_resume | 64 | call do_notify_resume |
66 | wrpr %g0, RTRAP_PSTATE, %pstate | 65 | wrpr %g0, RTRAP_PSTATE, %pstate |
@@ -96,15 +95,14 @@ __handle_perfctrs: | |||
96 | wrpr %g0, RTRAP_PSTATE, %pstate | 95 | wrpr %g0, RTRAP_PSTATE, %pstate |
97 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate | 96 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate |
98 | ldx [%g6 + TI_FLAGS], %l0 | 97 | ldx [%g6 + TI_FLAGS], %l0 |
99 | 1: andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 | 98 | 1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 |
100 | 99 | ||
101 | be,pt %xcc, __handle_perfctrs_continue | 100 | be,pt %xcc, __handle_perfctrs_continue |
102 | sethi %hi(TSTATE_PEF), %o0 | 101 | sethi %hi(TSTATE_PEF), %o0 |
103 | clr %o0 | 102 | mov %l5, %o1 |
104 | mov %l5, %o2 | 103 | mov %l6, %o2 |
105 | mov %l6, %o3 | 104 | add %sp, PTREGS_OFF, %o0 |
106 | add %sp, PTREGS_OFF, %o1 | 105 | mov %l0, %o3 |
107 | mov %l0, %o4 | ||
108 | call do_notify_resume | 106 | call do_notify_resume |
109 | 107 | ||
110 | wrpr %g0, RTRAP_PSTATE, %pstate | 108 | wrpr %g0, RTRAP_PSTATE, %pstate |
@@ -129,11 +127,10 @@ __handle_userfpu: | |||
129 | ba,a,pt %xcc, __handle_userfpu_continue | 127 | ba,a,pt %xcc, __handle_userfpu_continue |
130 | 128 | ||
131 | __handle_signal: | 129 | __handle_signal: |
132 | clr %o0 | 130 | mov %l5, %o1 |
133 | mov %l5, %o2 | 131 | mov %l6, %o2 |
134 | mov %l6, %o3 | 132 | add %sp, PTREGS_OFF, %o0 |
135 | add %sp, PTREGS_OFF, %o1 | 133 | mov %l0, %o3 |
136 | mov %l0, %o4 | ||
137 | call do_notify_resume | 134 | call do_notify_resume |
138 | wrpr %g0, RTRAP_PSTATE, %pstate | 135 | wrpr %g0, RTRAP_PSTATE, %pstate |
139 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate | 136 | wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate |
@@ -200,7 +197,7 @@ __handle_preemption_continue: | |||
200 | andcc %l1, %o0, %g0 | 197 | andcc %l1, %o0, %g0 |
201 | andcc %l0, _TIF_NEED_RESCHED, %g0 | 198 | andcc %l0, _TIF_NEED_RESCHED, %g0 |
202 | bne,pn %xcc, __handle_preemption | 199 | bne,pn %xcc, __handle_preemption |
203 | andcc %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0 | 200 | andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 |
204 | bne,pn %xcc, __handle_signal | 201 | bne,pn %xcc, __handle_signal |
205 | __handle_signal_continue: | 202 | __handle_signal_continue: |
206 | ldub [%g6 + TI_WSAVED], %o2 | 203 | ldub [%g6 + TI_WSAVED], %o2 |
diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 60f5dfabb1e1..ca11a4c457d4 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c | |||
@@ -36,9 +36,6 @@ | |||
36 | 36 | ||
37 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 37 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
38 | 38 | ||
39 | static int do_signal(sigset_t *oldset, struct pt_regs * regs, | ||
40 | unsigned long orig_o0, int ret_from_syscall); | ||
41 | |||
42 | /* {set, get}context() needed for 64-bit SparcLinux userland. */ | 39 | /* {set, get}context() needed for 64-bit SparcLinux userland. */ |
43 | asmlinkage void sparc64_set_context(struct pt_regs *regs) | 40 | asmlinkage void sparc64_set_context(struct pt_regs *regs) |
44 | { | 41 | { |
@@ -242,114 +239,29 @@ struct rt_signal_frame { | |||
242 | /* Align macros */ | 239 | /* Align macros */ |
243 | #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) | 240 | #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) |
244 | 241 | ||
245 | /* | 242 | static long _sigpause_common(old_sigset_t set) |
246 | * atomically swap in the new signal mask, and wait for a signal. | ||
247 | * This is really tricky on the Sparc, watch out... | ||
248 | */ | ||
249 | asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs) | ||
250 | { | 243 | { |
251 | sigset_t saveset; | ||
252 | |||
253 | #ifdef CONFIG_SPARC32_COMPAT | ||
254 | if (test_thread_flag(TIF_32BIT)) { | ||
255 | extern asmlinkage void _sigpause32_common(compat_old_sigset_t, | ||
256 | struct pt_regs *); | ||
257 | _sigpause32_common(set, regs); | ||
258 | return; | ||
259 | } | ||
260 | #endif | ||
261 | set &= _BLOCKABLE; | 244 | set &= _BLOCKABLE; |
262 | spin_lock_irq(¤t->sighand->siglock); | 245 | spin_lock_irq(¤t->sighand->siglock); |
263 | saveset = current->blocked; | 246 | current->saved_sigmask = current->blocked; |
264 | siginitset(¤t->blocked, set); | 247 | siginitset(¤t->blocked, set); |
265 | recalc_sigpending(); | 248 | recalc_sigpending(); |
266 | spin_unlock_irq(¤t->sighand->siglock); | 249 | spin_unlock_irq(¤t->sighand->siglock); |
267 | |||
268 | if (test_thread_flag(TIF_32BIT)) { | ||
269 | regs->tpc = (regs->tnpc & 0xffffffff); | ||
270 | regs->tnpc = (regs->tnpc + 4) & 0xffffffff; | ||
271 | } else { | ||
272 | regs->tpc = regs->tnpc; | ||
273 | regs->tnpc += 4; | ||
274 | } | ||
275 | 250 | ||
276 | /* Condition codes and return value where set here for sigpause, | 251 | current->state = TASK_INTERRUPTIBLE; |
277 | * and so got used by setup_frame, which again causes sigreturn() | 252 | schedule(); |
278 | * to return -EINTR. | 253 | set_thread_flag(TIF_RESTORE_SIGMASK); |
279 | */ | 254 | return -ERESTARTNOHAND; |
280 | while (1) { | ||
281 | current->state = TASK_INTERRUPTIBLE; | ||
282 | schedule(); | ||
283 | /* | ||
284 | * Return -EINTR and set condition code here, | ||
285 | * so the interrupted system call actually returns | ||
286 | * these. | ||
287 | */ | ||
288 | regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); | ||
289 | regs->u_regs[UREG_I0] = EINTR; | ||
290 | if (do_signal(&saveset, regs, 0, 0)) | ||
291 | return; | ||
292 | } | ||
293 | } | 255 | } |
294 | 256 | ||
295 | asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs) | 257 | asmlinkage long sys_sigpause(unsigned int set) |
296 | { | 258 | { |
297 | _sigpause_common(set, regs); | 259 | return _sigpause_common(set); |
298 | } | 260 | } |
299 | 261 | ||
300 | asmlinkage void do_sigsuspend(struct pt_regs *regs) | 262 | asmlinkage long sys_sigsuspend(old_sigset_t set) |
301 | { | 263 | { |
302 | _sigpause_common(regs->u_regs[UREG_I0], regs); | 264 | return _sigpause_common(set); |
303 | } | ||
304 | |||
305 | asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, struct pt_regs *regs) | ||
306 | { | ||
307 | sigset_t oldset, set; | ||
308 | |||
309 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
310 | if (sigsetsize != sizeof(sigset_t)) { | ||
311 | regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); | ||
312 | regs->u_regs[UREG_I0] = EINVAL; | ||
313 | return; | ||
314 | } | ||
315 | if (copy_from_user(&set, uset, sizeof(set))) { | ||
316 | regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); | ||
317 | regs->u_regs[UREG_I0] = EFAULT; | ||
318 | return; | ||
319 | } | ||
320 | |||
321 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
322 | spin_lock_irq(¤t->sighand->siglock); | ||
323 | oldset = current->blocked; | ||
324 | current->blocked = set; | ||
325 | recalc_sigpending(); | ||
326 | spin_unlock_irq(¤t->sighand->siglock); | ||
327 | |||
328 | if (test_thread_flag(TIF_32BIT)) { | ||
329 | regs->tpc = (regs->tnpc & 0xffffffff); | ||
330 | regs->tnpc = (regs->tnpc + 4) & 0xffffffff; | ||
331 | } else { | ||
332 | regs->tpc = regs->tnpc; | ||
333 | regs->tnpc += 4; | ||
334 | } | ||
335 | |||
336 | /* Condition codes and return value where set here for sigpause, | ||
337 | * and so got used by setup_frame, which again causes sigreturn() | ||
338 | * to return -EINTR. | ||
339 | */ | ||
340 | while (1) { | ||
341 | current->state = TASK_INTERRUPTIBLE; | ||
342 | schedule(); | ||
343 | /* | ||
344 | * Return -EINTR and set condition code here, | ||
345 | * so the interrupted system call actually returns | ||
346 | * these. | ||
347 | */ | ||
348 | regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY); | ||
349 | regs->u_regs[UREG_I0] = EINTR; | ||
350 | if (do_signal(&oldset, regs, 0, 0)) | ||
351 | return; | ||
352 | } | ||
353 | } | 265 | } |
354 | 266 | ||
355 | static inline int | 267 | static inline int |
@@ -607,26 +519,29 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, | |||
607 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 519 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
608 | * mistake. | 520 | * mistake. |
609 | */ | 521 | */ |
610 | static int do_signal(sigset_t *oldset, struct pt_regs * regs, | 522 | static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall) |
611 | unsigned long orig_i0, int restart_syscall) | ||
612 | { | 523 | { |
613 | siginfo_t info; | 524 | siginfo_t info; |
614 | struct signal_deliver_cookie cookie; | 525 | struct signal_deliver_cookie cookie; |
615 | struct k_sigaction ka; | 526 | struct k_sigaction ka; |
616 | int signr; | 527 | int signr; |
528 | sigset_t *oldset; | ||
617 | 529 | ||
618 | cookie.restart_syscall = restart_syscall; | 530 | cookie.restart_syscall = restart_syscall; |
619 | cookie.orig_i0 = orig_i0; | 531 | cookie.orig_i0 = orig_i0; |
620 | 532 | ||
621 | if (!oldset) | 533 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
534 | oldset = ¤t->saved_sigmask; | ||
535 | else | ||
622 | oldset = ¤t->blocked; | 536 | oldset = ¤t->blocked; |
623 | 537 | ||
624 | #ifdef CONFIG_SPARC32_COMPAT | 538 | #ifdef CONFIG_SPARC32_COMPAT |
625 | if (test_thread_flag(TIF_32BIT)) { | 539 | if (test_thread_flag(TIF_32BIT)) { |
626 | extern int do_signal32(sigset_t *, struct pt_regs *, | 540 | extern void do_signal32(sigset_t *, struct pt_regs *, |
627 | unsigned long, int); | 541 | unsigned long, int); |
628 | return do_signal32(oldset, regs, orig_i0, | 542 | do_signal32(oldset, regs, orig_i0, |
629 | cookie.restart_syscall); | 543 | cookie.restart_syscall); |
544 | return; | ||
630 | } | 545 | } |
631 | #endif | 546 | #endif |
632 | 547 | ||
@@ -635,7 +550,15 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, | |||
635 | if (cookie.restart_syscall) | 550 | if (cookie.restart_syscall) |
636 | syscall_restart(orig_i0, regs, &ka.sa); | 551 | syscall_restart(orig_i0, regs, &ka.sa); |
637 | handle_signal(signr, &ka, &info, oldset, regs); | 552 | handle_signal(signr, &ka, &info, oldset, regs); |
638 | return 1; | 553 | |
554 | /* a signal was successfully delivered; the saved | ||
555 | * sigmask will have been stored in the signal frame, | ||
556 | * and will be restored by sigreturn, so we can simply | ||
557 | * clear the TIF_RESTORE_SIGMASK flag. | ||
558 | */ | ||
559 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
560 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
561 | return; | ||
639 | } | 562 | } |
640 | if (cookie.restart_syscall && | 563 | if (cookie.restart_syscall && |
641 | (regs->u_regs[UREG_I0] == ERESTARTNOHAND || | 564 | (regs->u_regs[UREG_I0] == ERESTARTNOHAND || |
@@ -652,15 +575,21 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs, | |||
652 | regs->tpc -= 4; | 575 | regs->tpc -= 4; |
653 | regs->tnpc -= 4; | 576 | regs->tnpc -= 4; |
654 | } | 577 | } |
655 | return 0; | 578 | |
579 | /* if there's no signal to deliver, we just put the saved sigmask | ||
580 | * back | ||
581 | */ | ||
582 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
583 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
584 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
585 | } | ||
656 | } | 586 | } |
657 | 587 | ||
658 | void do_notify_resume(sigset_t *oldset, struct pt_regs *regs, | 588 | void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall, |
659 | unsigned long orig_i0, int restart_syscall, | ||
660 | unsigned long thread_info_flags) | 589 | unsigned long thread_info_flags) |
661 | { | 590 | { |
662 | if (thread_info_flags & _TIF_SIGPENDING) | 591 | if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) |
663 | do_signal(oldset, regs, orig_i0, restart_syscall); | 592 | do_signal(regs, orig_i0, restart_syscall); |
664 | } | 593 | } |
665 | 594 | ||
666 | void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) | 595 | void ptrace_signal_deliver(struct pt_regs *regs, void *cookie) |
diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 009a86e5ded4..708ba9b42cda 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c | |||
@@ -32,9 +32,6 @@ | |||
32 | 32 | ||
33 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 33 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
34 | 34 | ||
35 | int do_signal32(sigset_t *oldset, struct pt_regs *regs, | ||
36 | unsigned long orig_o0, int ret_from_syscall); | ||
37 | |||
38 | /* Signal frames: the original one (compatible with SunOS): | 35 | /* Signal frames: the original one (compatible with SunOS): |
39 | * | 36 | * |
40 | * Set up a signal frame... Make the stack look the way SunOS | 37 | * Set up a signal frame... Make the stack look the way SunOS |
@@ -226,102 +223,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from) | |||
226 | return 0; | 223 | return 0; |
227 | } | 224 | } |
228 | 225 | ||
229 | /* | ||
230 | * atomically swap in the new signal mask, and wait for a signal. | ||
231 | * This is really tricky on the Sparc, watch out... | ||
232 | */ | ||
233 | asmlinkage void _sigpause32_common(compat_old_sigset_t set, struct pt_regs *regs) | ||
234 | { | ||
235 | sigset_t saveset; | ||
236 | |||
237 | set &= _BLOCKABLE; | ||
238 | spin_lock_irq(¤t->sighand->siglock); | ||
239 | saveset = current->blocked; | ||
240 | siginitset(¤t->blocked, set); | ||
241 | recalc_sigpending(); | ||
242 | spin_unlock_irq(¤t->sighand->siglock); | ||
243 | |||
244 | regs->tpc = regs->tnpc; | ||
245 | regs->tnpc += 4; | ||
246 | if (test_thread_flag(TIF_32BIT)) { | ||
247 | regs->tpc &= 0xffffffff; | ||
248 | regs->tnpc &= 0xffffffff; | ||
249 | } | ||
250 | |||
251 | /* Condition codes and return value where set here for sigpause, | ||
252 | * and so got used by setup_frame, which again causes sigreturn() | ||
253 | * to return -EINTR. | ||
254 | */ | ||
255 | while (1) { | ||
256 | current->state = TASK_INTERRUPTIBLE; | ||
257 | schedule(); | ||
258 | /* | ||
259 | * Return -EINTR and set condition code here, | ||
260 | * so the interrupted system call actually returns | ||
261 | * these. | ||
262 | */ | ||
263 | regs->tstate |= TSTATE_ICARRY; | ||
264 | regs->u_regs[UREG_I0] = EINTR; | ||
265 | if (do_signal32(&saveset, regs, 0, 0)) | ||
266 | return; | ||
267 | } | ||
268 | } | ||
269 | |||
270 | asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs) | ||
271 | { | ||
272 | sigset_t oldset, set; | ||
273 | compat_sigset_t set32; | ||
274 | |||
275 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
276 | if (((compat_size_t)sigsetsize) != sizeof(sigset_t)) { | ||
277 | regs->tstate |= TSTATE_ICARRY; | ||
278 | regs->u_regs[UREG_I0] = EINVAL; | ||
279 | return; | ||
280 | } | ||
281 | if (copy_from_user(&set32, compat_ptr(uset), sizeof(set32))) { | ||
282 | regs->tstate |= TSTATE_ICARRY; | ||
283 | regs->u_regs[UREG_I0] = EFAULT; | ||
284 | return; | ||
285 | } | ||
286 | switch (_NSIG_WORDS) { | ||
287 | case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32); | ||
288 | case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32); | ||
289 | case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32); | ||
290 | case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32); | ||
291 | } | ||
292 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
293 | spin_lock_irq(¤t->sighand->siglock); | ||
294 | oldset = current->blocked; | ||
295 | current->blocked = set; | ||
296 | recalc_sigpending(); | ||
297 | spin_unlock_irq(¤t->sighand->siglock); | ||
298 | |||
299 | regs->tpc = regs->tnpc; | ||
300 | regs->tnpc += 4; | ||
301 | if (test_thread_flag(TIF_32BIT)) { | ||
302 | regs->tpc &= 0xffffffff; | ||
303 | regs->tnpc &= 0xffffffff; | ||
304 | } | ||
305 | |||
306 | /* Condition codes and return value where set here for sigpause, | ||
307 | * and so got used by setup_frame, which again causes sigreturn() | ||
308 | * to return -EINTR. | ||
309 | */ | ||
310 | while (1) { | ||
311 | current->state = TASK_INTERRUPTIBLE; | ||
312 | schedule(); | ||
313 | /* | ||
314 | * Return -EINTR and set condition code here, | ||
315 | * so the interrupted system call actually returns | ||
316 | * these. | ||
317 | */ | ||
318 | regs->tstate |= TSTATE_ICARRY; | ||
319 | regs->u_regs[UREG_I0] = EINTR; | ||
320 | if (do_signal32(&oldset, regs, 0, 0)) | ||
321 | return; | ||
322 | } | ||
323 | } | ||
324 | |||
325 | static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) | 226 | static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu) |
326 | { | 227 | { |
327 | unsigned long *fpregs = current_thread_info()->fpregs; | 228 | unsigned long *fpregs = current_thread_info()->fpregs; |
@@ -1362,8 +1263,8 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs | |||
1362 | * want to handle. Thus you cannot kill init even with a SIGKILL even by | 1263 | * want to handle. Thus you cannot kill init even with a SIGKILL even by |
1363 | * mistake. | 1264 | * mistake. |
1364 | */ | 1265 | */ |
1365 | int do_signal32(sigset_t *oldset, struct pt_regs * regs, | 1266 | void do_signal32(sigset_t *oldset, struct pt_regs * regs, |
1366 | unsigned long orig_i0, int restart_syscall) | 1267 | unsigned long orig_i0, int restart_syscall) |
1367 | { | 1268 | { |
1368 | siginfo_t info; | 1269 | siginfo_t info; |
1369 | struct signal_deliver_cookie cookie; | 1270 | struct signal_deliver_cookie cookie; |
@@ -1380,7 +1281,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs, | |||
1380 | syscall_restart32(orig_i0, regs, &ka.sa); | 1281 | syscall_restart32(orig_i0, regs, &ka.sa); |
1381 | handle_signal32(signr, &ka, &info, oldset, | 1282 | handle_signal32(signr, &ka, &info, oldset, |
1382 | regs, svr4_signal); | 1283 | regs, svr4_signal); |
1383 | return 1; | 1284 | |
1285 | /* a signal was successfully delivered; the saved | ||
1286 | * sigmask will have been stored in the signal frame, | ||
1287 | * and will be restored by sigreturn, so we can simply | ||
1288 | * clear the TIF_RESTORE_SIGMASK flag. | ||
1289 | */ | ||
1290 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
1291 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
1292 | return; | ||
1384 | } | 1293 | } |
1385 | if (cookie.restart_syscall && | 1294 | if (cookie.restart_syscall && |
1386 | (regs->u_regs[UREG_I0] == ERESTARTNOHAND || | 1295 | (regs->u_regs[UREG_I0] == ERESTARTNOHAND || |
@@ -1397,7 +1306,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs, | |||
1397 | regs->tpc -= 4; | 1306 | regs->tpc -= 4; |
1398 | regs->tnpc -= 4; | 1307 | regs->tnpc -= 4; |
1399 | } | 1308 | } |
1400 | return 0; | 1309 | |
1310 | /* if there's no signal to deliver, we just put the saved sigmask | ||
1311 | * back | ||
1312 | */ | ||
1313 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
1314 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
1315 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
1316 | } | ||
1401 | } | 1317 | } |
1402 | 1318 | ||
1403 | struct sigstack32 { | 1319 | struct sigstack32 { |
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index d177d7e5c9d3..3c06bfb92a8c 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
@@ -69,7 +69,6 @@ struct poll { | |||
69 | 69 | ||
70 | extern void die_if_kernel(char *str, struct pt_regs *regs); | 70 | extern void die_if_kernel(char *str, struct pt_regs *regs); |
71 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 71 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
72 | void _sigpause_common (unsigned int set, struct pt_regs *); | ||
73 | extern void *__bzero(void *, size_t); | 72 | extern void *__bzero(void *, size_t); |
74 | extern void *__memscan_zero(void *, size_t); | 73 | extern void *__memscan_zero(void *, size_t); |
75 | extern void *__memscan_generic(void *, int, size_t); | 74 | extern void *__memscan_generic(void *, int, size_t); |
@@ -236,9 +235,10 @@ EXPORT_SYMBOL(pci_dma_supported); | |||
236 | /* I/O device mmaping on Sparc64. */ | 235 | /* I/O device mmaping on Sparc64. */ |
237 | EXPORT_SYMBOL(io_remap_pfn_range); | 236 | EXPORT_SYMBOL(io_remap_pfn_range); |
238 | 237 | ||
238 | #ifdef CONFIG_COMPAT | ||
239 | /* Solaris/SunOS binary compatibility */ | 239 | /* Solaris/SunOS binary compatibility */ |
240 | EXPORT_SYMBOL(_sigpause_common); | ||
241 | EXPORT_SYMBOL(verify_compat_iovec); | 240 | EXPORT_SYMBOL(verify_compat_iovec); |
241 | #endif | ||
242 | 242 | ||
243 | EXPORT_SYMBOL(dump_fpu); | 243 | EXPORT_SYMBOL(dump_fpu); |
244 | EXPORT_SYMBOL(pte_alloc_one_kernel); | 244 | EXPORT_SYMBOL(pte_alloc_one_kernel); |
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 98d24bc00044..5ed1a17cd5b9 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S | |||
@@ -41,7 +41,7 @@ sys_call_table32: | |||
41 | /*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid | 41 | /*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid |
42 | .word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall | 42 | .word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall |
43 | /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending | 43 | /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending |
44 | .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid | 44 | .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid |
45 | /*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall | 45 | /*110*/ .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall |
46 | .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd | 46 | .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd |
47 | /*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod | 47 | /*120*/ .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod |
@@ -76,7 +76,10 @@ sys_call_table32: | |||
76 | .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy | 76 | .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy |
77 | /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink | 77 | /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink |
78 | .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid | 78 | .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid |
79 | /*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl | 79 | /*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat |
80 | .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, compat_sys_newfstatat | ||
81 | /*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat | ||
82 | .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll | ||
80 | 83 | ||
81 | #endif /* CONFIG_COMPAT */ | 84 | #endif /* CONFIG_COMPAT */ |
82 | 85 | ||
@@ -142,7 +145,10 @@ sys_call_table: | |||
142 | .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy | 145 | .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy |
143 | /*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink | 146 | /*270*/ .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink |
144 | .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid | 147 | .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid |
145 | /*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl | 148 | /*280*/ .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat |
149 | .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, compat_sys_newfstatat | ||
150 | /*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat | ||
151 | .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll | ||
146 | 152 | ||
147 | #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ | 153 | #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ |
148 | defined(CONFIG_SOLARIS_EMUL_MODULE) | 154 | defined(CONFIG_SOLARIS_EMUL_MODULE) |
@@ -239,13 +245,20 @@ sunos_sys_table: | |||
239 | /*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys | 245 | /*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys |
240 | .word sunos_nosys, sunos_nosys, sunos_nosys | 246 | .word sunos_nosys, sunos_nosys, sunos_nosys |
241 | .word sunos_nosys, sunos_nosys, sunos_nosys | 247 | .word sunos_nosys, sunos_nosys, sunos_nosys |
248 | .word sunos_nosys | ||
249 | /*260*/ .word sunos_nosys, sunos_nosys, sunos_nosys | ||
242 | .word sunos_nosys, sunos_nosys, sunos_nosys | 250 | .word sunos_nosys, sunos_nosys, sunos_nosys |
243 | .word sunos_nosys, sunos_nosys, sunos_nosys | 251 | .word sunos_nosys, sunos_nosys, sunos_nosys |
252 | .word sunos_nosys | ||
253 | /*270*/ .word sunos_nosys, sunos_nosys, sunos_nosys | ||
244 | .word sunos_nosys, sunos_nosys, sunos_nosys | 254 | .word sunos_nosys, sunos_nosys, sunos_nosys |
245 | .word sunos_nosys, sunos_nosys, sunos_nosys | 255 | .word sunos_nosys, sunos_nosys, sunos_nosys |
256 | .word sunos_nosys | ||
257 | /*280*/ .word sunos_nosys, sunos_nosys, sunos_nosys | ||
246 | .word sunos_nosys, sunos_nosys, sunos_nosys | 258 | .word sunos_nosys, sunos_nosys, sunos_nosys |
247 | .word sunos_nosys, sunos_nosys, sunos_nosys | 259 | .word sunos_nosys, sunos_nosys, sunos_nosys |
260 | .word sunos_nosys | ||
261 | /*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys | ||
248 | .word sunos_nosys, sunos_nosys, sunos_nosys | 262 | .word sunos_nosys, sunos_nosys, sunos_nosys |
249 | .word sunos_nosys, sunos_nosys, sunos_nosys | 263 | .word sunos_nosys, sunos_nosys, sunos_nosys |
250 | .word sunos_nosys | ||
251 | #endif | 264 | #endif |
diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S index 4b6ae583c0a3..eb314ed23cdb 100644 --- a/arch/sparc64/solaris/entry64.S +++ b/arch/sparc64/solaris/entry64.S | |||
@@ -180,6 +180,8 @@ solaris_sigsuspend: | |||
180 | nop | 180 | nop |
181 | call sys_sigsuspend | 181 | call sys_sigsuspend |
182 | stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] | 182 | stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] |
183 | b,pt %xcc, ret_from_solaris | ||
184 | nop | ||
183 | 185 | ||
184 | .globl solaris_getpid | 186 | .globl solaris_getpid |
185 | solaris_getpid: | 187 | solaris_getpid: |