fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / x86_64 / ia32 / ia32_signal.c
index e0a9243..5799853 100644 (file)
@@ -6,8 +6,6 @@
  *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  *  2000-12-*   x86-64 compatibility mode signal handling by Andi Kleen
- * 
- *  $Id: ia32_signal.c,v 1.22 2002/07/29 10:34:03 ak Exp $
  */
 
 #include <linux/sched.h>
@@ -23,6 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/personality.h>
 #include <linux/compat.h>
+#include <linux/binfmts.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
@@ -115,25 +114,19 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 }
 
 asmlinkage long
-sys32_sigsuspend(int history0, int history1, old_sigset_t mask,
-                struct pt_regs *regs)
+sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
 {
-       sigset_t saveset;
-
        mask &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        siginitset(&current->blocked, mask);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       regs->rax = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
 }
 
 asmlinkage long
@@ -439,15 +432,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
                goto give_sigsegv;
 
-       {
-               struct exec_domain *ed = current_thread_info()->exec_domain;
-               err |= __put_user((ed
-                          && ed->signal_invmap
-                          && sig < 32
-                          ? ed->signal_invmap[sig]
-                          : sig),
-                         &frame->sig);
-       }
+       err |= __put_user(sig, &frame->sig);
        if (err)
                goto give_sigsegv;
 
@@ -465,7 +450,11 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
 
        /* Return stub is in 32bit vsyscall page */
        { 
-               void __user *restorer = VSYSCALL32_SIGRETURN; 
+               void __user *restorer;
+               if (current->binfmt->hasvdso)
+                       restorer = VSYSCALL32_SIGRETURN;
+               else
+                       restorer = (void *)&frame->retcode;
                if (ka->sa.sa_flags & SA_RESTORER)
                        restorer = ka->sa.sa_restorer;       
                err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
@@ -494,27 +483,28 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
        regs->rsp = (unsigned long) frame;
        regs->rip = (unsigned long) ka->sa.sa_handler;
 
+       /* Make -mregparm=3 work */
+       regs->rax = sig;
+       regs->rdx = 0;
+       regs->rcx = 0;
+
        asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); 
        asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); 
 
        regs->cs = __USER32_CS; 
        regs->ss = __USER32_DS; 
-
        set_fs(USER_DS);
-    regs->eflags &= ~TF_MASK;
-    if (test_thread_flag(TIF_SINGLESTEP))
-        ptrace_notify(SIGTRAP);
 
 #if DEBUG_SIG
        printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
                current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
-       return 1;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
-       return 0;
+       return -EFAULT;
 }
 
 int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -590,6 +580,16 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->rsp = (unsigned long) frame;
        regs->rip = (unsigned long) ka->sa.sa_handler;
 
+       /* Make -mregparm=3 work */
+       regs->rax = sig;
+       regs->rdx = (unsigned long) &frame->info;
+       regs->rcx = (unsigned long) &frame->uc;
+
+       /* Make -mregparm=3 work */
+       regs->rax = sig;
+       regs->rdx = (unsigned long) &frame->info;
+       regs->rcx = (unsigned long) &frame->uc;
+
        asm volatile("movl %0,%%ds" :: "r" (__USER32_DS)); 
        asm volatile("movl %0,%%es" :: "r" (__USER32_DS)); 
        
@@ -597,18 +597,15 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->ss = __USER32_DS; 
 
        set_fs(USER_DS);
-    regs->eflags &= ~TF_MASK;
-    if (test_thread_flag(TIF_SINGLESTEP))
-        ptrace_notify(SIGTRAP);
 
 #if DEBUG_SIG
        printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
                current->comm, current->pid, frame, regs->rip, frame->pretcode);
 #endif
 
-       return 1;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
-       return 0;
+       return -EFAULT;
 }