summary refs log tree commit diff
path: root/arch/alpha
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 18:50:11 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 18:50:11 -0800
commit9e2d59ad580d590134285f361a0e80f0e98c0207 (patch)
treef3232be75781484193413f32ec82c21f6d8eb76e /arch/alpha
parent5ce1a70e2f00f0bce0cab57f798ca354b9496169 (diff)
parent235b80226b986dabcbba844968f7807866bd0bfe (diff)
downloadlinux-9e2d59ad580d590134285f361a0e80f0e98c0207.tar.gz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull signal handling cleanups from Al Viro:
 "This is the first pile; another one will come a bit later and will
  contain SYSCALL_DEFINE-related patches.

   - a bunch of signal-related syscalls (both native and compat)
     unified.

   - a bunch of compat syscalls switched to COMPAT_SYSCALL_DEFINE
     (fixing several potential problems with missing argument
     validation, while we are at it)

   - a lot of now-pointless wrappers killed

   - a couple of architectures (cris and hexagon) forgot to save
     altstack settings into sigframe, even though they used the
     (uninitialized) values in sigreturn; fixed.

   - microblaze fixes for delivery of multiple signals arriving at once

   - saner set of helpers for signal delivery introduced, several
     architectures switched to using those."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (143 commits)
  x86: convert to ksignal
  sparc: convert to ksignal
  arm: switch to struct ksignal * passing
  alpha: pass k_sigaction and siginfo_t using ksignal pointer
  burying unused conditionals
  make do_sigaltstack() static
  arm64: switch to generic old sigaction() (compat-only)
  arm64: switch to generic compat rt_sigaction()
  arm64: switch compat to generic old sigsuspend
  arm64: switch to generic compat rt_sigqueueinfo()
  arm64: switch to generic compat rt_sigpending()
  arm64: switch to generic compat rt_sigprocmask()
  arm64: switch to generic sigaltstack
  sparc: switch to generic old sigsuspend
  sparc: COMPAT_SYSCALL_DEFINE does all sign-extension as well as SYSCALL_DEFINE
  sparc: kill sign-extending wrappers for native syscalls
  kill sparc32_open()
  sparc: switch to use of generic old sigaction
  sparc: switch sys_compat_rt_sigaction() to COMPAT_SYSCALL_DEFINE
  mips: switch to generic sys_fork() and sys_clone()
  ...
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/Kconfig3
-rw-r--r--arch/alpha/include/asm/signal.h11
-rw-r--r--arch/alpha/include/asm/unistd.h1
-rw-r--r--arch/alpha/kernel/process.c1
-rw-r--r--arch/alpha/kernel/signal.c121
5 files changed, 48 insertions, 89 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index dabc93649495..1ecbf7a1b677 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -21,7 +21,8 @@ config ALPHA
 	select GENERIC_STRNLEN_USER
 	select HAVE_MOD_ARCH_SPECIFIC
 	select MODULES_USE_ELF_RELA
-	select GENERIC_SIGALTSTACK
+	select ODD_RT_SIGACTION
+	select OLD_SIGSUSPEND
 	help
 	  The Alpha is a 64-bit general-purpose processor designed and
 	  marketed by the Digital Equipment Corporation of blessed memory,
diff --git a/arch/alpha/include/asm/signal.h b/arch/alpha/include/asm/signal.h
index 8a1ac28cd562..963f0494dca7 100644
--- a/arch/alpha/include/asm/signal.h
+++ b/arch/alpha/include/asm/signal.h
@@ -22,15 +22,6 @@ struct osf_sigaction {
 	int		sa_flags;
 };
 
-struct sigaction {
-	__sighandler_t	sa_handler;
-	unsigned long	sa_flags;
-	sigset_t	sa_mask;	/* mask last for extensibility */
-};
-
-struct k_sigaction {
-	struct sigaction sa;
-	__sigrestore_t ka_restorer;
-};
+#define __ARCH_HAS_KA_RESTORER
 #include <asm/sigcontext.h>
 #endif
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h
index b3396ee039b7..6d6fe7ab5473 100644
--- a/arch/alpha/include/asm/unistd.h
+++ b/arch/alpha/include/asm/unistd.h
@@ -14,7 +14,6 @@
 #define __ARCH_WANT_SYS_OLD_GETRLIMIT
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
-#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #define __ARCH_WANT_SYS_FORK
 #define __ARCH_WANT_SYS_VFORK
 #define __ARCH_WANT_SYS_CLONE
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index b5d0d0923699..63d27fb9b023 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -250,7 +250,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 	struct pt_regs *childregs = task_pt_regs(p);
 	struct pt_regs *regs = current_pt_regs();
 	struct switch_stack *childstack, *stack;
-	unsigned long settls;
 
 	childstack = ((struct switch_stack *) childregs) - 1;
 	childti->pcb.ksp = (unsigned long) childstack;
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 02d02c047f17..6cec2881acbf 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -113,16 +113,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
 }
 
 /*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
-{
-	sigset_t blocked;
-	siginitset(&blocked, mask);
-	return sigsuspend(&blocked);
-}
-
-/*
  * Do a signal return; undo the signal stack.
  */
 
@@ -282,12 +272,9 @@ give_sigsegv:
  */
 
 static inline void __user *
-get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
+get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
 {
-	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
-		sp = current->sas_ss_sp + current->sas_ss_size;
-
-	return (void __user *)((sp - frame_size) & -32ul);
+	return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul);
 }
 
 static long
@@ -348,14 +335,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 }
 
 static int
-setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
-	    struct pt_regs *regs)
+setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	unsigned long oldsp, r26, err = 0;
 	struct sigframe __user *frame;
 
 	oldsp = rdusp();
-	frame = get_sigframe(ka, oldsp, sizeof(*frame));
+	frame = get_sigframe(ksig, oldsp, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
@@ -365,9 +351,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->ka_restorer) {
-		r26 = (unsigned long) ka->ka_restorer;
-	} else {
+	r26 = (unsigned long) ksig->ka.ka_restorer;
+	if (!r26) {
 		err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
 		err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
 		err |= __put_user(INSN_CALLSYS, frame->retcode+2);
@@ -381,8 +366,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 
 	/* "Return" to the handler */
 	regs->r26 = r26;
-	regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
-	regs->r16 = sig;			/* a0: signal number */
+	regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+	regs->r16 = ksig->sig;			/* a0: signal number */
 	regs->r17 = 0;				/* a1: exception code */
 	regs->r18 = (unsigned long) &frame->sc;	/* a2: sigcontext pointer */
 	wrusp((unsigned long) frame);
@@ -395,18 +380,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 }
 
 static int
-setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
-	       sigset_t *set, struct pt_regs *regs)
+setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
 {
 	unsigned long oldsp, r26, err = 0;
 	struct rt_sigframe __user *frame;
 
 	oldsp = rdusp();
-	frame = get_sigframe(ka, oldsp, sizeof(*frame));
+	frame = get_sigframe(ksig, oldsp, sizeof(*frame));
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
-	err |= copy_siginfo_to_user(&frame->info, info);
+	err |= copy_siginfo_to_user(&frame->info, &ksig->info);
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -421,9 +405,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
 	/* Set up to return from userspace.  If provided, use a stub
 	   already in userspace.  */
-	if (ka->ka_restorer) {
-		r26 = (unsigned long) ka->ka_restorer;
-	} else {
+	r26 = (unsigned long) ksig->ka.ka_restorer;
+	if (!r26) {
 		err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
 		err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
 				  frame->retcode+1);
@@ -437,8 +420,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
 	/* "Return" to the handler */
 	regs->r26 = r26;
-	regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
-	regs->r16 = sig;			  /* a0: signal number */
+	regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
+	regs->r16 = ksig->sig;			  /* a0: signal number */
 	regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
 	regs->r18 = (unsigned long) &frame->uc;	  /* a2: ucontext pointer */
 	wrusp((unsigned long) frame);
@@ -456,22 +439,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
  * OK, we're invoking a handler.
  */
 static inline void
-handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
-	      struct pt_regs * regs)
+handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 {
 	sigset_t *oldset = sigmask_to_save();
 	int ret;
 
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(ksig, oldset, regs);
 	else
-		ret = setup_frame(sig, ka, oldset, regs);
+		ret = setup_frame(ksig, oldset, regs);
 
-	if (ret) {
-		force_sigsegv(sig, current);
-		return;
-	}
-	signal_delivered(sig, info, ka, regs, 0);
+	signal_setup_done(ret, ksig, 0);
 }
 
 static inline void
@@ -514,47 +492,38 @@ syscall_restart(unsigned long r0, unsigned long r19,
 static void
 do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
 {
-	siginfo_t info;
-	int signr;
 	unsigned long single_stepping = ptrace_cancel_bpt(current);
-	struct k_sigaction ka;
+	struct ksignal ksig;
 
 	/* This lets the debugger run, ... */
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-
-	/* ... so re-check the single stepping. */
-	single_stepping |= ptrace_cancel_bpt(current);
-
-	if (signr > 0) {
+	if (get_signal(&ksig)) {
+		/* ... so re-check the single stepping. */
+		single_stepping |= ptrace_cancel_bpt(current);
 		/* Whee!  Actually deliver the signal.  */
 		if (r0)
-			syscall_restart(r0, r19, regs, &ka);
-		handle_signal(signr, &ka, &info, regs);
-		if (single_stepping) 
-			ptrace_set_bpt(current); /* re-set bpt */
-		return;
-	}
-
-	if (r0) {
-	  	switch (regs->r0) {
-		case ERESTARTNOHAND:
-		case ERESTARTSYS:
-		case ERESTARTNOINTR:
-			/* Reset v0 and a3 and replay syscall.  */
-			regs->r0 = r0;
-			regs->r19 = r19;
-			regs->pc -= 4;
-			break;
-		case ERESTART_RESTARTBLOCK:
-			/* Force v0 to the restart syscall and reply.  */
-			regs->r0 = __NR_restart_syscall;
-			regs->pc -= 4;
-			break;
+			syscall_restart(r0, r19, regs, &ksig.ka);
+		handle_signal(&ksig, regs);
+	} else {
+		single_stepping |= ptrace_cancel_bpt(current);
+		if (r0) {
+			switch (regs->r0) {
+			case ERESTARTNOHAND:
+			case ERESTARTSYS:
+			case ERESTARTNOINTR:
+				/* Reset v0 and a3 and replay syscall.  */
+				regs->r0 = r0;
+				regs->r19 = r19;
+				regs->pc -= 4;
+				break;
+			case ERESTART_RESTARTBLOCK:
+				/* Set v0 to the restart_syscall and replay */
+				regs->r0 = __NR_restart_syscall;
+				regs->pc -= 4;
+				break;
+			}
 		}
+		restore_saved_sigmask();
 	}
-
-	/* If there's no signal to deliver, we just restore the saved mask.  */
-	restore_saved_sigmask();
 	if (single_stepping)
 		ptrace_set_bpt(current);	/* re-set breakpoint */
 }