sh: __NR_restart_syscall support.
authorPaul Mundt <lethal@linux-sh.org>
Wed, 27 Sep 2006 08:22:49 +0000 (17:22 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Wed, 27 Sep 2006 08:22:49 +0000 (17:22 +0900)
This implements support for __NR_restart_syscall.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh/kernel/entry.S
arch/sh/kernel/signal.c
arch/sh/kernel/syscalls.S

index b087d34dba35ce7f7344fb71bd16edc5ed764d0a..fcbf50d4ee1093537b9d8dfe6b82cac56f5aae2b 100644 (file)
@@ -376,6 +376,7 @@ work_notifysig:
        bt/s    restore_all
         mov    r15, r4
        mov     #0, r5
+       mov     r12, r6         ! set arg2(save_r0)
        mov.l   2f, r1
        mova    restore_all, r0
        jmp     @r1
@@ -534,6 +535,7 @@ syscall_call:
        mov.l   @r9, r8
        jsr     @r8             ! jump to specific syscall handler
         nop
+       mov.l   @(OFF_R0,r15), r12              ! save r0
        mov.l   r0, @(OFF_R0,r15)               ! save the return value
        !
 syscall_exit:
index b475c4d2405f3e81795dfb39dfdd8aa2c350e94d..eb6a3b97e46c8963becac9088e1d7b560f01fbae 100644 (file)
@@ -33,7 +33,8 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
+asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset,
+                        unsigned int save_r0);
 
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
@@ -56,7 +57,7 @@ sys_sigsuspend(old_sigset_t mask,
        while (1) {
                current->state = TASK_INTERRUPTIBLE;
                schedule();
-               if (do_signal(&regs, &saveset))
+               if (do_signal(&regs, &saveset, regs.regs[0]))
                        return -EINTR;
        }
 }
@@ -85,7 +86,7 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
        while (1) {
                current->state = TASK_INTERRUPTIBLE;
                schedule();
-               if (do_signal(&regs, &saveset))
+               if (do_signal(&regs, &saveset, regs.regs[0]))
                        return -EINTR;
        }
 }
@@ -563,7 +564,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
  * the kernel can handle, and then we build all the user-level signal handling
  * stack-frames in one go after that.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset)
+int do_signal(struct pt_regs *regs, sigset_t *oldset, unsigned int save_r0)
 {
        siginfo_t info;
        int signr;
@@ -597,9 +598,12 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
                /* Restart the system call - no handlers present */
                if (regs->regs[0] == -ERESTARTNOHAND ||
                    regs->regs[0] == -ERESTARTSYS ||
-                   regs->regs[0] == -ERESTARTNOINTR ||
-                   regs->regs[0] == -ERESTART_RESTARTBLOCK) {
+                   regs->regs[0] == -ERESTARTNOINTR) {
+                       regs->regs[0] = save_r0;
                        regs->pc -= 2;
+               } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) {
+                       regs->pc -= 2;
+                       regs->regs[3] = __NR_restart_syscall;
                }
        }
        return 0;
index ada61b0d9a738fca414cc59d3c68197835abff96..ea23b213c77f6bd2b736a787c6a5143a6a8bc409 100644 (file)
@@ -34,7 +34,7 @@
 
        .data
 ENTRY(sys_call_table)
-       .long sys_ni_syscall    /* 0  -  old "setup()" system call*/
+       .long sys_restart_syscall       /* 0  -  old "setup()" system call*/
        .long sys_exit
        .long sys_fork
        .long sys_read