[SPARC]: Add support for *at(), ppoll, and pselect syscalls.
David S. Miller [Thu, 19 Jan 2006 10:42:49 +0000 (02:42 -0800)]
This also includes by necessity _TIF_RESTORE_SIGMASK support,
which actually resulted in a lot of cleanups.

The sparc signal handling code is quite a mess and I should
clean it up some day.

Signed-off-by: David S. Miller <davem@davemloft.net>

16 files changed:
arch/sparc/kernel/entry.S
arch/sparc/kernel/rtrap.S
arch/sparc/kernel/signal.c
arch/sparc/kernel/sparc_ksyms.c
arch/sparc/kernel/systbls.S
arch/sparc64/kernel/entry.S
arch/sparc64/kernel/rtrap.S
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/sparc64_ksyms.c
arch/sparc64/kernel/systbls.S
arch/sparc64/solaris/entry64.S
include/asm-sparc/thread_info.h
include/asm-sparc/unistd.h
include/asm-sparc64/thread_info.h
include/asm-sparc64/unistd.h

index 03ecb4e..c51d08d 100644 (file)
@@ -1277,62 +1277,6 @@ sys_sigstack:
         mov    %l5, %o7
 
        .align  4
-       .globl  sys_sigpause
-sys_sigpause:
-       /* Note: %o0 already has correct value... */
-       call    do_sigpause
-        add    %sp, STACKFRAME_SZ, %o1
-
-       ld      [%curptr + TI_FLAGS], %l5
-       andcc   %l5, _TIF_SYSCALL_TRACE, %g0
-       be      1f
-        nop
-
-       call    syscall_trace
-        nop
-
-1:
-       /* We are returning to a signal handler. */
-       RESTORE_ALL
-
-       .align  4
-       .globl  sys_sigsuspend
-sys_sigsuspend:
-       call    do_sigsuspend
-        add    %sp, STACKFRAME_SZ, %o0
-
-       ld      [%curptr + TI_FLAGS], %l5
-       andcc   %l5, _TIF_SYSCALL_TRACE, %g0
-       be      1f
-        nop
-
-       call    syscall_trace
-        nop
-
-1:
-       /* We are returning to a signal handler. */
-       RESTORE_ALL
-
-       .align  4
-       .globl  sys_rt_sigsuspend
-sys_rt_sigsuspend:
-       /* Note: %o0, %o1 already have correct value... */
-       call    do_rt_sigsuspend
-        add    %sp, STACKFRAME_SZ, %o2
-
-       ld      [%curptr + TI_FLAGS], %l5
-       andcc   %l5, _TIF_SYSCALL_TRACE, %g0
-       be      1f
-        nop
-
-       call    syscall_trace
-        nop
-
-1:
-       /* We are returning to a signal handler. */
-       RESTORE_ALL
-
-       .align  4
        .globl  sys_sigreturn
 sys_sigreturn:
        call    do_sigreturn
index f7460d8..77ca6fd 100644 (file)
@@ -68,15 +68,14 @@ ret_trap_lockless_ipi:
 
        ld      [%curptr + TI_FLAGS], %g2
 signal_p:
-       andcc   %g2, (_TIF_NOTIFY_RESUME|_TIF_SIGPENDING), %g0
+       andcc   %g2, (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %g0
        bz,a    ret_trap_continue
         ld     [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
 
-       clr     %o0
-       mov     %l5, %o2
-       mov     %l6, %o3
+       mov     %l5, %o1
+       mov     %l6, %o2
        call    do_signal
-        add    %sp, STACKFRAME_SZ, %o1 ! pt_regs ptr
+        add    %sp, STACKFRAME_SZ, %o0 ! pt_regs ptr
 
        /* Fall through. */
        ld      [%sp + STACKFRAME_SZ + PT_PSR], %t_psr
index 5f34d7d..0748d81 100644 (file)
@@ -35,9 +35,6 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
                   void *fpqueue, unsigned long *fpqdepth);
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
 
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
-                        unsigned long orig_o0, int restart_syscall);
-
 /* Signal frames: the original one (compatible with SunOS):
  *
  * Set up a signal frame... Make the stack look the way SunOS
@@ -95,98 +92,30 @@ struct rt_signal_frame {
 #define NF_ALIGNEDSZ  (((sizeof(struct new_signal_frame) + 7) & (~7)))
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
+static int _sigpause_common(old_sigset_t set)
 {
-       sigset_t saveset;
-
        set &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        siginitset(&current->blocked, set);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       regs->pc = regs->npc;
-       regs->npc += 4;
-
-       /* Condition codes and return value where set here for sigpause,
-        * and so got used by setup_frame, which again causes sigreturn()
-        * to return -EINTR.
-        */
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               /*
-                * Return -EINTR and set condition code here,
-                * so the interrupted system call actually returns
-                * these.
-                */
-               regs->psr |= PSR_C;
-               regs->u_regs[UREG_I0] = EINTR;
-               if (do_signal(&saveset, regs, 0, 0))
-                       return;
-       }
-}
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
 
-asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
-{
-       _sigpause_common(set, regs);
+       return -ERESTARTNOHAND;
 }
 
-asmlinkage void do_sigsuspend (struct pt_regs *regs)
+asmlinkage int sys_sigpause(unsigned int set)
 {
-       _sigpause_common(regs->u_regs[UREG_I0], regs);
+       return _sigpause_common(set);
 }
 
-asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
-                                struct pt_regs *regs)
+asmlinkage int sys_sigsuspend(old_sigset_t set)
 {
-       sigset_t oldset, set;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t)) {
-               regs->psr |= PSR_C;
-               regs->u_regs[UREG_I0] = EINVAL;
-               return;
-       }
-
-       if (copy_from_user(&set, uset, sizeof(set))) {
-               regs->psr |= PSR_C;
-               regs->u_regs[UREG_I0] = EFAULT;
-               return;
-       }
-
-       sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       oldset = current->blocked;
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs->pc = regs->npc;
-       regs->npc += 4;
-
-       /* Condition codes and return value where set here for sigpause,
-        * and so got used by setup_frame, which again causes sigreturn()
-        * to return -EINTR.
-        */
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               /*
-                * Return -EINTR and set condition code here,
-                * so the interrupted system call actually returns
-                * these.
-                */
-               regs->psr |= PSR_C;
-               regs->u_regs[UREG_I0] = EINTR;
-               if (do_signal(&oldset, regs, 0, 0))
-                       return;
-       }
+       return _sigpause_common(set);
 }
 
 static inline int
@@ -1067,13 +996,13 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
-                        unsigned long orig_i0, int restart_syscall)
+asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int restart_syscall)
 {
        siginfo_t info;
        struct sparc_deliver_cookie cookie;
        struct k_sigaction ka;
        int signr;
+       sigset_t *oldset;
 
        /*
         * XXX Disable svr4 signal handling until solaris emulation works.
@@ -1089,7 +1018,9 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
        cookie.restart_syscall = restart_syscall;
        cookie.orig_i0 = orig_i0;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, &cookie);
@@ -1098,7 +1029,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
                        syscall_restart(cookie.orig_i0, regs, &ka.sa);
                handle_signal(signr, &ka, &info, oldset,
                              regs, svr4_signal);
-               return 1;
+               /* a signal was successfully delivered; the saved
+                * sigmask will have been stored in the signal frame,
+                * and will be restored by sigreturn, so we can simply
+                * clear the TIF_RESTORE_SIGMASK flag.
+                */
+               if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+               return;
        }
        if (cookie.restart_syscall &&
            (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1115,7 +1053,14 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
                regs->pc -= 4;
                regs->npc -= 4;
        }
-       return 0;
+
+       /* if there's no signal to deliver, we just put the saved sigmask
+        * back
+        */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
 }
 
 asmlinkage int
index 0b0d492..19b2539 100644 (file)
@@ -66,7 +66,6 @@ struct poll {
 
 extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *);
 extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *);
-void _sigpause_common (unsigned int set, struct pt_regs *);
 extern void (*__copy_1page)(void *, const void *);
 extern void __memmove(void *, const void *, __kernel_size_t);
 extern void (*bzero_1page)(void *);
@@ -227,7 +226,6 @@ EXPORT_SYMBOL(kunmap_atomic);
 /* Solaris/SunOS binary compatibility */
 EXPORT_SYMBOL(svr4_setcontext);
 EXPORT_SYMBOL(svr4_getcontext);
-EXPORT_SYMBOL(_sigpause_common);
 
 EXPORT_SYMBOL(dump_thread);
 
index e457a40..6877ae4 100644 (file)
@@ -75,7 +75,10 @@ sys_call_table:
 /*265*/        .long sys_timer_delete, sys_timer_create, sys_nis_syscall, sys_io_setup, sys_io_destroy
 /*270*/        .long sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
 /*275*/        .long sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/        .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/        .long sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+/*285*/        .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_newfstatat
+/*290*/        .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+/*295*/        .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll
 
 #ifdef CONFIG_SUNOS_EMUL
        /* Now the SunOS syscall table. */
@@ -181,6 +184,11 @@ sunos_sys_table:
        .long sunos_nosys, sunos_nosys, sunos_nosys
        .long sunos_nosys
 /*280*/        .long sunos_nosys, sunos_nosys, sunos_nosys
+       .long sunos_nosys, sunos_nosys, sunos_nosys
+       .long sunos_nosys, sunos_nosys, sunos_nosys
        .long sunos_nosys
+/*290*/        .long sunos_nosys, sunos_nosys, sunos_nosys
+       .long sunos_nosys, sunos_nosys, sunos_nosys
+       .long sunos_nosys, sunos_nosys, sunos_nosys
 
 #endif
index 7100029..e50e56e 100644 (file)
@@ -1416,7 +1416,6 @@ execve_merge:
         add            %sp, PTREGS_OFF, %o0
 
        .globl  sys_pipe, sys_sigpause, sys_nis_syscall
-       .globl  sys_sigsuspend, sys_rt_sigsuspend
        .globl  sys_rt_sigreturn
        .globl  sys_ptrace
        .globl  sys_sigaltstack
@@ -1440,28 +1439,6 @@ sys32_sigaltstack:
                 mov            %i6, %o2
 #endif
                .align          32
-sys_sigsuspend:        add             %sp, PTREGS_OFF, %o0
-               call            do_sigsuspend
-                add            %o7, 1f-.-4, %o7
-               nop
-sys_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
-               add             %sp, PTREGS_OFF, %o2
-               call            do_rt_sigsuspend
-                add            %o7, 1f-.-4, %o7
-               nop
-#ifdef CONFIG_COMPAT
-       .globl  sys32_rt_sigsuspend
-sys32_rt_sigsuspend: /* NOTE: %o0,%o1 have a correct value already */
-               srl             %o0, 0, %o0
-               add             %sp, PTREGS_OFF, %o2
-               call            do_rt_sigsuspend32
-                add            %o7, 1f-.-4, %o7
-#endif
-               /* NOTE: %o0 has a correct value already */
-sys_sigpause:  add             %sp, PTREGS_OFF, %o1
-               call            do_sigpause
-                add            %o7, 1f-.-4, %o7
-               nop
 #ifdef CONFIG_COMPAT
        .globl  sys32_sigreturn
 sys32_sigreturn:
index 090dcca..b80eba0 100644 (file)
@@ -53,14 +53,13 @@ __handle_user_windows:
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
                ldx                     [%g6 + TI_FLAGS], %l0
 
-1:             andcc                   %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+1:             andcc                   %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
                be,pt                   %xcc, __handle_user_windows_continue
                 nop
-               clr                     %o0
-               mov                     %l5, %o2
-               mov                     %l6, %o3
-               add                     %sp, PTREGS_OFF, %o1
-               mov                     %l0, %o4
+               mov                     %l5, %o1
+               mov                     %l6, %o2
+               add                     %sp, PTREGS_OFF, %o0
+               mov                     %l0, %o3
 
                call                    do_notify_resume
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
@@ -96,15 +95,14 @@ __handle_perfctrs:
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
                ldx                     [%g6 + TI_FLAGS], %l0
-1:             andcc                   %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+1:             andcc                   %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
 
                be,pt                   %xcc, __handle_perfctrs_continue
                 sethi                  %hi(TSTATE_PEF), %o0
-               clr                     %o0
-               mov                     %l5, %o2
-               mov                     %l6, %o3
-               add                     %sp, PTREGS_OFF, %o1
-               mov                     %l0, %o4
+               mov                     %l5, %o1
+               mov                     %l6, %o2
+               add                     %sp, PTREGS_OFF, %o0
+               mov                     %l0, %o3
                call                    do_notify_resume
 
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
@@ -129,11 +127,10 @@ __handle_userfpu:
                ba,a,pt                 %xcc, __handle_userfpu_continue
 
 __handle_signal:
-               clr                     %o0
-               mov                     %l5, %o2
-               mov                     %l6, %o3
-               add                     %sp, PTREGS_OFF, %o1
-               mov                     %l0, %o4
+               mov                     %l5, %o1
+               mov                     %l6, %o2
+               add                     %sp, PTREGS_OFF, %o0
+               mov                     %l0, %o3
                call                    do_notify_resume
                 wrpr                   %g0, RTRAP_PSTATE, %pstate
                wrpr                    %g0, RTRAP_PSTATE_IRQOFF, %pstate
@@ -200,7 +197,7 @@ __handle_preemption_continue:
                 andcc                  %l1, %o0, %g0
                andcc                   %l0, _TIF_NEED_RESCHED, %g0
                bne,pn                  %xcc, __handle_preemption
-                andcc                  %l0, (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING), %g0
+                andcc                  %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0
                bne,pn                  %xcc, __handle_signal
 __handle_signal_continue:
                 ldub                   [%g6 + TI_WSAVED], %o2
index 60f5dfa..ca11a4c 100644 (file)
@@ -36,9 +36,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-static int do_signal(sigset_t *oldset, struct pt_regs * regs,
-                    unsigned long orig_o0, int ret_from_syscall);
-
 /* {set, get}context() needed for 64-bit SparcLinux userland. */
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
 {
@@ -242,114 +239,29 @@ struct rt_signal_frame {
 /* Align macros */
 #define RT_ALIGNEDSZ  (((sizeof(struct rt_signal_frame) + 7) & (~7)))
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause_common(old_sigset_t set, struct pt_regs *regs)
+static long _sigpause_common(old_sigset_t set)
 {
-       sigset_t saveset;
-
-#ifdef CONFIG_SPARC32_COMPAT
-       if (test_thread_flag(TIF_32BIT)) {
-               extern asmlinkage void _sigpause32_common(compat_old_sigset_t,
-                                                         struct pt_regs *);
-               _sigpause32_common(set, regs);
-               return;
-       }
-#endif
        set &= _BLOCKABLE;
        spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
+       current->saved_sigmask = current->blocked;
        siginitset(&current->blocked, set);
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
-       
-       if (test_thread_flag(TIF_32BIT)) {
-               regs->tpc = (regs->tnpc & 0xffffffff);
-               regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
-       } else {
-               regs->tpc = regs->tnpc;
-               regs->tnpc += 4;
-       }
 
-       /* Condition codes and return value where set here for sigpause,
-        * and so got used by setup_frame, which again causes sigreturn()
-        * to return -EINTR.
-        */
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               /*
-                * Return -EINTR and set condition code here,
-                * so the interrupted system call actually returns
-                * these.
-                */
-               regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-               regs->u_regs[UREG_I0] = EINTR;
-               if (do_signal(&saveset, regs, 0, 0))
-                       return;
-       }
+       current->state = TASK_INTERRUPTIBLE;
+       schedule();
+       set_thread_flag(TIF_RESTORE_SIGMASK);
+       return -ERESTARTNOHAND;
 }
 
-asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
+asmlinkage long sys_sigpause(unsigned int set)
 {
-       _sigpause_common(set, regs);
+       return _sigpause_common(set);
 }
 
-asmlinkage void do_sigsuspend(struct pt_regs *regs)
+asmlinkage long sys_sigsuspend(old_sigset_t set)
 {
-       _sigpause_common(regs->u_regs[UREG_I0], regs);
-}
-
-asmlinkage void do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, struct pt_regs *regs)
-{
-       sigset_t oldset, set;
-        
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t)) {
-               regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-               regs->u_regs[UREG_I0] = EINVAL;
-               return;
-       }
-       if (copy_from_user(&set, uset, sizeof(set))) {
-               regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-               regs->u_regs[UREG_I0] = EFAULT;
-               return;
-       }
-                                                                
-       sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       oldset = current->blocked;
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-       
-       if (test_thread_flag(TIF_32BIT)) {
-               regs->tpc = (regs->tnpc & 0xffffffff);
-               regs->tnpc = (regs->tnpc + 4) & 0xffffffff;
-       } else {
-               regs->tpc = regs->tnpc;
-               regs->tnpc += 4;
-       }
-
-       /* Condition codes and return value where set here for sigpause,
-        * and so got used by setup_frame, which again causes sigreturn()
-        * to return -EINTR.
-        */
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               /*
-                * Return -EINTR and set condition code here,
-                * so the interrupted system call actually returns
-                * these.
-                */
-               regs->tstate |= (TSTATE_ICARRY|TSTATE_XCARRY);
-               regs->u_regs[UREG_I0] = EINTR;
-               if (do_signal(&oldset, regs, 0, 0))
-                       return;
-       }
+       return _sigpause_common(set);
 }
 
 static inline int
@@ -607,26 +519,29 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-static int do_signal(sigset_t *oldset, struct pt_regs * regs,
-                    unsigned long orig_i0, int restart_syscall)
+static void do_signal(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall)
 {
        siginfo_t info;
        struct signal_deliver_cookie cookie;
        struct k_sigaction ka;
        int signr;
+       sigset_t *oldset;
        
        cookie.restart_syscall = restart_syscall;
        cookie.orig_i0 = orig_i0;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
 #ifdef CONFIG_SPARC32_COMPAT
        if (test_thread_flag(TIF_32BIT)) {
-               extern int do_signal32(sigset_t *, struct pt_regs *,
-                                      unsigned long, int);
-               return do_signal32(oldset, regs, orig_i0,
-                                  cookie.restart_syscall);
+               extern void do_signal32(sigset_t *, struct pt_regs *,
+                                       unsigned long, int);
+               do_signal32(oldset, regs, orig_i0,
+                           cookie.restart_syscall);
+               return;
        }
 #endif 
 
@@ -635,7 +550,15 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
                if (cookie.restart_syscall)
                        syscall_restart(orig_i0, regs, &ka.sa);
                handle_signal(signr, &ka, &info, oldset, regs);
-               return 1;
+
+               /* a signal was successfully delivered; the saved
+                * sigmask will have been stored in the signal frame,
+                * and will be restored by sigreturn, so we can simply
+                * clear the TIF_RESTORE_SIGMASK flag.
+                */
+               if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+               return;
        }
        if (cookie.restart_syscall &&
            (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -652,15 +575,21 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
                regs->tpc -= 4;
                regs->tnpc -= 4;
        }
-       return 0;
+
+       /* if there's no signal to deliver, we just put the saved sigmask
+        * back
+        */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
 }
 
-void do_notify_resume(sigset_t *oldset, struct pt_regs *regs,
-                     unsigned long orig_i0, int restart_syscall,
+void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, int restart_syscall,
                      unsigned long thread_info_flags)
 {
-       if (thread_info_flags & _TIF_SIGPENDING)
-               do_signal(oldset, regs, orig_i0, restart_syscall);
+       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+               do_signal(regs, orig_i0, restart_syscall);
 }
 
 void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
index 009a86e..708ba9b 100644 (file)
@@ -32,9 +32,6 @@
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
-int do_signal32(sigset_t *oldset, struct pt_regs *regs,
-               unsigned long orig_o0, int ret_from_syscall);
-
 /* Signal frames: the original one (compatible with SunOS):
  *
  * Set up a signal frame... Make the stack look the way SunOS
@@ -226,102 +223,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
        return 0;
 }
 
-/*
- * atomically swap in the new signal mask, and wait for a signal.
- * This is really tricky on the Sparc, watch out...
- */
-asmlinkage void _sigpause32_common(compat_old_sigset_t set, struct pt_regs *regs)
-{
-       sigset_t saveset;
-
-       set &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       siginitset(&current->blocked, set);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-       
-       regs->tpc = regs->tnpc;
-       regs->tnpc += 4;
-       if (test_thread_flag(TIF_32BIT)) {
-               regs->tpc &= 0xffffffff;
-               regs->tnpc &= 0xffffffff;
-       }
-
-       /* Condition codes and return value where set here for sigpause,
-        * and so got used by setup_frame, which again causes sigreturn()
-        * to return -EINTR.
-        */
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               /*
-                * Return -EINTR and set condition code here,
-                * so the interrupted system call actually returns
-                * these.
-                */
-               regs->tstate |= TSTATE_ICARRY;
-               regs->u_regs[UREG_I0] = EINTR;
-               if (do_signal32(&saveset, regs, 0, 0))
-                       return;
-       }
-}
-
-asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *regs)
-{
-       sigset_t oldset, set;
-       compat_sigset_t set32;
-        
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (((compat_size_t)sigsetsize) != sizeof(sigset_t)) {
-               regs->tstate |= TSTATE_ICARRY;
-               regs->u_regs[UREG_I0] = EINVAL;
-               return;
-       }
-       if (copy_from_user(&set32, compat_ptr(uset), sizeof(set32))) {
-               regs->tstate |= TSTATE_ICARRY;
-               regs->u_regs[UREG_I0] = EFAULT;
-               return;
-       }
-       switch (_NSIG_WORDS) {
-       case 4: set.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
-       case 3: set.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
-       case 2: set.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
-       case 1: set.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
-       }
-       sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       oldset = current->blocked;
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-       
-       regs->tpc = regs->tnpc;
-       regs->tnpc += 4;
-       if (test_thread_flag(TIF_32BIT)) {
-               regs->tpc &= 0xffffffff;
-               regs->tnpc &= 0xffffffff;
-       }
-
-       /* Condition codes and return value where set here for sigpause,
-        * and so got used by setup_frame, which again causes sigreturn()
-        * to return -EINTR.
-        */
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               /*
-                * Return -EINTR and set condition code here,
-                * so the interrupted system call actually returns
-                * these.
-                */
-               regs->tstate |= TSTATE_ICARRY;
-               regs->u_regs[UREG_I0] = EINTR;
-               if (do_signal32(&oldset, regs, 0, 0))
-                       return;
-       }
-}
-
 static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t __user *fpu)
 {
        unsigned long *fpregs = current_thread_info()->fpregs;
@@ -1362,8 +1263,8 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs
  * want to handle. Thus you cannot kill init even with a SIGKILL even by
  * mistake.
  */
-int do_signal32(sigset_t *oldset, struct pt_regs * regs,
-               unsigned long orig_i0, int restart_syscall)
+void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+                unsigned long orig_i0, int restart_syscall)
 {
        siginfo_t info;
        struct signal_deliver_cookie cookie;
@@ -1380,7 +1281,15 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
                        syscall_restart32(orig_i0, regs, &ka.sa);
                handle_signal32(signr, &ka, &info, oldset,
                                regs, svr4_signal);
-               return 1;
+
+               /* a signal was successfully delivered; the saved
+                * sigmask will have been stored in the signal frame,
+                * and will be restored by sigreturn, so we can simply
+                * clear the TIF_RESTORE_SIGMASK flag.
+                */
+               if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+               return;
        }
        if (cookie.restart_syscall &&
            (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
@@ -1397,7 +1306,14 @@ int do_signal32(sigset_t *oldset, struct pt_regs * regs,
                regs->tpc -= 4;
                regs->tnpc -= 4;
        }
-       return 0;
+
+       /* if there's no signal to deliver, we just put the saved sigmask
+        * back
+        */
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
 }
 
 struct sigstack32 {
index d177d7e..3c06bfb 100644 (file)
@@ -69,7 +69,6 @@ struct poll {
 
 extern void die_if_kernel(char *str, struct pt_regs *regs);
 extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
-void _sigpause_common (unsigned int set, struct pt_regs *);
 extern void *__bzero(void *, size_t);
 extern void *__memscan_zero(void *, size_t);
 extern void *__memscan_generic(void *, int, size_t);
@@ -236,9 +235,10 @@ EXPORT_SYMBOL(pci_dma_supported);
 /* I/O device mmaping on Sparc64. */
 EXPORT_SYMBOL(io_remap_pfn_range);
 
+#ifdef CONFIG_COMPAT
 /* Solaris/SunOS binary compatibility */
-EXPORT_SYMBOL(_sigpause_common);
 EXPORT_SYMBOL(verify_compat_iovec);
+#endif
 
 EXPORT_SYMBOL(dump_fpu);
 EXPORT_SYMBOL(pte_alloc_one_kernel);
index 98d24bc..5ed1a17 100644 (file)
@@ -41,7 +41,7 @@ sys_call_table32:
 /*90*/ .word sys_dup2, sys_setfsuid, compat_sys_fcntl, sys32_select, sys_setfsgid
        .word sys_fsync, sys32_setpriority, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall
 /*100*/ .word sys32_getpriority, sys32_rt_sigreturn, sys32_rt_sigaction, sys32_rt_sigprocmask, sys32_rt_sigpending
-       .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, sys32_rt_sigsuspend, sys_setresuid, sys_getresuid
+       .word compat_sys_rt_sigtimedwait, sys32_rt_sigqueueinfo, compat_sys_rt_sigsuspend, sys_setresuid, sys_getresuid
 /*110*/        .word sys_setresgid, sys_getresgid, sys_setregid, sys_nis_syscall, sys_nis_syscall
        .word sys32_getgroups, sys32_gettimeofday, sys32_getrusage, sys_nis_syscall, sys_getcwd
 /*120*/        .word compat_sys_readv, compat_sys_writev, sys32_settimeofday, sys32_fchown16, sys_fchmod
@@ -76,7 +76,10 @@ sys_call_table32:
        .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/        .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
        .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
-/*280*/        .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/        .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
+       .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, compat_sys_newfstatat
+/*285*/        .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+       .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll
 
 #endif /* CONFIG_COMPAT */
 
@@ -142,7 +145,10 @@ sys_call_table:
        .word sys_timer_delete, sys_timer_create, sys_ni_syscall, sys_io_setup, sys_io_destroy
 /*270*/        .word sys_io_submit, sys_io_cancel, sys_io_getevents, sys_mq_open, sys_mq_unlink
        .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid
-/*280*/        .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl
+/*280*/        .word sys_nis_syscall, sys_add_key, sys_request_key, sys_keyctl, sys_openat
+       .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, compat_sys_newfstatat
+/*285*/        .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
+       .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll
 
 #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \
     defined(CONFIG_SOLARIS_EMUL_MODULE)
@@ -239,13 +245,20 @@ sunos_sys_table:
 /*250*/        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
+       .word sunos_nosys
+/*260*/        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
+       .word sunos_nosys
+/*270*/        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
+       .word sunos_nosys
+/*280*/        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
+       .word sunos_nosys
+/*290*/        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
        .word sunos_nosys, sunos_nosys, sunos_nosys
-       .word sunos_nosys
 #endif
index 4b6ae58..eb314ed 100644 (file)
@@ -180,6 +180,8 @@ solaris_sigsuspend:
         nop
        call            sys_sigsuspend
         stx            %o0, [%sp + PTREGS_OFF + PT_V9_I0]
+       b,pt            %xcc, ret_from_solaris
+        nop
 
        .globl          solaris_getpid
 solaris_getpid:
index 65f060b..91b9f58 100644 (file)
@@ -128,9 +128,10 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
  * thread information flag bit numbers
  */
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
-#define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
+/* flag bit 1 is available */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
+#define TIF_RESTORE_SIGMASK    4       /* restore signal mask in do_signal() */
 #define TIF_USEDFPU            8       /* FPU was used by this task
                                         * this quantum (SMP) */
 #define TIF_POLLING_NRFLAG     9       /* true if poll_idle() is polling
@@ -139,9 +140,9 @@ BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
+#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
index 58dba51..2ac64e6 100644 (file)
 #define __NR_add_key           281
 #define __NR_request_key       282
 #define __NR_keyctl            283
+#define __NR_openat            284
+#define __NR_mkdirat           285
+#define __NR_mknodat           286
+#define __NR_fchownat          287
+#define __NR_futimesat         288
+#define __NR_newfstatat                289
+#define __NR_unlinkat          290
+#define __NR_renameat          291
+#define __NR_linkat            292
+#define __NR_symlinkat         293
+#define __NR_readlinkat                294
+#define __NR_fchmodat          295
+#define __NR_faccessat         296
+#define __NR_pselect6          297
+#define __NR_ppoll             298
 
-/* WARNING: You MAY NOT add syscall numbers larger than 283, since
+/* WARNING: You MAY NOT add syscall numbers larger than 298, since
  *          all of the syscall tables in the Sparc kernel are
- *          sized to have 283 entries (starting at zero).  Therefore
- *          find a free slot in the 0-282 range.
+ *          sized to have 298 entries (starting at zero).  Therefore
+ *          find a free slot in the 0-298 range.
  */
 
 #define _syscall0(type,name) \
@@ -458,6 +473,7 @@ return -1; \
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
 #endif
 
 #ifdef __KERNEL_SYSCALLS__
index c94d8b3..ac9d068 100644 (file)
@@ -221,7 +221,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
  *      nop
  */
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
-#define TIF_NOTIFY_RESUME      1       /* resumption notification requested */
+#define TIF_RESTORE_SIGMASK    1       /* restore signal mask in do_signal() */
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_PERFCTR            4       /* performance counters active */
@@ -241,7 +241,6 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define TIF_POLLING_NRFLAG     14
 
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
-#define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_PERFCTR           (1<<TIF_PERFCTR)
@@ -250,11 +249,12 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define _TIF_32BIT             (1<<TIF_32BIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
+#define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
 #define _TIF_ABI_PENDING       (1<<TIF_ABI_PENDING)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_USER_WORK_MASK    ((0xff << TI_FLAG_WSAVED_SHIFT) | \
-                                (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
+                                (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | \
                                  _TIF_NEED_RESCHED | _TIF_PERFCTR))
 
 #endif /* __KERNEL__ */
index 51ec287..84ac2bd 100644 (file)
 #define __NR_add_key           281
 #define __NR_request_key       282
 #define __NR_keyctl            283
+#define __NR_openat            284
+#define __NR_mkdirat           285
+#define __NR_mknodat           286
+#define __NR_fchownat          287
+#define __NR_futimesat         288
+#define __NR_newfstatat                289
+#define __NR_unlinkat          290
+#define __NR_renameat          291
+#define __NR_linkat            292
+#define __NR_symlinkat         293
+#define __NR_readlinkat                294
+#define __NR_fchmodat          295
+#define __NR_faccessat         296
+#define __NR_pselect6          297
+#define __NR_ppoll             298
 
-/* WARNING: You MAY NOT add syscall numbers larger than 283, since
+/* WARNING: You MAY NOT add syscall numbers larger than 298, since
  *          all of the syscall tables in the Sparc kernel are
- *          sized to have 283 entries (starting at zero).  Therefore
- *          find a free slot in the 0-282 range.
+ *          sized to have 298 entries (starting at zero).  Therefore
+ *          find a free slot in the 0-298 range.
  */
 
 #define _syscall0(type,name) \
@@ -501,6 +516,8 @@ asmlinkage long sys_rt_sigaction(int sig,
 #define __ARCH_WANT_SYS_OLDUMOUNT
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 #endif
 
 /*