patch-2.4.22 linux-2.4.22/arch/sh/kernel/signal.c

Next file: linux-2.4.22/arch/sh/kernel/sys_sh.c
Previous file: linux-2.4.22/arch/sh/kernel/sh_ksyms.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/arch/sh/kernel/signal.c linux-2.4.22/arch/sh/kernel/signal.c
@@ -1,4 +1,4 @@
-/* $Id: signal.c,v 1.21 2000/03/11 14:06:21 gniibe Exp $
+/* $Id: signal.c,v 1.1.1.1.2.11 2002/10/23 00:57:46 mrbrown Exp $
  *
  *  linux/arch/sh/kernel/signal.c
  *
@@ -30,7 +30,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,
+			 int from_syscall, unsigned long orig_r0);
 
 int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
 {
@@ -88,7 +89,7 @@
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&regs, &saveset))
+		if (do_signal(&regs, &saveset, 0, 0))
 			return -EINTR;
 	}
 }
@@ -117,7 +118,7 @@
 	while (1) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule();
-		if (do_signal(&regs, &saveset))
+		if (do_signal(&regs, &saveset, 0, 0))
 			return -EINTR;
 	}
 }
@@ -167,20 +168,21 @@
  * Do a signal return; undo the signal stack.
  */
 
+#define MOVW(n)	(0x9300|((n)-2))	/* Move mem word at PC+n to R3 */
+#define TRAP16	0xc310			/* Syscall w/no args (NR in R3) */
+
 struct sigframe
 {
 	struct sigcontext sc;
 	unsigned long extramask[_NSIG_WORDS-1];
-	char retcode[4];
+	u16 retcode[3];
 };
 
 struct rt_sigframe
 {
-	struct siginfo *pinfo;
-	void *puc;
 	struct siginfo info;
 	struct ucontext uc;
-	char retcode[4];
+	u16 retcode[3];
 };
 
 #if defined(__SH4__)
@@ -196,39 +198,32 @@
 static inline int save_sigcontext_fpu(struct sigcontext *sc)
 {
 	struct task_struct *tsk = current;
-	unsigned long flags;
-	int val;
 
 	if (!tsk->used_math) {
-	  val = 0;
-		__copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
+		__put_user(0, &sc->sc_ownedfp);
 		return 0;
 	}
 
-	val = 1;
-	__copy_to_user(&sc->sc_ownedfp, &val, sizeof(int));
+	__put_user(1, &sc->sc_ownedfp);
 
 	/* This will cause a "finit" to be triggered by the next
 	   attempted FPU operation by the 'current' process.
 	   */
 	tsk->used_math = 0;
 
-	save_and_cli(flags);
 	unlazy_fpu(tsk);
-	restore_flags(flags);
-
 	return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard,
 			      sizeof(long)*(16*2+2));
 }
 #endif
 
 static int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc, int *r0_p)
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
 {
 	unsigned int err = 0;
 
 #define COPY(x)		err |= __get_user(regs->x, &sc->sc_##x)
-			COPY(regs[1]);
+	COPY(regs[0]);	COPY(regs[1]);
 	COPY(regs[2]);	COPY(regs[3]);
 	COPY(regs[4]);	COPY(regs[5]);
 	COPY(regs[6]);	COPY(regs[7]);
@@ -254,19 +249,16 @@
 			err |= restore_sigcontext_fpu(sc);
 	}
 #endif
-
-	regs->syscall_nr = -1;		/* disable syscall checks */
-	err |= __get_user(*r0_p, &sc->sc_regs[0]);
 	return err;
 }
 
+
 asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
 			     unsigned long r6, unsigned long r7,
 			     struct pt_regs regs)
 {
 	struct sigframe *frame = (struct sigframe *)regs.regs[15];
 	sigset_t set;
-	int r0;
 
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -284,9 +276,9 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 
-	if (restore_sigcontext(&regs, &frame->sc, &r0))
+	if (restore_sigcontext(&regs, &frame->sc))
 		goto badframe;
-	return r0;
+	return regs.regs[0];
 
 badframe:
 	force_sig(SIGSEGV, current);
@@ -300,7 +292,6 @@
 	struct rt_sigframe *frame = (struct rt_sigframe *)regs.regs[15];
 	sigset_t set;
 	stack_t st;
-	int r0;
 
 	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
@@ -314,7 +305,7 @@
 	recalc_sigpending(current);
 	spin_unlock_irq(&current->sigmask_lock);
 
-	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext, &r0))
+	if (restore_sigcontext(&regs, &frame->uc.uc_mcontext))
 		goto badframe;
 
 	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
@@ -322,13 +313,12 @@
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
 	do_sigaltstack(&st, NULL, regs.regs[15]);
-
-	return r0;
+	return regs.regs[0];
 
 badframe:
 	force_sig(SIGSEGV, current);
 	return 0;
-}	
+}
 
 /*
  * Set up a signal frame.
@@ -406,15 +396,11 @@
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		regs->pr = (unsigned long) ka->sa.sa_restorer;
 	} else {
-		/* This is : mov  #__NR_sigreturn,r3 ; trapa #0x10 */
-#ifdef __LITTLE_ENDIAN__
-		unsigned long code = 0xc310e300 | (__NR_sigreturn);
-#else
-		unsigned long code = 0xe300c310 | (__NR_sigreturn << 16);
-#endif
-
+		/* Generate return code (system call to sigreturn) */
+		err |= __put_user(MOVW(2), &frame->retcode[0]);
+		err |= __put_user(TRAP16, &frame->retcode[1]);
+		err |= __put_user((__NR_sigreturn), &frame->retcode[2]);
 		regs->pr = (unsigned long) frame->retcode;
-		err |= __put_user(code, (long *)(frame->retcode+0));
 	}
 
 	if (err)
@@ -459,8 +445,6 @@
 		? current->exec_domain->signal_invmap[sig]
 		: sig;
 
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
 
 	/* Create the ucontext.  */
@@ -480,24 +464,22 @@
 	if (ka->sa.sa_flags & SA_RESTORER) {
 		regs->pr = (unsigned long) ka->sa.sa_restorer;
 	} else {
-		/* This is : mov  #__NR_rt_sigreturn,r3 ; trapa #0x10 */
-#ifdef __LITTLE_ENDIAN__
-		unsigned long code = 0xc310e300 | (__NR_rt_sigreturn);
-#else
-		unsigned long code = 0xe300c310 | (__NR_rt_sigreturn << 16);
-#endif
-
+		/* Generate return code (system call to rt_sigreturn) */
+		err |= __put_user(MOVW(2), &frame->retcode[0]);
+		err |= __put_user(TRAP16, &frame->retcode[1]);
+		err |= __put_user((__NR_rt_sigreturn), &frame->retcode[2]);
 		regs->pr = (unsigned long) frame->retcode;
-		err |= __put_user(code, (long *)(frame->retcode+0));
 	}
 
 	if (err)
 		goto give_sigsegv;
 
-	/* Set up registers for signal handler */
-	regs->regs[15] = (unsigned long) frame;
-	regs->regs[4] = signal; /* Arg for signal handler */
-	regs->pc = (unsigned long) ka->sa.sa_handler;
+	/* Set up registers (SP, PC, and args) for signal handler */
+	regs->regs[15] = (unsigned long) frame;		/* Stack pointer */
+	regs->regs[4] = signal;				/* Arg1 (signal) */
+	regs->regs[5] = (unsigned long)&frame->info;	/* Arg2 (siginfo) */
+	regs->regs[6] = (unsigned long)&frame->uc;	/* Arg3 (context) */
+	regs->pc = (unsigned long) ka->sa.sa_handler;	/* Program counter */
 
 	set_fs(USER_DS);
 
@@ -521,10 +503,11 @@
 
 static void
 handle_signal(unsigned long sig, struct k_sigaction *ka,
-	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, 
+	      int from_syscall, unsigned long orig_r0)
 {
 	/* Are we from a system call? */
-	if (regs->syscall_nr >= 0) {
+	if (from_syscall) {
 		/* If so, check system call restarting.. */
 		switch (regs->regs[0]) {
 			case -ERESTARTNOHAND:
@@ -538,9 +521,20 @@
 				}
 			/* fallthrough */
 			case -ERESTARTNOINTR:
-				regs->regs[0] = regs->syscall_nr;
+				regs->regs[0] = orig_r0;
 				regs->pc -= 2;
 		}
+	} else {
+		/* gUSA handling */
+		if (regs->regs[15] >= 0xc0000000) {
+			int offset = (int)regs->regs[15];
+
+			/* Reset stack pointer: clear critical region mark */
+			regs->regs[15] = regs->regs[1];
+			if (regs->pc < regs->regs[0])
+				/* Go to rewind point #1 */
+				regs->pc = regs->regs[0] + offset - 2;
+		}
 	}
 
 	/* Set up the stack frame */
@@ -570,7 +564,8 @@
  * 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,
+	      int from_syscall, unsigned long orig_r0)
 {
 	siginfo_t info;
 	struct k_sigaction *ka;
@@ -677,17 +672,18 @@
 		}
 
 		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, ka, &info, oldset, regs);
+		handle_signal(signr, ka, &info, oldset, regs,
+			      from_syscall, orig_r0);
 		return 1;
 	}
 
 	/* Did we come from a system call? */
-	if (regs->syscall_nr >= 0) {
+	if (from_syscall) {
 		/* Restart the system call - no handlers present */
 		if (regs->regs[0] == -ERESTARTNOHAND ||
 		    regs->regs[0] == -ERESTARTSYS ||
 		    regs->regs[0] == -ERESTARTNOINTR) {
-			regs->regs[0] = regs->syscall_nr;
+			regs->regs[0] = orig_r0;
 			regs->pc -= 2;
 		}
 	}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)