diff options
-rw-r--r-- | arch/sh/kernel/entry.S | 2 | ||||
-rw-r--r-- | arch/sh/kernel/signal.c | 16 | ||||
-rw-r--r-- | arch/sh/kernel/syscalls.S | 2 |
3 files changed, 13 insertions, 7 deletions
diff --git a/arch/sh/kernel/entry.S b/arch/sh/kernel/entry.S index b087d34dba3..fcbf50d4ee1 100644 --- a/arch/sh/kernel/entry.S +++ b/arch/sh/kernel/entry.S @@ -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: diff --git a/arch/sh/kernel/signal.c b/arch/sh/kernel/signal.c index b475c4d2405..eb6a3b97e46 100644 --- a/arch/sh/kernel/signal.c +++ b/arch/sh/kernel/signal.c @@ -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(®s, &saveset)) + if (do_signal(®s, &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(®s, &saveset)) + if (do_signal(®s, &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; diff --git a/arch/sh/kernel/syscalls.S b/arch/sh/kernel/syscalls.S index ada61b0d9a7..ea23b213c77 100644 --- a/arch/sh/kernel/syscalls.S +++ b/arch/sh/kernel/syscalls.S @@ -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 |