Pārlūkot izejas kodu

sh: __NR_restart_syscall support.

This implements support for __NR_restart_syscall.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Paul Mundt 18 gadi atpakaļ
vecāks
revīzija
0b8929354c
3 mainītis faili ar 13 papildinājumiem un 7 dzēšanām
  1. 2 0
      arch/sh/kernel/entry.S
  2. 10 6
      arch/sh/kernel/signal.c
  3. 1 1
      arch/sh/kernel/syscalls.S

+ 2 - 0
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:

+ 10 - 6
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(&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;

+ 1 - 1
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