]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/hexagon/kernel/signal.c
Merge remote-tracking branch 'hid/for-next'
[karo-tx-linux.git] / arch / hexagon / kernel / signal.c
index 60fa2ca3202be2060f2b9065a51447ab0c34d6d9..d7c73874b5150312196e484bc294b02e14bc7558 100644 (file)
@@ -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;
@@ -193,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;
@@ -210,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:
@@ -234,17 +245,6 @@ 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
  */
@@ -272,21 +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 (restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
-       return 0;
+       return regs->r00;
 
 badframe:
        force_sig(SIGSEGV, current);