Merge branch 'master'
[pandora-kernel.git] / arch / i386 / kernel / signal.c
index 89ef7ad..adcd069 100644 (file)
@@ -278,9 +278,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
        int tmp, err = 0;
 
        tmp = 0;
-       __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
+       savesegment(gs, tmp);
        err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
-       __asm__("movl %%fs,%0" : "=r"(tmp): "0"(tmp));
+       savesegment(fs, tmp);
        err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
 
        err |= __put_user(regs->xes, (unsigned int __user *)&sc->es);
@@ -338,7 +338,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
                esp = (unsigned long) ka->sa.sa_restorer;
        }
 
-       return (void __user *)((esp - frame_size) & -8ul);
+       esp -= frame_size;
+       /* Align the stack pointer according to the i386 ABI,
+        * i.e. so that on function entry ((sp + 4) & 15) == 0. */
+       esp = ((esp + 4) & -16ul) - 4;
+       return (void __user *) esp;
 }
 
 /* These symbols are defined with the addresses in the vsyscall page.
@@ -577,10 +581,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        else
                ret = setup_frame(sig, ka, oldset, regs);
 
-       if (ret && !(ka->sa.sa_flags & SA_NODEFER)) {
+       if (ret) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-               sigaddset(&current->blocked,sig);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
        }
@@ -603,7 +608,9 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
         * We want the common case to go fast, which
         * is why we may in certain cases get here from
         * kernel mode. Just return without doing anything
-        * if so.
+        * if so.  vm86 regs switched out by assembly code
+        * before reaching here, so testing against kernel
+        * CS suffices.
         */
        if (!user_mode(regs))
                return 1;