obj-y                          := semaphore.o cputable.o ptrace.o syscalls.o \
                                   irq.o align.o signal_32.o pmc.o vdso.o \
-                                  init_task.o process.o systbl.o idle.o
+                                  init_task.o process.o systbl.o idle.o \
+                                  signal.o
 obj-y                          += vdso32/
 obj-$(CONFIG_PPC64)            += setup_64.o binfmt_elf32.o sys_ppc32.o \
                                   signal_64.o ptrace32.o \
 
--- /dev/null
+/*
+ * Common signal handling code for both 32 and 64 bits
+ *
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Extracted from signal_32.c and signal_64.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <asm/unistd.h>
+
+void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
+                          int has_handler)
+{
+       unsigned long ret = regs->gpr[3];
+       int restart = 1;
+
+       /* syscall ? */
+       if (TRAP(regs) != 0x0C00)
+               return;
+
+       /* error signalled ? */
+       if (!(regs->ccr & 0x10000000))
+               return;
+
+       switch (ret) {
+       case ERESTART_RESTARTBLOCK:
+       case ERESTARTNOHAND:
+               /* ERESTARTNOHAND means that the syscall should only be
+                * restarted if there was no handler for the signal, and since
+                * we only get here if there is a handler, we dont restart.
+                */
+               restart = !has_handler;
+               break;
+       case ERESTARTSYS:
+               /* ERESTARTSYS means to restart the syscall if there is no
+                * handler or the handler was registered with SA_RESTART
+                */
+               restart = !has_handler || (ka->sa.sa_flags & SA_RESTART) != 0;
+               break;
+       case ERESTARTNOINTR:
+               /* ERESTARTNOINTR means that the syscall should be
+                * called again after the signal handler returns.
+                */
+               break;
+       default:
+               return;
+       }
+       if (restart) {
+               if (ret == ERESTART_RESTARTBLOCK)
+                       regs->gpr[0] = __NR_restart_syscall;
+               else
+                       regs->gpr[3] = regs->orig_gpr3;
+               regs->nip -= 4;
+               regs->result = 0;
+       } else {
+               regs->result = -EINTR;
+               regs->gpr[3] = EINTR;
+               regs->ccr |= 0x10000000;
+       }
+}
 
--- /dev/null
+/*
+ *    Copyright (c) 2007 Benjamin Herrenschmidt, IBM Coproration
+ *    Extracted from signal_32.c and signal_64.c
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License.  See the file README.legal in the main directory of
+ * this archive for more details.
+ */
+
+#ifndef _POWERPC_ARCH_SIGNAL_H
+#define _POWERPC_ARCH_SIGNAL_H
+
+extern void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
+                                 int has_handler);
+
+#endif  /* _POWERPC_ARCH_SIGNAL_H */
 
 #include <asm/pgtable.h>
 #endif
 
+#include "signal.h"
+
 #undef DEBUG_SIG
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 #ifdef CONFIG_PPC32
 no_signal:
 #endif
-       if (TRAP(regs) == 0x0C00                /* System Call! */
-           && regs->ccr & 0x10000000           /* error signalled */
-           && ((ret = regs->gpr[3]) == ERESTARTSYS
-               || ret == ERESTARTNOHAND || ret == ERESTARTNOINTR
-               || ret == ERESTART_RESTARTBLOCK)) {
-
-               if (signr > 0
-                   && (ret == ERESTARTNOHAND || ret == ERESTART_RESTARTBLOCK
-                       || (ret == ERESTARTSYS
-                           && !(ka.sa.sa_flags & SA_RESTART)))) {
-                       /* make the system call return an EINTR error */
-                       regs->result = -EINTR;
-                       regs->gpr[3] = EINTR;
-                       /* note that the cr0.SO bit is already set */
-               } else {
-                       regs->nip -= 4; /* Back up & retry system call */
-                       regs->result = 0;
-                       regs->trap = 0;
-                       if (ret == ERESTART_RESTARTBLOCK)
-                               regs->gpr[0] = __NR_restart_syscall;
-                       else
-                               regs->gpr[3] = regs->orig_gpr3;
-               }
-       }
+       /* Is there any syscall restart business here ? */
+       check_syscall_restart(regs, &ka, signr > 0);
 
        if (signr == 0) {
                /* No signal to deliver -- put the saved sigmask back */
 
 #include <asm/syscalls.h>
 #include <asm/vdso.h>
 
+#include "signal.h"
+
 #define DEBUG_SIG 0
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
        return ret;
 }
 
-static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
-{
-       switch ((int)regs->result) {
-       case -ERESTART_RESTARTBLOCK:
-       case -ERESTARTNOHAND:
-               /* ERESTARTNOHAND means that the syscall should only be
-                * restarted if there was no handler for the signal, and since
-                * we only get here if there is a handler, we dont restart.
-                */
-               regs->result = -EINTR;
-               regs->gpr[3] = EINTR;
-               regs->ccr |= 0x10000000;
-               break;
-       case -ERESTARTSYS:
-               /* ERESTARTSYS means to restart the syscall if there is no
-                * handler or the handler was registered with SA_RESTART
-                */
-               if (!(ka->sa.sa_flags & SA_RESTART)) {
-                       regs->result = -EINTR;
-                       regs->gpr[3] = EINTR;
-                       regs->ccr |= 0x10000000;
-                       break;
-               }
-               /* fallthrough */
-       case -ERESTARTNOINTR:
-               /* ERESTARTNOINTR means that the syscall should be
-                * called again after the signal handler returns.
-                */
-               regs->gpr[3] = regs->orig_gpr3;
-               regs->nip -= 4;
-               regs->result = 0;
-               break;
-       }
-}
-
 /*
  * Note that 'init' is a special process: it doesn't get signals it doesn't
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
                oldset = ¤t->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+       /* Is there any syscall restart business here ? */
+       check_syscall_restart(regs, &ka, signr > 0);
+
        if (signr > 0) {
                int ret;
 
-               /* Whee!  Actually deliver the signal.  */
-               if (TRAP(regs) == 0x0C00)
-                       syscall_restart(regs, &ka);
-
                /*
                 * Reenable the DABR before delivering the signal to
                 * user space. The DABR will have been cleared if it
                if (current->thread.dabr)
                        set_dabr(current->thread.dabr);
 
+               /* Whee!  Actually deliver the signal.  */
                ret = handle_signal(signr, &ka, &info, oldset, regs);
 
                /* If a signal was successfully delivered, the saved sigmask is in
                return ret;
        }
 
-       if (TRAP(regs) == 0x0C00) {     /* System Call! */
-               if ((int)regs->result == -ERESTARTNOHAND ||
-                   (int)regs->result == -ERESTARTSYS ||
-                   (int)regs->result == -ERESTARTNOINTR) {
-                       regs->gpr[3] = regs->orig_gpr3;
-                       regs->nip -= 4; /* Back up & retry system call */
-                       regs->result = 0;
-               } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
-                       regs->gpr[0] = __NR_restart_syscall;
-                       regs->nip -= 4;
-                       regs->result = 0;
-               }
-       }
        /* No signal to deliver -- put the saved sigmask back */
        if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
                clear_thread_flag(TIF_RESTORE_SIGMASK);