OSDN Git Service

Merge tag 'ptrace-cleanups-for-v5.18' of git://git.kernel.org/pub/scm/linux/kernel...
[uclinux-h8/linux.git] / arch / parisc / kernel / signal.c
index 2f7ebe9..8bc0dda 100644 (file)
@@ -1,16 +1,13 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- *  linux/arch/parisc/kernel/signal.c: Architecture-specific signal
- *  handling support.
+ *  PA-RISC architecture-specific signal handling support.
  *
  *  Copyright (C) 2000 David Huggins-Daines <dhd@debian.org>
  *  Copyright (C) 2000 Linuxcare, Inc.
+ *  Copyright (C) 2000-2022 Helge Deller <deller@gmx.de>
+ *  Copyright (C) 2022 John David Anglin <dave.anglin@bell.net>
  *
  *  Based on the ia64, i386, and alpha versions.
- *
- *  Like the IA-64, we are a recent enough port (we are *starting*
- *  with glibc2.2) that we do not need to support the old non-realtime
- *  Linux signals.  Therefore we don't.
  */
 
 #include <linux/sched.h>
@@ -32,6 +29,7 @@
 #include <linux/uaccess.h>
 #include <asm/cacheflush.h>
 #include <asm/asm-offsets.h>
+#include <asm/vdso.h>
 
 #ifdef CONFIG_COMPAT
 #include "signal32.h"
  * Do a signal return - restore sigcontext.
  */
 
-/* Trampoline for calling rt_sigreturn() */
-#define INSN_LDI_R25_0  0x34190000 /* ldi  0,%r25 (in_syscall=0) */
-#define INSN_LDI_R25_1  0x34190002 /* ldi  1,%r25 (in_syscall=1) */
-#define INSN_LDI_R20    0x3414015a /* ldi  __NR_rt_sigreturn,%r20 */
-#define INSN_BLE_SR2_R0  0xe4008200 /* be,l 0x100(%sr2,%r0),%sr0,%r31 */
-/* For debugging */
-#define INSN_DIE_HORRIBLY 0x68000ccc /* stw %r0,0x666(%sr0,%r0) */
-
 static long
 restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
 {
@@ -77,9 +67,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
        err |= __copy_from_user(regs->iaoq, sc->sc_iaoq, sizeof(regs->iaoq));
        err |= __copy_from_user(regs->iasq, sc->sc_iasq, sizeof(regs->iasq));
        err |= __get_user(regs->sar, &sc->sc_sar);
-       DBG(2,"restore_sigcontext: iaoq is %#lx / %#lx\n",
-                       regs->iaoq[0],regs->iaoq[1]);
-       DBG(2,"restore_sigcontext: r28 is %ld\n", regs->gr[28]);
+       DBG(2, "%s: iaoq is %#lx / %#lx\n",
+                       __func__, regs->iaoq[0], regs->iaoq[1]);
+       DBG(2, "%s: r28 is %ld\n", __func__, regs->gr[28]);
        return err;
 }
 
@@ -102,7 +92,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
        /* Unwind the user stack to get the rt_sigframe structure. */
        frame = (struct rt_sigframe __user *)
                (usp - sigframe_size);
-       DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
+       DBG(2, "%s: frame is %p pid %d\n", __func__, frame, task_pid_nr(current));
 
        regs->orig_r28 = 1; /* no restarts for sigreturn */
 
@@ -110,7 +100,6 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
        compat_frame = (struct compat_rt_sigframe __user *)frame;
        
        if (is_compat_task()) {
-               DBG(2,"sys_rt_sigreturn: ELF32 process.\n");
                if (get_compat_sigset(&set, &compat_frame->uc.uc_sigmask))
                        goto give_sigsegv;
        } else
@@ -125,25 +114,25 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
        /* Good thing we saved the old gr[30], eh? */
 #ifdef CONFIG_64BIT
        if (is_compat_task()) {
-               DBG(1,"sys_rt_sigreturn: compat_frame->uc.uc_mcontext 0x%p\n",
-                               &compat_frame->uc.uc_mcontext);
+               DBG(1, "%s: compat_frame->uc.uc_mcontext 0x%p\n",
+                               __func__, &compat_frame->uc.uc_mcontext);
 // FIXME: Load upper half from register file
                if (restore_sigcontext32(&compat_frame->uc.uc_mcontext, 
                                        &compat_frame->regs, regs))
                        goto give_sigsegv;
-               DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n", 
-                               usp, &compat_frame->uc.uc_stack);
+               DBG(1, "%s: usp %#08lx stack 0x%p\n",
+                               __func__, usp, &compat_frame->uc.uc_stack);
                if (compat_restore_altstack(&compat_frame->uc.uc_stack))
                        goto give_sigsegv;
        } else
 #endif
        {
-               DBG(1,"sys_rt_sigreturn: frame->uc.uc_mcontext 0x%p\n",
-                               &frame->uc.uc_mcontext);
+               DBG(1, "%s: frame->uc.uc_mcontext 0x%p\n",
+                               __func__, &frame->uc.uc_mcontext);
                if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
                        goto give_sigsegv;
-               DBG(1,"sys_rt_sigreturn: usp %#08lx stack 0x%p\n", 
-                               usp, &frame->uc.uc_stack);
+               DBG(1, "%s: usp %#08lx stack 0x%p\n",
+                               __func__, usp, &frame->uc.uc_stack);
                if (restore_altstack(&frame->uc.uc_stack))
                        goto give_sigsegv;
        }
@@ -155,14 +144,11 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
         */
        if (in_syscall)
                regs->gr[31] = regs->iaoq[0];
-#if DEBUG_SIG
-       DBG(1,"sys_rt_sigreturn: returning to %#lx, DUMPING REGS:\n", regs->iaoq[0]);
-       show_regs(regs);
-#endif
+
        return;
 
 give_sigsegv:
-       DBG(1,"sys_rt_sigreturn: Sending SIGSEGV\n");
+       DBG(1, "%s: Sending SIGSEGV\n", __func__);
        force_sig(SIGSEGV);
        return;
 }
@@ -177,15 +163,15 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
        /*FIXME: ELF32 vs. ELF64 has different frame_size, but since we
          don't use the parameter it doesn't matter */
 
-       DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
-                       (unsigned long)ka, sp, frame_size);
+       DBG(1, "%s: ka = %#lx, sp = %#lx, frame_size = %zu\n",
+                       __func__, (unsigned long)ka, sp, frame_size);
        
        /* Align alternate stack and reserve 64 bytes for the signal
           handler's frame marker.  */
        if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
                sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */
 
-       DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
+       DBG(1, "%s: Returning sp = %#lx\n", __func__, (unsigned long)sp);
        return (void __user *) sp; /* Stacks grow up.  Fun. */
 }
 
@@ -205,20 +191,20 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_sysc
                err |= __put_user(regs->gr[31]+4, &sc->sc_iaoq[1]);
                err |= __put_user(regs->sr[3], &sc->sc_iasq[0]);
                err |= __put_user(regs->sr[3], &sc->sc_iasq[1]);
-               DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (in syscall)\n",
-                       regs->gr[31], regs->gr[31]+4);
+               DBG(1, "%s: iaoq %#lx / %#lx (in syscall)\n",
+                       __func__, regs->gr[31], regs->gr[31]+4);
        } else {
                err |= __copy_to_user(sc->sc_iaoq, regs->iaoq, sizeof(regs->iaoq));
                err |= __copy_to_user(sc->sc_iasq, regs->iasq, sizeof(regs->iasq));
-               DBG(1,"setup_sigcontext: iaoq %#lx / %#lx (not in syscall)\n", 
-                       regs->iaoq[0], regs->iaoq[1]);
+               DBG(1, "%s: iaoq %#lx / %#lx (not in syscall)\n",
+                       __func__, regs->iaoq[0], regs->iaoq[1]);
        }
 
        err |= __put_user(flags, &sc->sc_flags);
        err |= __copy_to_user(sc->sc_gr, regs->gr, sizeof(regs->gr));
        err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
        err |= __put_user(regs->sar, &sc->sc_sar);
-       DBG(1,"setup_sigcontext: r28 is %ld\n", regs->gr[28]);
+       DBG(1, "%s: r28 is %ld\n", __func__, regs->gr[28]);
 
        return err;
 }
@@ -230,7 +216,7 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
        struct rt_sigframe __user *frame;
        unsigned long rp, usp;
        unsigned long haddr, sigframe_size;
-       unsigned long start, end;
+       unsigned long start;
        int err = 0;
 #ifdef CONFIG_64BIT
        struct compat_rt_sigframe __user * compat_frame;
@@ -247,11 +233,10 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
 #endif
        frame = get_sigframe(&ksig->ka, usp, sigframe_size);
 
-       DBG(1,"SETUP_RT_FRAME: START\n");
-       DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
+       DBG(1, "%s: frame %p info %p\n", __func__, frame, &ksig->info);
 
        start = (unsigned long) frame;
-       if (start >= user_addr_max() - sigframe_size)
+       if (start >= TASK_SIZE_MAX - sigframe_size)
                return -EFAULT;
        
 #ifdef CONFIG_64BIT
@@ -259,11 +244,12 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
        compat_frame = (struct compat_rt_sigframe __user *)frame;
        
        if (is_compat_task()) {
-               DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
+               DBG(1, "%s: frame->info = 0x%p\n", __func__, &compat_frame->info);
                err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
                err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
-               DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
-               DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
+               DBG(1, "%s: frame->uc = 0x%p\n", __func__, &compat_frame->uc);
+               DBG(1, "%s: frame->uc.uc_mcontext = 0x%p\n",
+                       __func__, &compat_frame->uc.uc_mcontext);
                err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext, 
                                        &compat_frame->regs, regs, in_syscall);
                err |= put_compat_sigset(&compat_frame->uc.uc_sigmask, set,
@@ -271,11 +257,12 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
        } else
 #endif
        {       
-               DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
+               DBG(1, "%s: frame->info = 0x%p\n", __func__, &frame->info);
                err |= copy_siginfo_to_user(&frame->info, &ksig->info);
                err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
-               DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
-               DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
+               DBG(1, "%s: frame->uc = 0x%p\n", __func__, &frame->uc);
+               DBG(1, "%s: frame->uc.uc_mcontext = 0x%p\n",
+                       __func__, &frame->uc.uc_mcontext);
                err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
                /* FIXME: Should probably be converted as well for the compat case */
                err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
@@ -284,32 +271,15 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
        if (err)
                return -EFAULT;
 
-       /* Set up to return from userspace.  If provided, use a stub
-          already in userspace. The first words of tramp are used to
-          save the previous sigrestartblock trampoline that might be
-          on the stack. We start the sigreturn trampoline at 
-          SIGRESTARTBLOCK_TRAMP+X. */
-       err |= __put_user(in_syscall ? INSN_LDI_R25_1 : INSN_LDI_R25_0,
-                       &frame->tramp[SIGRESTARTBLOCK_TRAMP+0]);
-       err |= __put_user(INSN_LDI_R20, 
-                       &frame->tramp[SIGRESTARTBLOCK_TRAMP+1]);
-       err |= __put_user(INSN_BLE_SR2_R0, 
-                       &frame->tramp[SIGRESTARTBLOCK_TRAMP+2]);
-       err |= __put_user(INSN_NOP, &frame->tramp[SIGRESTARTBLOCK_TRAMP+3]);
-
-       start = (unsigned long) &frame->tramp[0];
-       end = (unsigned long) &frame->tramp[TRAMP_SIZE];
-       flush_user_dcache_range_asm(start, end);
-       flush_user_icache_range_asm(start, end);
-
-       /* TRAMP Words 0-4, Length 5 = SIGRESTARTBLOCK_TRAMP
-        * TRAMP Words 5-9, Length 4 = SIGRETURN_TRAMP
-        * So the SIGRETURN_TRAMP is at the end of SIGRESTARTBLOCK_TRAMP
-        */
-       rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
+#ifdef CONFIG_64BIT
+       if (!is_compat_task())
+               rp = VDSO64_SYMBOL(current, sigtramp_rt);
+       else
+#endif
+               rp = VDSO32_SYMBOL(current, sigtramp_rt);
 
-       if (err)
-               return -EFAULT;
+       if (in_syscall)
+               rp += 4*4; /* skip 4 instructions and start at ldi 1,%r25 */
 
        haddr = A(ksig->ka.sa.sa_handler);
        /* The sa_handler may be a pointer to a function descriptor */
@@ -340,8 +310,8 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
                
                haddr = fdesc.addr;
                regs->gr[19] = fdesc.gp;
-               DBG(1,"setup_rt_frame: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
-                    haddr, regs->gr[19], in_syscall);
+               DBG(1, "%s: 64 bit signal, exe=%#lx, r19=%#lx, in_syscall=%d\n",
+                    __func__, haddr, regs->gr[19], in_syscall);
        }
 #endif
 
@@ -351,7 +321,7 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
                regs->gr[31] = haddr;
 #ifdef CONFIG_64BIT
                if (!test_thread_flag(TIF_32BIT))
-                       sigframe_size |= 1;
+                       sigframe_size |= 1; /* XXX ???? */
 #endif
        } else {
                unsigned long psw = USER_PSW;
@@ -373,11 +343,11 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
                }
 
                regs->gr[0] = psw;
-               regs->iaoq[0] = haddr | 3;
+               regs->iaoq[0] = haddr | PRIV_USER;
                regs->iaoq[1] = regs->iaoq[0] + 4;
        }
 
-       regs->gr[2]  = rp;                /* userland return pointer */
+       regs->gr[2]  = rp;                      /* userland return pointer */
        regs->gr[26] = ksig->sig;               /* signal number */
        
 #ifdef CONFIG_64BIT
@@ -391,15 +361,15 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
                regs->gr[24] = A(&frame->uc);   /* ucontext pointer */
        }
        
-       DBG(1,"setup_rt_frame: making sigreturn frame: %#lx + %#lx = %#lx\n",
+       DBG(1, "%s: making sigreturn frame: %#lx + %#lx = %#lx\n", __func__,
               regs->gr[30], sigframe_size,
               regs->gr[30] + sigframe_size);
        /* Raise the user stack pointer to make a proper call frame. */
        regs->gr[30] = (A(frame) + sigframe_size);
 
 
-       DBG(1,"setup_rt_frame: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
-              current->comm, current->pid, frame, regs->gr[30],
+       DBG(1, "%s: sig deliver (%s,%d) frame=0x%p sp=%#lx iaoq=%#lx/%#lx rp=%#lx\n",
+              __func__, current->comm, current->pid, frame, regs->gr[30],
               regs->iaoq[0], regs->iaoq[1], rp);
 
        return 0;
@@ -415,8 +385,8 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
        int ret;
        sigset_t *oldset = sigmask_to_save();
 
-       DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
-              ksig->sig, ksig->ka, ksig->info, oldset, regs);
+       DBG(1, "%s: sig=%d, ka=%p, info=%p, oldset=%p, regs=%p\n",
+              __func__, ksig->sig, &ksig->ka, &ksig->info, oldset, regs);
        
        /* Set up the stack frame */
        ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
@@ -424,8 +394,8 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
        signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
                          test_thread_flag(TIF_BLOCKSTEP));
 
-       DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
-               regs->gr[28]);
+       DBG(1, "%s: Exit (success), regs->gr[28] = %ld\n",
+               __func__, regs->gr[28]);
 }
 
 /*
@@ -483,21 +453,27 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
        if (regs->orig_r28)
                return;
        regs->orig_r28 = 1; /* no more restarts */
+
+       DBG(1, "%s:  orig_r28 = %ld  pid %d  r20 %ld\n",
+               __func__, regs->orig_r28, task_pid_nr(current), regs->gr[20]);
+
        /* Check the return code */
        switch (regs->gr[28]) {
        case -ERESTART_RESTARTBLOCK:
        case -ERESTARTNOHAND:
-               DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
+               DBG(1, "%s: ERESTARTNOHAND: returning -EINTR\n", __func__);
                regs->gr[28] = -EINTR;
                break;
        case -ERESTARTSYS:
                if (!(ka->sa.sa_flags & SA_RESTART)) {
-                       DBG(1,"ERESTARTSYS: putting -EINTR\n");
+                       DBG(1, "%s: ERESTARTSYS: putting -EINTR pid %d\n",
+                               __func__, task_pid_nr(current));
                        regs->gr[28] = -EINTR;
                        break;
                }
                fallthrough;
        case -ERESTARTNOINTR:
+               DBG(1, "%s: %ld\n", __func__, regs->gr[28]);
                check_syscallno_in_delay_branch(regs);
                break;
        }
@@ -509,50 +485,52 @@ insert_restart_trampoline(struct pt_regs *regs)
        if (regs->orig_r28)
                return;
        regs->orig_r28 = 1; /* no more restarts */
-       switch(regs->gr[28]) {
+
+       DBG(2, "%s: gr28 = %ld pid %d\n",
+               __func__, regs->gr[28], task_pid_nr(current));
+
+       switch (regs->gr[28]) {
        case -ERESTART_RESTARTBLOCK: {
                /* Restart the system call - no handlers present */
                unsigned int *usp = (unsigned int *)regs->gr[30];
-               unsigned long start = (unsigned long) &usp[2];
-               unsigned long end  = (unsigned long) &usp[5];
+               unsigned long rp;
                long err = 0;
 
                /* check that we don't exceed the stack */
-               if (A(&usp[0]) >= user_addr_max() - 5 * sizeof(int))
+               if (A(&usp[0]) >= TASK_SIZE_MAX - 5 * sizeof(int))
                        return;
 
-               /* Setup a trampoline to restart the syscall
-                * with __NR_restart_syscall
+               /* Call trampoline in vdso to restart the syscall
+                * with __NR_restart_syscall.
+                * Original return addresses are on stack like this:
                 *
                 *  0: <return address (orig r31)>
                 *  4: <2nd half for 64-bit>
-                *  8: ldw 0(%sp), %r31
-                * 12: be 0x100(%sr2, %r0)
-                * 16: ldi __NR_restart_syscall, %r20
                 */
 #ifdef CONFIG_64BIT
-               err |= put_user(regs->gr[31] >> 32, &usp[0]);
-               err |= put_user(regs->gr[31] & 0xffffffff, &usp[1]);
-               err |= put_user(0x0fc010df, &usp[2]);
-#else
-               err |= put_user(regs->gr[31], &usp[0]);
-               err |= put_user(0x0fc0109f, &usp[2]);
+               if (!is_compat_task()) {
+                       err |= put_user(regs->gr[31] >> 32, &usp[0]);
+                       err |= put_user(regs->gr[31] & 0xffffffff, &usp[1]);
+                       rp = VDSO64_SYMBOL(current, restart_syscall);
+               } else
 #endif
-               err |= put_user(0xe0008200, &usp[3]);
-               err |= put_user(0x34140000, &usp[4]);
-
+               {
+                       err |= put_user(regs->gr[31], &usp[0]);
+                       rp = VDSO32_SYMBOL(current, restart_syscall);
+               }
                WARN_ON(err);
 
-               /* flush data/instruction cache for new insns */
-               flush_user_dcache_range_asm(start, end);
-               flush_user_icache_range_asm(start, end);
-
-               regs->gr[31] = regs->gr[30] + 8;
+               regs->gr[31] = rp;
+               DBG(1, "%s: ERESTART_RESTARTBLOCK\n", __func__);
                return;
        }
+       case -EINTR:
+               /* ok, was handled before and should be returned. */
+               break;
        case -ERESTARTNOHAND:
        case -ERESTARTSYS:
        case -ERESTARTNOINTR:
+               DBG(1, "%s: Type %ld\n", __func__, regs->gr[28]);
                check_syscallno_in_delay_branch(regs);
                return;
        default:
@@ -567,30 +545,35 @@ insert_restart_trampoline(struct pt_regs *regs)
  * registers).  As noted below, the syscall number gets restored for
  * us due to the magic of delayed branching.
  */
-asmlinkage void
-do_signal(struct pt_regs *regs, long in_syscall)
+static void do_signal(struct pt_regs *regs, long in_syscall)
 {
        struct ksignal ksig;
+       int restart_syscall;
+       bool has_handler;
 
-       DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
-              regs, regs->sr[7], in_syscall);
+       has_handler = get_signal(&ksig);
 
-       if (get_signal(&ksig)) {
-               DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
+       restart_syscall = 0;
+       if (in_syscall)
+               restart_syscall = 1;
+
+       if (has_handler) {
                /* Restart a system call if necessary. */
-               if (in_syscall)
+               if (restart_syscall)
                        syscall_restart(regs, &ksig.ka);
 
                handle_signal(&ksig, regs, in_syscall);
+               DBG(1, "%s: Handled signal pid %d\n",
+                       __func__, task_pid_nr(current));
                return;
        }
 
-       /* Did we come from a system call? */
-       if (in_syscall)
+       /* Do we need to restart the system call? */
+       if (restart_syscall)
                insert_restart_trampoline(regs);
        
-       DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 
-               regs->gr[28]);
+       DBG(1, "%s: Exit (not delivered), regs->gr[28] = %ld  orig_r28 = %ld  pid %d\n",
+               __func__, regs->gr[28], regs->orig_r28, task_pid_nr(current));
 
        restore_saved_sigmask();
 }