Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 19 Jun 2007 15:07:34 +0000 (08:07 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Tue, 19 Jun 2007 15:07:34 +0000 (08:07 -0700)
* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6:
  sh: Handle -ERESTART_RESTARTBLOCK for restartable syscalls.
  sh: oops_enter()/oops_exit() in die().
  sh: Fix restartable syscall arg5 clobbering.

arch/sh/kernel/signal.c
arch/sh/kernel/traps.c

index b32c35a7c0a3e42512765962e8b71c0c1096a5c8..e323e299878b7a101087ae1d08d84bf6295776f1 100644 (file)
@@ -268,7 +268,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
 badframe:
        force_sig(SIGSEGV, current);
        return 0;
-}      
+}
 
 /*
  * Set up a signal frame.
@@ -481,7 +481,7 @@ give_sigsegv:
 
 static int
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-             sigset_t *oldset, struct pt_regs *regs)
+             sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
 {
        int ret;
 
@@ -489,6 +489,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
        if (regs->tra >= 0) {
                /* If so, check system call restarting.. */
                switch (regs->regs[0]) {
+                       case -ERESTART_RESTARTBLOCK:
                        case -ERESTARTNOHAND:
                                regs->regs[0] = -EINTR;
                                break;
@@ -500,6 +501,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
                                }
                        /* fallthrough */
                        case -ERESTARTNOINTR:
+                               regs->regs[0] = save_r0;
                                regs->pc -= instruction_size(
                                                ctrl_inw(regs->pc - 4));
                                break;
@@ -583,7 +585,8 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
+               if (handle_signal(signr, &ka, &info, oldset,
+                                 regs, save_r0) == 0) {
                        /* a signal was successfully delivered; the saved
                         * sigmask will have been stored in the signal frame,
                         * and will be restored by sigreturn, so we can simply
index 5b75cb6f8f9baad9aec571397e3cc2dd5d7b1ab0..8f18930d5bf879f7c455905df94cdf0afb833b95 100644 (file)
@@ -83,6 +83,8 @@ void die(const char * str, struct pt_regs * regs, long err)
 {
        static int die_counter;
 
+       oops_enter();
+
        console_verbose();
        spin_lock_irq(&die_lock);
        bust_spinlocks(1);
@@ -112,6 +114,7 @@ void die(const char * str, struct pt_regs * regs, long err)
        if (panic_on_oops)
                panic("Fatal exception");
 
+       oops_exit();
        do_exit(SIGSEGV);
 }