* this archive for more details.
  */
 
+#include <linux/freezer.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 #include <asm/unistd.h>
 #include "signal.h"
 
 
+#ifdef CONFIG_PPC64
+static inline int is_32bit_task(void)
+{
+       return test_thread_flag(TIF_32BIT);
+}
+#else
+static inline int is_32bit_task(void)
+{
+       return 1;
+}
+#endif
+
+
 /*
  * Restore the user process's signal mask
  */
        spin_unlock_irq(¤t->sighand->siglock);
 }
 
-void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
-                          int has_handler)
+static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
+                                 int has_handler)
 {
        unsigned long ret = regs->gpr[3];
        int restart = 1;
        }
 }
 
+int do_signal(sigset_t *oldset, struct pt_regs *regs)
+{
+       siginfo_t info;
+       int signr;
+       struct k_sigaction ka;
+       int ret;
+       int is32 = is_32bit_task();
+
+#ifdef CONFIG_PPC32
+       if (try_to_freeze()) {
+               signr = 0;
+               if (!signal_pending(current))
+                       goto no_signal;
+       }
+#endif
+
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = ¤t->saved_sigmask;
+       else if (!oldset)
+               oldset = ¤t->blocked;
+
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+#ifdef CONFIG_PPC32
+no_signal:
+#endif
+       /* 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 */
+               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+                       sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
+               }
+               return 0;               /* no signals delivered */
+       }
+
+#ifdef CONFIG_PPC64
+        /*
+        * Reenable the DABR before delivering the signal to
+        * user space. The DABR will have been cleared if it
+        * triggered inside the kernel.
+        */
+       if (current->thread.dabr)
+               set_dabr(current->thread.dabr);
+#endif
+
+       if (is32) {
+               unsigned int newsp;
+
+               if ((ka.sa.sa_flags & SA_ONSTACK) &&
+                   current->sas_ss_size && !on_sig_stack(regs->gpr[1]))
+                       newsp = current->sas_ss_sp + current->sas_ss_size;
+               else
+                       newsp = regs->gpr[1];
+
+               if (ka.sa.sa_flags & SA_SIGINFO)
+                       ret = handle_rt_signal32(signr, &ka, &info, oldset,
+                                       regs, newsp);
+               else
+                       ret = handle_signal32(signr, &ka, &info, oldset,
+                                       regs, newsp);
+#ifdef CONFIG_PPC64
+       } else {
+               ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
+#endif
+       }
+
+       if (ret) {
+               spin_lock_irq(¤t->sighand->siglock);
+               sigorsets(¤t->blocked, ¤t->blocked,
+                         &ka.sa.sa_mask);
+               if (!(ka.sa.sa_flags & SA_NODEFER))
+                       sigaddset(¤t->blocked, signr);
+               recalc_sigpending();
+               spin_unlock_irq(¤t->sighand->siglock);
+
+               /*
+                * A signal was successfully delivered; the saved sigmask is in
+                * its frame, and we can clear the TIF_RESTORE_SIGMASK flag.
+                */
+               if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+       }
+
+       return ret;
+}
+
 long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                unsigned long r5, unsigned long r6, unsigned long r7,
                unsigned long r8, struct pt_regs *regs)
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 extern void restore_sigmask(sigset_t *set);
-extern void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
-                                 int has_handler);
+
+extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+                          siginfo_t *info, sigset_t *oldset,
+                          struct pt_regs *regs, unsigned long newsp);
+
+extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
+                             siginfo_t *info, sigset_t *oldset,
+                             struct pt_regs *regs, unsigned long newsp);
+
+extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
+                             siginfo_t *info, sigset_t *set,
+                             struct pt_regs *regs);
 
 #endif  /* _POWERPC_ARCH_SIGNAL_H */
 
 #undef DEBUG_SIG
 
 #ifdef CONFIG_PPC64
-#define do_signal      do_signal32
 #define sys_sigsuspend compat_sys_sigsuspend
 #define sys_rt_sigsuspend      compat_sys_rt_sigsuspend
 #define sys_rt_sigreturn       compat_sys_rt_sigreturn
 
 #endif /* CONFIG_PPC64 */
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
  * Set up a signal frame for a "real-time" signal handler
  * (one which gets siginfo).
  */
-static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka,
+int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
                siginfo_t *info, sigset_t *oldset,
                struct pt_regs *regs, unsigned long newsp)
 {
 /*
  * OK, we're invoking a handler
  */
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
+int handle_signal32(unsigned long sig, struct k_sigaction *ka,
                siginfo_t *info, sigset_t *oldset, struct pt_regs *regs,
                unsigned long newsp)
 {
        force_sig(SIGSEGV, current);
        return 0;
 }
-
-/*
- * 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
- * mistake.
- */
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
-{
-       siginfo_t info;
-       struct k_sigaction ka;
-       unsigned int newsp;
-       int signr, ret;
-
-#ifdef CONFIG_PPC32
-       if (try_to_freeze()) {
-               signr = 0;
-               if (!signal_pending(current))
-                       goto no_signal;
-       }
-#endif
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = ¤t->saved_sigmask;
-       else if (!oldset)
-               oldset = ¤t->blocked;
-
-       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-#ifdef CONFIG_PPC32
-no_signal:
-#endif
-       /* 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 */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
-               }
-               return 0;               /* no signals delivered */
-       }
-
-       if ((ka.sa.sa_flags & SA_ONSTACK) && current->sas_ss_size
-           && !on_sig_stack(regs->gpr[1]))
-               newsp = current->sas_ss_sp + current->sas_ss_size;
-       else
-               newsp = regs->gpr[1];
-       newsp &= ~0xfUL;
-
-#ifdef CONFIG_PPC64
-       /*
-        * Reenable the DABR before delivering the signal to
-        * user space. The DABR will have been cleared if it
-        * triggered inside the kernel.
-        */
-       if (current->thread.dabr)
-               set_dabr(current->thread.dabr);
-#endif
-
-       /* Whee!  Actually deliver the signal.  */
-       if (ka.sa.sa_flags & SA_SIGINFO)
-               ret = handle_rt_signal(signr, &ka, &info, oldset, regs, newsp);
-       else
-               ret = handle_signal(signr, &ka, &info, oldset, regs, newsp);
-
-       if (ret) {
-               spin_lock_irq(¤t->sighand->siglock);
-               sigorsets(¤t->blocked, ¤t->blocked,
-                         &ka.sa.sa_mask);
-               if (!(ka.sa.sa_flags & SA_NODEFER))
-                       sigaddset(¤t->blocked, signr);
-               recalc_sigpending();
-               spin_unlock_irq(¤t->sighand->siglock);
-               /* A signal was successfully delivered; the saved sigmask is in
-                  its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-       }
-
-       return ret;
-}
 
        return 0;
 }
 
-static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
                sigset_t *set, struct pt_regs *regs)
 {
        /* Handler is *really* a pointer to the function descriptor for
        force_sigsegv(signr, current);
        return 0;
 }
-
-
-/*
- * OK, we're invoking a handler
- */
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
-                        siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
-{
-       int ret;
-
-       /* Set up Signal Frame */
-       ret = setup_rt_frame(sig, ka, info, oldset, regs);
-
-       if (ret) {
-               spin_lock_irq(¤t->sighand->siglock);
-               sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
-               if (!(ka->sa.sa_flags & SA_NODEFER))
-                       sigaddset(¤t->blocked,sig);
-               recalc_sigpending();
-               spin_unlock_irq(¤t->sighand->siglock);
-       }
-
-       return ret;
-}
-
-/*
- * 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
- * mistake.
- */
-int do_signal(sigset_t *oldset, struct pt_regs *regs)
-{
-       siginfo_t info;
-       int signr;
-       struct k_sigaction ka;
-
-       /*
-        * If the current thread is 32 bit - invoke the
-        * 32 bit signal handling code
-        */
-       if (test_thread_flag(TIF_32BIT))
-               return do_signal32(oldset, regs);
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = ¤t->saved_sigmask;
-       else if (!oldset)
-               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;
-
-               /*
-                * Reenable the DABR before delivering the signal to
-                * user space. The DABR will have been cleared if it
-                * triggered inside the kernel.
-                */
-               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
-                  its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
-               if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-               return ret;
-       }
-
-       /* No signal to deliver -- put the saved sigmask back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL(do_signal);