Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[safe/jmp/linux-2.6] / arch / mips / kernel / signal_n32.c
index 384fc4a..7ca2a07 100644 (file)
@@ -17,7 +17,6 @@
  */
 #include <linux/cache.h>
 #include <linux/sched.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
@@ -32,6 +31,7 @@
 
 #include <asm/asm.h>
 #include <asm/cacheflush.h>
+#include <asm/compat-signal.h>
 #include <asm/sim.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
@@ -48,9 +48,9 @@
 #define __NR_N32_rt_sigreturn          6211
 #define __NR_N32_restart_syscall       6214
 
-#define DEBUG_SIG 0
+extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
+extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 /* IRIX compatible stack_t  */
 typedef struct sigaltstack32 {
@@ -64,26 +64,63 @@ struct ucontextn32 {
        s32                 uc_link;
        stack32_t           uc_stack;
        struct sigcontext   uc_mcontext;
-       sigset_t            uc_sigmask;   /* mask last for extensibility */
+       compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
 };
 
+#if ICACHE_REFILLS_WORKAROUND_WAR == 0
+
 struct rt_sigframe_n32 {
        u32 rs_ass[4];                  /* argument save space for o32 */
-#if ICACHE_REFILLS_WORKAROUND_WAR
-       u32 rs_pad[2];
-#else
        u32 rs_code[2];                 /* signal trampoline */
-#endif
        struct siginfo rs_info;
        struct ucontextn32 rs_uc;
-#if ICACHE_REFILLS_WORKAROUND_WAR
+};
+
+#else  /* ICACHE_REFILLS_WORKAROUND_WAR */
+
+struct rt_sigframe_n32 {
+       u32 rs_ass[4];                  /* argument save space for o32 */
+       u32 rs_pad[2];
+       struct siginfo rs_info;
+       struct ucontextn32 rs_uc;
        u32 rs_code[8] ____cacheline_aligned;           /* signal trampoline */
-#endif
 };
 
-save_static_function(sysn32_rt_sigreturn);
-__attribute_used__ noinline static void
-_sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
+#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
+
+extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat);
+
+asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+{
+       compat_sigset_t __user *unewset;
+       compat_sigset_t uset;
+       size_t sigsetsize;
+       sigset_t newset;
+
+       /* XXX Don't preclude handling different sized sigset_t's.  */
+       sigsetsize = regs.regs[5];
+       if (sigsetsize != sizeof(sigset_t))
+               return -EINVAL;
+
+       unewset = (compat_sigset_t __user *) regs.regs[4];
+       if (copy_from_user(&uset, unewset, sizeof(uset)))
+               return -EFAULT;
+       sigset_from_compat (&newset, &uset);
+       sigdelsetmask(&newset, ~_BLOCKABLE);
+
+       spin_lock_irq(&current->sighand->siglock);
+       current->saved_sigmask = current->blocked;
+       current->blocked = newset;
+       recalc_sigpending();
+       spin_unlock_irq(&current->sighand->siglock);
+
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
+}
+
+asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
 {
        struct rt_sigframe_n32 __user *frame;
        sigset_t set;
@@ -93,7 +130,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        frame = (struct rt_sigframe_n32 __user *) regs.regs[29];
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
-       if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+       if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
@@ -108,7 +145,7 @@ _sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        /* The ucontext contains a stack32_t, so we must convert!  */
        if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
                goto badframe;
-       st.ss_size = (long) sp;
+       st.ss_sp = (void __user *)(long) sp;
        if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
                goto badframe;
        if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
@@ -151,7 +188,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
        /* Create the ucontext.  */
        err |= __put_user(0, &frame->rs_uc.uc_flags);
        err |= __put_user(0, &frame->rs_uc.uc_link);
-        sp = (int) (long) current->sas_ss_sp;
+       sp = (int) (long) current->sas_ss_sp;
        err |= __put_user(sp,
                          &frame->rs_uc.uc_stack.ss_sp);
        err |= __put_user(sas_ss_flags(regs->regs[29]),
@@ -159,7 +196,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
        err |= __put_user(current->sas_ss_size,
                          &frame->rs_uc.uc_stack.ss_size);
        err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
-       err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+       err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 
        if (err)
                goto give_sigsegv;
@@ -181,11 +218,10 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
        regs->regs[31] = (unsigned long) frame->rs_code;
        regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
 
-#if DEBUG_SIG
-       printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n",
+       DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
               current->comm, current->pid,
               frame, regs->cp0_epc, regs->regs[31]);
-#endif
+
        return 0;
 
 give_sigsegv: