]> err.no Git - linux-2.6/blobdiff - arch/powerpc/kernel/signal_64.c
[POWERPC] Fix bootwrapper builds with newer gcc versions
[linux-2.6] / arch / powerpc / kernel / signal_64.c
index c17903cd384a4c46c42c57326ab8eb0fde027969..da7c058e3731ffc712367f7f2f4e01e572d0055d 100644 (file)
@@ -64,6 +64,11 @@ struct rt_sigframe {
        char abigap[288];
 } __attribute__ ((aligned (16)));
 
+static const char fmt32[] = KERN_INFO \
+       "%s[%d]: bad frame in %s: %08lx nip %08lx lr %08lx\n";
+static const char fmt64[] = KERN_INFO \
+       "%s[%d]: bad frame in %s: %016lx nip %016lx lr %016lx\n";
+
 /*
  * Set up the sigcontext for the signal frame.
  */
@@ -82,6 +87,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 #ifdef CONFIG_ALTIVEC
        elf_vrreg_t __user *v_regs = (elf_vrreg_t __user *)(((unsigned long)sc->vmx_reserve + 15) & ~0xful);
 #endif
+       unsigned long msr = regs->msr;
        long err = 0;
 
        flush_fp_to_thread(current);
@@ -97,7 +103,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
                /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg)
                 * contains valid data.
                 */
-               regs->msr |= MSR_VEC;
+               msr |= MSR_VEC;
        }
        /* We always copy to/from vrsave, it's 0 if we don't have or don't
         * use altivec.
@@ -109,6 +115,7 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
        err |= __put_user(&sc->gp_regs, &sc->regs);
        WARN_ON(!FULL_REGS(regs));
        err |= __copy_to_user(&sc->gp_regs, regs, GP_REGS_SIZE);
+       err |= __put_user(msr, &sc->gp_regs[PT_MSR]);
        err |= __copy_to_user(&sc->fp_regs, &current->thread.fpr, FP_REGS_SIZE);
        err |= __put_user(signr, &sc->signal);
        err |= __put_user(handler, &sc->handler);
@@ -168,6 +175,13 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
         */
        discard_lazy_cpu_state();
 
+       /*
+        * Force reload of FP/VEC.
+        * This has to be done before copying stuff into current->thread.fpr/vr
+        * for the reasons explained in the previous comment.
+        */
+       regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
+
        err |= __copy_from_user(&current->thread.fpr, &sc->fp_regs, FP_REGS_SIZE);
 
 #ifdef CONFIG_ALTIVEC
@@ -189,31 +203,9 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
                current->thread.vrsave = 0;
 #endif /* CONFIG_ALTIVEC */
 
-       /* Force reload of FP/VEC */
-       regs->msr &= ~(MSR_FP | MSR_FE0 | MSR_FE1 | MSR_VEC);
-
        return err;
 }
 
-/*
- * Allocate space for the signal frame
- */
-static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
-                                 size_t frame_size)
-{
-        unsigned long newsp;
-
-        /* Default to using normal stack */
-        newsp = regs->gpr[1];
-
-       if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
-               if (! on_sig_stack(regs->gpr[1]))
-                       newsp = (current->sas_ss_sp + current->sas_ss_size);
-       }
-
-        return (void __user *)((newsp - frame_size) & -16ul);
-}
-
 /*
  * Setup the trampoline code on the stack
  */
@@ -330,6 +322,11 @@ badframe:
        printk("badframe in sys_rt_sigreturn, regs=%p uc=%p &uc->uc_mcontext=%p\n",
               regs, uc, &uc->uc_mcontext);
 #endif
+       if (show_unhandled_signals && printk_ratelimit())
+               printk(regs->msr & MSR_SF ? fmt64 : fmt32,
+                       current->comm, current->pid, "rt_sigreturn",
+                       (long)uc, regs->nip, regs->link);
+
        force_sig(SIGSEGV, current);
        return 0;
 }
@@ -348,8 +345,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
        long err = 0;
 
        frame = get_sigframe(ka, regs, sizeof(*frame));
-
-       if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+       if (unlikely(frame == NULL))
                goto badframe;
 
        err |= __put_user(&frame->info, &frame->pinfo);
@@ -386,7 +382,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
        funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
 
        /* Allocate a dummy caller frame for the signal handler. */
-       newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE;
+       newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
        err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
 
        /* Set up "regs" so we "return" to the signal handler. */
@@ -414,6 +410,11 @@ badframe:
        printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
               regs, frame, newsp);
 #endif
+       if (show_unhandled_signals && printk_ratelimit())
+               printk(regs->msr & MSR_SF ? fmt64 : fmt32,
+                       current->comm, current->pid, "setup_rt_frame",
+                       (long)frame, regs->nip, regs->link);
+
        force_sigsegv(signr, current);
        return 0;
 }