All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mark Salter <msalter@redhat.com>
To: linux-kernel@vger.kernel.org
Cc: linux-arch@vger.kernel.org, Aurelien Jacquiot <a-jacquiot@ti.com>,
	Mark Salter <msalter@redhat.com>
Subject: [PATCH v4 10/24] C6X: signal management
Date: Tue,  4 Oct 2011 12:43:47 -0400	[thread overview]
Message-ID: <1317746641-26725-11-git-send-email-msalter@redhat.com> (raw)
In-Reply-To: <1317746641-26725-1-git-send-email-msalter@redhat.com>

From: Aurelien Jacquiot <a-jacquiot@ti.com>

Original port to early 2.6 kernel using TI COFF toolchain.
Brought up to date by Mark Salter <msalter@redhat.com>

Signed-off-by: Aurelien Jacquiot <a-jacquiot@ti.com>
Signed-off-by: Mark Salter <msalter@redhat.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
---
 arch/c6x/include/asm/sigcontext.h |   80 ++++++++
 arch/c6x/include/asm/signal.h     |   17 ++
 arch/c6x/kernel/signal.c          |  377 +++++++++++++++++++++++++++++++++++++
 3 files changed, 474 insertions(+), 0 deletions(-)
 create mode 100644 arch/c6x/include/asm/sigcontext.h
 create mode 100644 arch/c6x/include/asm/signal.h
 create mode 100644 arch/c6x/kernel/signal.c

diff --git a/arch/c6x/include/asm/sigcontext.h b/arch/c6x/include/asm/sigcontext.h
new file mode 100644
index 0000000..eb702f3
--- /dev/null
+++ b/arch/c6x/include/asm/sigcontext.h
@@ -0,0 +1,80 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2009 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+#ifndef _ASM_C6X_SIGCONTEXT_H
+#define _ASM_C6X_SIGCONTEXT_H
+
+
+struct sigcontext {
+	unsigned long  sc_mask;		/* old sigmask */
+	unsigned long  sc_sp;		/* old user stack pointer */
+
+	unsigned long  sc_a4;
+	unsigned long  sc_b4;
+	unsigned long  sc_a6;
+	unsigned long  sc_b6;
+	unsigned long  sc_a8;
+	unsigned long  sc_b8;
+
+	unsigned long  sc_a0;
+	unsigned long  sc_a1;
+	unsigned long  sc_a2;
+	unsigned long  sc_a3;
+	unsigned long  sc_a5;
+	unsigned long  sc_a7;
+	unsigned long  sc_a9;
+
+	unsigned long  sc_b0;
+	unsigned long  sc_b1;
+	unsigned long  sc_b2;
+	unsigned long  sc_b3;
+	unsigned long  sc_b5;
+	unsigned long  sc_b7;
+	unsigned long  sc_b9;
+
+	unsigned long  sc_a16;
+	unsigned long  sc_a17;
+	unsigned long  sc_a18;
+	unsigned long  sc_a19;
+	unsigned long  sc_a20;
+	unsigned long  sc_a21;
+	unsigned long  sc_a22;
+	unsigned long  sc_a23;
+	unsigned long  sc_a24;
+	unsigned long  sc_a25;
+	unsigned long  sc_a26;
+	unsigned long  sc_a27;
+	unsigned long  sc_a28;
+	unsigned long  sc_a29;
+	unsigned long  sc_a30;
+	unsigned long  sc_a31;
+
+	unsigned long  sc_b16;
+	unsigned long  sc_b17;
+	unsigned long  sc_b18;
+	unsigned long  sc_b19;
+	unsigned long  sc_b20;
+	unsigned long  sc_b21;
+	unsigned long  sc_b22;
+	unsigned long  sc_b23;
+	unsigned long  sc_b24;
+	unsigned long  sc_b25;
+	unsigned long  sc_b26;
+	unsigned long  sc_b27;
+	unsigned long  sc_b28;
+	unsigned long  sc_b29;
+	unsigned long  sc_b30;
+	unsigned long  sc_b31;
+
+	unsigned long  sc_csr;
+	unsigned long  sc_pc;
+};
+
+#endif /* _ASM_C6X_SIGCONTEXT_H */
diff --git a/arch/c6x/include/asm/signal.h b/arch/c6x/include/asm/signal.h
new file mode 100644
index 0000000..f1cd870
--- /dev/null
+++ b/arch/c6x/include/asm/signal.h
@@ -0,0 +1,17 @@
+#ifndef _ASM_C6X_SIGNAL_H
+#define _ASM_C6X_SIGNAL_H
+
+#include <asm-generic/signal.h>
+
+#ifndef __ASSEMBLY__
+#include <linux/linkage.h>
+
+struct pt_regs;
+
+extern asmlinkage int do_rt_sigreturn(struct pt_regs *regs);
+extern asmlinkage void do_notify_resume(struct pt_regs *regs,
+					u32 thread_info_flags,
+					int syscall);
+#endif
+
+#endif /* _ASM_C6X_SIGNAL_H */
diff --git a/arch/c6x/kernel/signal.c b/arch/c6x/kernel/signal.c
new file mode 100644
index 0000000..304f675
--- /dev/null
+++ b/arch/c6x/kernel/signal.c
@@ -0,0 +1,377 @@
+/*
+ *  Port on Texas Instruments TMS320C6x architecture
+ *
+ *  Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated
+ *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
+ *
+ *  Updated for 2.6.34: Mark Salter <msalter@redhat.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/syscalls.h>
+#include <linux/tracehook.h>
+
+#include <asm/ucontext.h>
+#include <asm/cacheflush.h>
+
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/*
+ * Do a signal return, undo the signal stack.
+ */
+
+#define RETCODE_SIZE (9 << 2)	/* 9 instructions = 36 bytes */
+
+struct rt_sigframe {
+	struct siginfo __user *pinfo;
+	void __user *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	unsigned long retcode[RETCODE_SIZE >> 2];
+};
+
+static int restore_sigcontext(struct pt_regs *regs,
+			      struct sigcontext __user *sc)
+{
+	int err = 0;
+
+	/* The access_ok check was done by caller, so use __get_user here */
+#define COPY(x)  (err |= __get_user(regs->x, &sc->sc_##x))
+
+	COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8);
+	COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9);
+	COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9);
+
+	COPY(a16); COPY(a17); COPY(a18); COPY(a19);
+	COPY(a20); COPY(a21); COPY(a22); COPY(a23);
+	COPY(a24); COPY(a25); COPY(a26); COPY(a27);
+	COPY(a28); COPY(a29); COPY(a30); COPY(a31);
+	COPY(b16); COPY(b17); COPY(b18); COPY(b19);
+	COPY(b20); COPY(b21); COPY(b22); COPY(b23);
+	COPY(b24); COPY(b25); COPY(b26); COPY(b27);
+	COPY(b28); COPY(b29); COPY(b30); COPY(b31);
+
+	COPY(csr); COPY(pc);
+
+#undef COPY
+
+	return err;
+}
+
+asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	sigset_t set;
+
+	/*
+	 * Since we stacked the signal on a dword boundary,
+	 * 'sp' should be dword aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->sp & 7)
+		goto badframe;
+
+	frame = (struct rt_sigframe __user *) ((unsigned long) regs->sp + 8);
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+		goto badframe;
+
+	return regs->a4;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
+			    unsigned long mask)
+{
+	int err = 0;
+
+	err |= __put_user(mask, &sc->sc_mask);
+
+	/* The access_ok check was done by caller, so use __put_user here */
+#define COPY(x) (err |= __put_user(regs->x, &sc->sc_##x))
+
+	COPY(sp); COPY(a4); COPY(b4); COPY(a6); COPY(b6); COPY(a8); COPY(b8);
+	COPY(a0); COPY(a1); COPY(a2); COPY(a3); COPY(a5); COPY(a7); COPY(a9);
+	COPY(b0); COPY(b1); COPY(b2); COPY(b3); COPY(b5); COPY(b7); COPY(b9);
+
+	COPY(a16); COPY(a17); COPY(a18); COPY(a19);
+	COPY(a20); COPY(a21); COPY(a22); COPY(a23);
+	COPY(a24); COPY(a25); COPY(a26); COPY(a27);
+	COPY(a28); COPY(a29); COPY(a30); COPY(a31);
+	COPY(b16); COPY(b17); COPY(b18); COPY(b19);
+	COPY(b20); COPY(b21); COPY(b22); COPY(b23);
+	COPY(b24); COPY(b25); COPY(b26); COPY(b27);
+	COPY(b28); COPY(b29); COPY(b30); COPY(b31);
+
+	COPY(csr); COPY(pc);
+
+#undef COPY
+
+	return err;
+}
+
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+					struct pt_regs *regs,
+					unsigned long framesize)
+{
+	unsigned long sp = regs->sp;
+
+	/*
+	 * This is the X/Open sanctioned signal stack switching.
+	 */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(sp) == 0)
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	/*
+	 * No matter what happens, 'sp' must be dword
+	 * aligned. Otherwise, nasty things will happen
+	 */
+	return (void __user *)((sp - framesize) & ~7);
+}
+
+static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	unsigned long __user *retcode;
+	int err = 0;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto segv_and_exit;
+
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+
+	/* Clear all the bits of the ucontext we don't use.  */
+	err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
+
+	err |= setup_sigcontext(&frame->uc.uc_mcontext,	regs, set->sig[0]);
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	/* Set up to return from userspace */
+	retcode = (unsigned long __user *) &frame->retcode;
+
+	/* The access_ok check was done above, so use __put_user here */
+#define COPY(x) (err |= __put_user(x, retcode++))
+
+	COPY(0x0000002AUL | (__NR_rt_sigreturn << 7));
+				/* MVK __NR_rt_sigreturn,B0 */
+	COPY(0x10000000UL);	/* SWE */
+	COPY(0x00006000UL);	/* NOP 4 */
+	COPY(0x00006000UL);	/* NOP 4 */
+	COPY(0x00006000UL);	/* NOP 4 */
+	COPY(0x00006000UL);	/* NOP 4 */
+	COPY(0x00006000UL);	/* NOP 4 */
+	COPY(0x00006000UL);	/* NOP 4 */
+	COPY(0x00006000UL);	/* NOP 4 */
+
+#undef COPY
+
+	if (err)
+		goto segv_and_exit;
+
+	flush_icache_range((unsigned long) &frame->retcode,
+			   (unsigned long) &frame->retcode + RETCODE_SIZE);
+
+	retcode = (unsigned long __user *) &frame->retcode;
+
+	/* Change user context to branch to signal handler */
+	regs->sp = (unsigned long) frame - 8;
+	regs->b3 = (unsigned long) retcode;
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+
+	/* Give the signal number to the handler */
+	regs->a4 = signr;
+
+	/*
+	 * For realtime signals we must also set the second and third
+	 * arguments for the signal handler.
+	 *   -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
+	 */
+	regs->b4 = (unsigned long)&frame->info;
+	regs->a6 = (unsigned long)&frame->uc;
+
+	return 0;
+
+segv_and_exit:
+	force_sigsegv(signr, current);
+	return -EFAULT;
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+	switch (regs->a4) {
+	case -ERESTARTNOHAND:
+		if (!has_handler)
+			goto do_restart;
+		regs->a4 = -EINTR;
+		break;
+
+	case -ERESTARTSYS:
+		if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+			regs->a4 = -EINTR;
+			break;
+		}
+	/* fallthrough */
+	case -ERESTARTNOINTR:
+do_restart:
+		regs->a4 = regs->orig_a4;
+		regs->pc -= 4;
+		break;
+	}
+}
+
+/*
+ * handle the actual delivery of a signal to userspace
+ */
+static int handle_signal(int sig,
+			 siginfo_t *info, struct k_sigaction *ka,
+			 sigset_t *oldset, struct pt_regs *regs,
+			 int syscall)
+{
+	int ret;
+
+	/* Are we from a system call? */
+	if (syscall) {
+		/* If so, check system call restarting.. */
+		switch (regs->a4) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->a4 = -EINTR;
+			break;
+
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->a4 = -EINTR;
+				break;
+			}
+
+			/* fallthrough */
+		case -ERESTARTNOINTR:
+			regs->a4 = regs->orig_a4;
+			regs->pc -= 4;
+		}
+	}
+
+	/* Set up the stack frame */
+	ret = setup_rt_frame(sig, ka, info, oldset, regs);
+	if (ret == 0) {
+		spin_lock_irq(&current->sighand->siglock);
+		sigorsets(&current->blocked, &current->blocked,
+			  &ka->sa.sa_mask);
+		if (!(ka->sa.sa_flags & SA_NODEFER))
+			sigaddset(&current->blocked, sig);
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+
+	return ret;
+}
+
+/*
+ * handle a potential signal
+ */
+static void do_signal(struct pt_regs *regs, int syscall)
+{
+	struct k_sigaction ka;
+	siginfo_t info;
+	sigset_t *oldset;
+	int signr;
+
+	/* we want the common case to go fast, which is why we may in certain
+	 * cases get here from kernel mode */
+	if (!user_mode(regs))
+		return;
+
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
+		oldset = &current->blocked;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	if (signr > 0) {
+		if (handle_signal(signr, &info, &ka, oldset,
+				  regs, syscall) == 0) {
+			/* a signal was successfully delivered; the saved
+			 * sigmask will have been stored in the signal frame,
+			 * and will be restored by sigreturn, so we can simply
+			 * clear the TIF_RESTORE_SIGMASK flag */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+
+			tracehook_signal_handler(signr, &info, &ka, regs, 0);
+		}
+
+		return;
+	}
+
+	/* did we come from a system call? */
+	if (syscall) {
+		/* restart the system call - no handlers present */
+		switch (regs->a4) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->a4 = regs->orig_a4;
+			regs->pc -= 4;
+			break;
+
+		case -ERESTART_RESTARTBLOCK:
+			regs->a4 = regs->orig_a4;
+			regs->b0 = __NR_restart_syscall;
+			regs->pc -= 4;
+			break;
+		}
+	}
+
+	/* if there's no signal to deliver, we just put the saved sigmask
+	 * back */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
+}
+
+/*
+ * notification of userspace execution resumption
+ * - triggered by current->work.notify_resume
+ */
+asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags,
+				 int syscall)
+{
+	/* deal with pending signal delivery */
+	if (thread_info_flags & ((1 << TIF_SIGPENDING) |
+				 (1 << TIF_RESTORE_SIGMASK)))
+		do_signal(regs, syscall);
+
+	if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
-- 
1.7.6.2


  parent reply	other threads:[~2011-10-04 16:49 UTC|newest]

Thread overview: 42+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-04 16:43 [PATCH v4 00/24] C6X: New architecture Mark Salter
2011-10-04 16:43 ` [PATCH v4 01/24] fix default __strnlen_user macro Mark Salter
2011-10-04 16:43 ` [PATCH v4 02/24] fixed generic page.h for non-zero PAGE_OFFSET Mark Salter
2011-10-04 16:43 ` [PATCH v4 03/24] add ELF machine define for TI C6X DSPs Mark Salter
2011-10-04 16:43 ` [PATCH v4 04/24] add missing __iomem to generic iounmap declaration Mark Salter
2011-10-04 16:43 ` [PATCH v4 05/24] C6X: build infrastructure Mark Salter
2011-10-04 19:11   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 06/24] C6X: early boot code Mark Salter
2011-10-04 19:11   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 07/24] C6X: devicetree support Mark Salter
2011-10-04 16:43   ` Mark Salter
2011-10-04 19:24   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 08/24] C6X: memory management and DMA support Mark Salter
2011-10-04 19:10   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 09/24] C6X: process management Mark Salter
2011-10-04 16:43 ` Mark Salter [this message]
2011-10-04 16:43 ` [PATCH v4 11/24] C6X: time management Mark Salter
2011-10-04 18:04   ` Thomas Gleixner
2011-10-04 19:13   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 12/24] C6X: interrupt handling Mark Salter
2011-10-04 18:06   ` Thomas Gleixner
2011-10-04 19:12   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 13/24] C6X: syscalls Mark Salter
2011-10-04 16:43 ` [PATCH v4 14/24] C6X: build infrastructure Mark Salter
2011-10-04 16:43 ` [PATCH v4 15/24] C6X: clocks Mark Salter
2011-10-04 16:43 ` [PATCH v4 16/24] C6X: cache control Mark Salter
2011-10-04 16:43 ` [PATCH v4 17/24] C6X: loadable module support Mark Salter
2011-10-04 19:08   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 18/24] C6X: ptrace support Mark Salter
2011-10-04 19:07   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 19/24] C6X: headers Mark Salter
2011-10-04 18:06   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 20/24] C6X: library code Mark Salter
2011-10-04 18:04   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 21/24] C6X: general SoC support Mark Salter
2011-10-04 19:23   ` Arnd Bergmann
2011-10-04 16:43 ` [PATCH v4 22/24] C6X: EMIF - External Memory Interface Mark Salter
2011-10-04 16:44 ` [PATCH v4 23/24] C6X: DSCR - Device State Configuration Registers Mark Salter
2011-10-04 16:44 ` [PATCH v4 24/24] C6X: MAINTAINERS Mark Salter
2011-10-04 19:27 ` [PATCH v4 00/24] C6X: New architecture Arnd Bergmann
2011-10-05 12:52   ` Mark Salter
2011-10-05 16:16     ` Arnd Bergmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1317746641-26725-11-git-send-email-msalter@redhat.com \
    --to=msalter@redhat.com \
    --cc=a-jacquiot@ti.com \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.