aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/signal.c')
-rw-r--r--arch/sh/kernel/signal.c158
1 files changed, 83 insertions, 75 deletions
diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c
index b475c4d2405f..5213f5bc6ce0 100644
--- a/arch/sh/kernel/signal.c
+++ b/arch/sh/kernel/signal.c
@@ -8,7 +8,6 @@
8 * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima 8 * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima
9 * 9 *
10 */ 10 */
11
12#include <linux/sched.h> 11#include <linux/sched.h>
13#include <linux/mm.h> 12#include <linux/mm.h>
14#include <linux/smp.h> 13#include <linux/smp.h>
@@ -21,6 +20,7 @@
21#include <linux/unistd.h> 20#include <linux/unistd.h>
22#include <linux/stddef.h> 21#include <linux/stddef.h>
23#include <linux/tty.h> 22#include <linux/tty.h>
23#include <linux/elf.h>
24#include <linux/personality.h> 24#include <linux/personality.h>
25#include <linux/binfmts.h> 25#include <linux/binfmts.h>
26 26
@@ -29,12 +29,8 @@
29#include <asm/pgtable.h> 29#include <asm/pgtable.h>
30#include <asm/cacheflush.h> 30#include <asm/cacheflush.h>
31 31
32#define DEBUG_SIG 0
33
34#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
35 33
36asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
37
38/* 34/*
39 * Atomically swap in the new signal mask, and wait for a signal. 35 * Atomically swap in the new signal mask, and wait for a signal.
40 */ 36 */
@@ -43,51 +39,17 @@ sys_sigsuspend(old_sigset_t mask,
43 unsigned long r5, unsigned long r6, unsigned long r7, 39 unsigned long r5, unsigned long r6, unsigned long r7,
44 struct pt_regs regs) 40 struct pt_regs regs)
45{ 41{
46 sigset_t saveset;
47
48 mask &= _BLOCKABLE; 42 mask &= _BLOCKABLE;
49 spin_lock_irq(&current->sighand->siglock); 43 spin_lock_irq(&current->sighand->siglock);
50 saveset = current->blocked; 44 current->saved_sigmask = current->blocked;
51 siginitset(&current->blocked, mask); 45 siginitset(&current->blocked, mask);
52 recalc_sigpending(); 46 recalc_sigpending();
53 spin_unlock_irq(&current->sighand->siglock); 47 spin_unlock_irq(&current->sighand->siglock);
54 48
55 regs.regs[0] = -EINTR; 49 current->state = TASK_INTERRUPTIBLE;
56 while (1) { 50 schedule();
57 current->state = TASK_INTERRUPTIBLE; 51 set_thread_flag(TIF_RESTORE_SIGMASK);
58 schedule(); 52 return -ERESTARTNOHAND;
59 if (do_signal(&regs, &saveset))
60 return -EINTR;
61 }
62}
63
64asmlinkage int
65sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
66 unsigned long r6, unsigned long r7,
67 struct pt_regs regs)
68{
69 sigset_t saveset, newset;
70
71 /* XXX: Don't preclude handling different sized sigset_t's. */
72 if (sigsetsize != sizeof(sigset_t))
73 return -EINVAL;
74
75 if (copy_from_user(&newset, unewset, sizeof(newset)))
76 return -EFAULT;
77 sigdelsetmask(&newset, ~_BLOCKABLE);
78 spin_lock_irq(&current->sighand->siglock);
79 saveset = current->blocked;
80 current->blocked = newset;
81 recalc_sigpending();
82 spin_unlock_irq(&current->sighand->siglock);
83
84 regs.regs[0] = -EINTR;
85 while (1) {
86 current->state = TASK_INTERRUPTIBLE;
87 schedule();
88 if (do_signal(&regs, &saveset))
89 return -EINTR;
90 }
91} 53}
92 54
93asmlinkage int 55asmlinkage int
@@ -348,7 +310,12 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
348 return (void __user *)((sp - frame_size) & -8ul); 310 return (void __user *)((sp - frame_size) & -8ul);
349} 311}
350 312
351static void setup_frame(int sig, struct k_sigaction *ka, 313/* These symbols are defined with the addresses in the vsyscall page.
314 See vsyscall-trapa.S. */
315extern void __user __kernel_sigreturn;
316extern void __user __kernel_rt_sigreturn;
317
318static int setup_frame(int sig, struct k_sigaction *ka,
352 sigset_t *set, struct pt_regs *regs) 319 sigset_t *set, struct pt_regs *regs)
353{ 320{
354 struct sigframe __user *frame; 321 struct sigframe __user *frame;
@@ -368,15 +335,18 @@ static void setup_frame(int sig, struct k_sigaction *ka,
368 335
369 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); 336 err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
370 337
371 if (_NSIG_WORDS > 1) { 338 if (_NSIG_WORDS > 1)
372 err |= __copy_to_user(frame->extramask, &set->sig[1], 339 err |= __copy_to_user(frame->extramask, &set->sig[1],
373 sizeof(frame->extramask)); 340 sizeof(frame->extramask));
374 }
375 341
376 /* Set up to return from userspace. If provided, use a stub 342 /* Set up to return from userspace. If provided, use a stub
377 already in userspace. */ 343 already in userspace. */
378 if (ka->sa.sa_flags & SA_RESTORER) { 344 if (ka->sa.sa_flags & SA_RESTORER) {
379 regs->pr = (unsigned long) ka->sa.sa_restorer; 345 regs->pr = (unsigned long) ka->sa.sa_restorer;
346#ifdef CONFIG_VSYSCALL
347 } else if (likely(current->mm->context.vdso)) {
348 regs->pr = VDSO_SYM(&__kernel_sigreturn);
349#endif
380 } else { 350 } else {
381 /* Generate return code (system call to sigreturn) */ 351 /* Generate return code (system call to sigreturn) */
382 err |= __put_user(MOVW(7), &frame->retcode[0]); 352 err |= __put_user(MOVW(7), &frame->retcode[0]);
@@ -402,21 +372,22 @@ static void setup_frame(int sig, struct k_sigaction *ka,
402 372
403 set_fs(USER_DS); 373 set_fs(USER_DS);
404 374
405#if DEBUG_SIG 375 pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
406 printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", 376 current->comm, current->pid, frame, regs->pc, regs->pr);
407 current->comm, current->pid, frame, regs->pc, regs->pr);
408#endif
409 377
410 flush_cache_sigtramp(regs->pr); 378 flush_cache_sigtramp(regs->pr);
379
411 if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) 380 if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
412 flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); 381 flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
413 return; 382
383 return 0;
414 384
415give_sigsegv: 385give_sigsegv:
416 force_sigsegv(sig, current); 386 force_sigsegv(sig, current);
387 return -EFAULT;
417} 388}
418 389
419static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 390static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
420 sigset_t *set, struct pt_regs *regs) 391 sigset_t *set, struct pt_regs *regs)
421{ 392{
422 struct rt_sigframe __user *frame; 393 struct rt_sigframe __user *frame;
@@ -452,6 +423,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
452 already in userspace. */ 423 already in userspace. */
453 if (ka->sa.sa_flags & SA_RESTORER) { 424 if (ka->sa.sa_flags & SA_RESTORER) {
454 regs->pr = (unsigned long) ka->sa.sa_restorer; 425 regs->pr = (unsigned long) ka->sa.sa_restorer;
426#ifdef CONFIG_VSYSCALL
427 } else if (likely(current->mm->context.vdso)) {
428 regs->pr = VDSO_SYM(&__kernel_rt_sigreturn);
429#endif
455 } else { 430 } else {
456 /* Generate return code (system call to rt_sigreturn) */ 431 /* Generate return code (system call to rt_sigreturn) */
457 err |= __put_user(MOVW(7), &frame->retcode[0]); 432 err |= __put_user(MOVW(7), &frame->retcode[0]);
@@ -477,28 +452,31 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
477 452
478 set_fs(USER_DS); 453 set_fs(USER_DS);
479 454
480#if DEBUG_SIG 455 pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
481 printk("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", 456 current->comm, current->pid, frame, regs->pc, regs->pr);
482 current->comm, current->pid, frame, regs->pc, regs->pr);
483#endif
484 457
485 flush_cache_sigtramp(regs->pr); 458 flush_cache_sigtramp(regs->pr);
459
486 if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) 460 if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode))
487 flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); 461 flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES);
488 return; 462
463 return 0;
489 464
490give_sigsegv: 465give_sigsegv:
491 force_sigsegv(sig, current); 466 force_sigsegv(sig, current);
467 return -EFAULT;
492} 468}
493 469
494/* 470/*
495 * OK, we're invoking a handler 471 * OK, we're invoking a handler
496 */ 472 */
497 473
498static void 474static int
499handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, 475handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
500 sigset_t *oldset, struct pt_regs *regs) 476 sigset_t *oldset, struct pt_regs *regs)
501{ 477{
478 int ret;
479
502 /* Are we from a system call? */ 480 /* Are we from a system call? */
503 if (regs->tra >= 0) { 481 if (regs->tra >= 0) {
504 /* If so, check system call restarting.. */ 482 /* If so, check system call restarting.. */
@@ -539,19 +517,23 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
539 517
540 /* Set up the stack frame */ 518 /* Set up the stack frame */
541 if (ka->sa.sa_flags & SA_SIGINFO) 519 if (ka->sa.sa_flags & SA_SIGINFO)
542 setup_rt_frame(sig, ka, info, oldset, regs); 520 ret = setup_rt_frame(sig, ka, info, oldset, regs);
543 else 521 else
544 setup_frame(sig, ka, oldset, regs); 522 ret = setup_frame(sig, ka, oldset, regs);
545 523
546 if (ka->sa.sa_flags & SA_ONESHOT) 524 if (ka->sa.sa_flags & SA_ONESHOT)
547 ka->sa.sa_handler = SIG_DFL; 525 ka->sa.sa_handler = SIG_DFL;
548 526
549 spin_lock_irq(&current->sighand->siglock); 527 if (ret == 0) {
550 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 528 spin_lock_irq(&current->sighand->siglock);
551 if (!(ka->sa.sa_flags & SA_NODEFER)) 529 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
552 sigaddset(&current->blocked,sig); 530 if (!(ka->sa.sa_flags & SA_NODEFER))
553 recalc_sigpending(); 531 sigaddset(&current->blocked,sig);
554 spin_unlock_irq(&current->sighand->siglock); 532 recalc_sigpending();
533 spin_unlock_irq(&current->sighand->siglock);
534 }
535
536 return ret;
555} 537}
556 538
557/* 539/*
@@ -563,11 +545,12 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
563 * the kernel can handle, and then we build all the user-level signal handling 545 * the kernel can handle, and then we build all the user-level signal handling
564 * stack-frames in one go after that. 546 * stack-frames in one go after that.
565 */ 547 */
566int do_signal(struct pt_regs *regs, sigset_t *oldset) 548static void do_signal(struct pt_regs *regs, unsigned int save_r0)
567{ 549{
568 siginfo_t info; 550 siginfo_t info;
569 int signr; 551 int signr;
570 struct k_sigaction ka; 552 struct k_sigaction ka;
553 sigset_t *oldset;
571 554
572 /* 555 /*
573 * We want the common case to go fast, which 556 * We want the common case to go fast, which
@@ -576,19 +559,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
576 * if so. 559 * if so.
577 */ 560 */
578 if (!user_mode(regs)) 561 if (!user_mode(regs))
579 return 1; 562 return;
580 563
581 if (try_to_freeze()) 564 if (try_to_freeze())
582 goto no_signal; 565 goto no_signal;
583 566
584 if (!oldset) 567 if (test_thread_flag(TIF_RESTORE_SIGMASK))
568 oldset = &current->saved_sigmask;
569 else
585 oldset = &current->blocked; 570 oldset = &current->blocked;
586 571
587 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 572 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
588 if (signr > 0) { 573 if (signr > 0) {
589 /* Whee! Actually deliver the signal. */ 574 /* Whee! Actually deliver the signal. */
590 handle_signal(signr, &ka, &info, oldset, regs); 575 if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
591 return 1; 576 /* a signal was successfully delivered; the saved
577 * sigmask will have been stored in the signal frame,
578 * and will be restored by sigreturn, so we can simply
579 * clear the TIF_RESTORE_SIGMASK flag */
580 if (test_thread_flag(TIF_RESTORE_SIGMASK))
581 clear_thread_flag(TIF_RESTORE_SIGMASK);
582 }
592 } 583 }
593 584
594 no_signal: 585 no_signal:
@@ -597,10 +588,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
597 /* Restart the system call - no handlers present */ 588 /* Restart the system call - no handlers present */
598 if (regs->regs[0] == -ERESTARTNOHAND || 589 if (regs->regs[0] == -ERESTARTNOHAND ||
599 regs->regs[0] == -ERESTARTSYS || 590 regs->regs[0] == -ERESTARTSYS ||
600 regs->regs[0] == -ERESTARTNOINTR || 591 regs->regs[0] == -ERESTARTNOINTR) {
601 regs->regs[0] == -ERESTART_RESTARTBLOCK) { 592 regs->regs[0] = save_r0;
593 regs->pc -= 2;
594 } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
602 regs->pc -= 2; 595 regs->pc -= 2;
596 regs->regs[3] = __NR_restart_syscall;
603 } 597 }
604 } 598 }
605 return 0; 599
600 /* if there's no signal to deliver, we just put the saved sigmask
601 * back */
602 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
603 clear_thread_flag(TIF_RESTORE_SIGMASK);
604 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
605 }
606}
607
608asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
609 __u32 thread_info_flags)
610{
611 /* deal with pending signal delivery */
612 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
613 do_signal(regs, save_r0);
606} 614}