aboutsummaryrefslogtreecommitdiff
path: root/arch/hexagon/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/hexagon/kernel/signal.c')
-rw-r--r--arch/hexagon/kernel/signal.c61
1 files changed, 20 insertions, 41 deletions
diff --git a/arch/hexagon/kernel/signal.c b/arch/hexagon/kernel/signal.c
index fe0d1373165..d7c73874b51 100644
--- a/arch/hexagon/kernel/signal.c
+++ b/arch/hexagon/kernel/signal.c
@@ -1,7 +1,7 @@
/*
* Signal support for Hexagon processor
*
- * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -41,6 +41,10 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
{
unsigned long sp = regs->r29;
+ /* check if we would overflow the alt stack */
+ if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
+ return (void __user __force *)-1UL;
+
/* Switch to signal stack if appropriate */
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
@@ -66,7 +70,10 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
err |= __put_user(regs->preds, &sc->sc_regs.p3_0);
err |= __put_user(regs->gp, &sc->sc_regs.gp);
err |= __put_user(regs->ugp, &sc->sc_regs.ugp);
-
+#if CONFIG_HEXAGON_ARCH_VERSION >= 4
+ err |= __put_user(regs->cs0, &sc->sc_regs.cs0);
+ err |= __put_user(regs->cs1, &sc->sc_regs.cs1);
+#endif
tmp = pt_elr(regs); err |= __put_user(tmp, &sc->sc_regs.pc);
tmp = pt_cause(regs); err |= __put_user(tmp, &sc->sc_regs.cause);
tmp = pt_badva(regs); err |= __put_user(tmp, &sc->sc_regs.badva);
@@ -93,7 +100,10 @@ static int restore_sigcontext(struct pt_regs *regs,
err |= __get_user(regs->preds, &sc->sc_regs.p3_0);
err |= __get_user(regs->gp, &sc->sc_regs.gp);
err |= __get_user(regs->ugp, &sc->sc_regs.ugp);
-
+#if CONFIG_HEXAGON_ARCH_VERSION >= 4
+ err |= __get_user(regs->cs0, &sc->sc_regs.cs0);
+ err |= __get_user(regs->cs1, &sc->sc_regs.cs1);
+#endif
err |= __get_user(tmp, &sc->sc_regs.pc); pt_set_elr(regs, tmp);
return err;
@@ -125,6 +135,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(0x5400c004, &frame->tramp[1]);
err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+ err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs));
if (err)
goto sigsegv;
@@ -192,7 +203,7 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
/*
* Called from return-from-event code.
*/
-static void do_signal(struct pt_regs *regs)
+void do_signal(struct pt_regs *regs)
{
struct k_sigaction sigact;
siginfo_t info;
@@ -209,8 +220,9 @@ static void do_signal(struct pt_regs *regs)
}
/*
- * If we came from a system call, handle the restart.
+ * No (more) signals; if we came from a system call, handle the restart.
*/
+
if (regs->syscall_nr >= 0) {
switch (regs->r00) {
case -ERESTARTNOHAND:
@@ -233,26 +245,9 @@ no_restart:
restore_saved_sigmask();
}
-void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
-{
- if (thread_info_flags & _TIF_SIGPENDING)
- do_signal(regs);
-
- if (thread_info_flags & _TIF_NOTIFY_RESUME) {
- clear_thread_flag(TIF_NOTIFY_RESUME);
- tracehook_notify_resume(regs);
- }
-}
-
/*
* Architecture-specific wrappers for signal-related system calls
*/
-asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
-{
- struct pt_regs *regs = current_pt_regs();
-
- return do_sigaltstack(uss, uoss, regs->r29);
-}
asmlinkage int sys_rt_sigreturn(void)
{
@@ -277,28 +272,12 @@ asmlinkage int sys_rt_sigreturn(void)
/* Restore the user's stack as well */
pt_psp(regs) = regs->r29;
- /*
- * Leave a trace in the stack frame that this was a sigreturn.
- * If the system call is to replay, we've already restored the
- * number in the GPR slot and it will be regenerated on the
- * new system call trap entry. Note that if restore_sigcontext()
- * did something other than a bulk copy of the pt_regs struct,
- * we could avoid this assignment by simply not overwriting
- * regs->syscall_nr.
- */
- regs->syscall_nr = __NR_rt_sigreturn;
+ regs->syscall_nr = -1;
- /*
- * If we were meticulous, we'd only call this if we knew that
- * we were actually going to use an alternate stack, and we'd
- * consider any error to be fatal. What we do here, in common
- * with many other architectures, is call it blindly and only
- * consider the -EFAULT return case to be proof of a problem.
- */
- if (do_sigaltstack(&frame->uc.uc_stack, NULL, pt_psp(regs)) == -EFAULT)
+ if (restore_altstack(&frame->uc.uc_stack))
goto badframe;
- return 0;
+ return regs->r00;
badframe:
force_sig(SIGSEGV, current);