From 188f677f84e935f83e3d539d6e8808006f6ac62f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 22 Apr 2012 03:35:28 -0400 Subject: xtensa: ->restart_block.fn needs to be reset on rt_sigreturn Signed-off-by: Al Viro --- arch/xtensa/kernel/signal.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/xtensa') diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index d78869a00b1..44e9329a648 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -248,6 +248,9 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3, sigset_t set; int ret; + /* Always make any pending restarted system calls return -EINTR */ + current_thread_info()->restart_block.fn = do_no_restart_syscall; + if (regs->depc > 64) panic("rt_sigreturn in double exception!\n"); -- cgit v1.2.3 From 9ccc9c75c9117d18a9b1f71a21f0066b1eb9db6f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 22 Apr 2012 00:59:07 -0400 Subject: xtensa: switch to generic rt_sigsuspend(2) Signed-off-by: Al Viro --- arch/xtensa/include/asm/syscall.h | 2 -- arch/xtensa/include/asm/unistd.h | 2 +- arch/xtensa/kernel/entry.S | 1 - arch/xtensa/kernel/signal.c | 54 +++++++++++---------------------------- 4 files changed, 16 insertions(+), 43 deletions(-) (limited to 'arch/xtensa') diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index efcf33b92e4..fc289f7e8eb 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -15,8 +15,6 @@ asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); asmlinkage long xtensa_ptrace(long, long, long, long); asmlinkage long xtensa_sigreturn(struct pt_regs*); asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); -asmlinkage long xtensa_sigsuspend(struct pt_regs*); -asmlinkage long xtensa_rt_sigsuspend(struct pt_regs*); asmlinkage long xtensa_sigaction(int, const struct old_sigaction*, struct old_sigaction*); asmlinkage long xtensa_sigaltstack(struct pt_regs *regs); diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index 798ee6d285a..bc7e005faa6 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -507,7 +507,7 @@ __SYSCALL(229, sys_rt_sigtimedwait, 4) #define __NR_rt_sigqueueinfo 230 __SYSCALL(230, sys_rt_sigqueueinfo, 3) #define __NR_rt_sigsuspend 231 -__SYSCALL(231, xtensa_rt_sigsuspend, 2) +__SYSCALL(231, sys_rt_sigsuspend, 2) /* Message */ diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 6223f3346b5..b1bb6d79d8b 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -418,7 +418,6 @@ common_exception_return: movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*) mov a6, a1 - movi a7, 0 callx4 a4 j 1b diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 44e9329a648..bb00cc470ca 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -31,8 +31,6 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); - extern struct task_struct *coproc_owners[]; struct rt_sigframe @@ -429,37 +427,6 @@ give_sigsegv: return -EFAULT; } -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ - -asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, - size_t sigsetsize, - long a2, long a3, long a4, long a5, - struct pt_regs *regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - - sigdelsetmask(&newset, ~_BLOCKABLE); - saveset = current->blocked; - set_current_blocked(&newset); - - regs->areg[2] = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (do_signal(regs, &saveset)) - return -EINTR; - } -} - asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, long a2, long a3, long a4, long a5, @@ -479,19 +446,22 @@ asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) +void do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; + sigset_t oldset; if (!user_mode(regs)) - return 0; + return; if (try_to_freeze()) goto no_signal; - if (!oldset) + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else oldset = ¤t->blocked; task_pt_regs(current)->icountlevel = 0; @@ -535,13 +505,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) /* Set up the stack frame */ ret = setup_frame(signr, &ka, &info, oldset, regs); if (ret) - return ret; + return; + clear_thread_flag(TIF_RESTORE_SIGMASK); block_sigmask(&ka, signr); if (current->ptrace & PT_SINGLESTEP) task_pt_regs(current)->icountlevel = 1; - return 1; + return; } no_signal: @@ -561,8 +532,13 @@ no_signal: break; } } + + /* If there's no signal to deliver, we just restore the saved mask. */ + if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) + set_current_blocked(¤t->saved_sigmask); + if (current->ptrace & PT_SINGLESTEP) task_pt_regs(current)->icountlevel = 1; - return 0; + return; } -- cgit v1.2.3 From b1175ed2234235276f4a2256f72a277b85320cf9 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 22 Apr 2012 16:19:57 -0400 Subject: xtensa: xtensa_sigaction doesn't exist ... and struct old_sigaction never used Signed-off-by: Al Viro --- arch/xtensa/include/asm/signal.h | 7 ------- arch/xtensa/include/asm/syscall.h | 2 -- 2 files changed, 9 deletions(-) (limited to 'arch/xtensa') diff --git a/arch/xtensa/include/asm/signal.h b/arch/xtensa/include/asm/signal.h index 633ba73bc4d..7f201b9d419 100644 --- a/arch/xtensa/include/asm/signal.h +++ b/arch/xtensa/include/asm/signal.h @@ -120,13 +120,6 @@ typedef void (*__sighandler_t)(int); #define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ #ifdef __KERNEL__ -struct old_sigaction { - __sighandler_t sa_handler; - old_sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - struct sigaction { __sighandler_t sa_handler; unsigned long sa_flags; diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index fc289f7e8eb..0b9f2e13c78 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -15,8 +15,6 @@ asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*); asmlinkage long xtensa_ptrace(long, long, long, long); asmlinkage long xtensa_sigreturn(struct pt_regs*); asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); -asmlinkage long xtensa_sigaction(int, const struct old_sigaction*, - struct old_sigaction*); asmlinkage long xtensa_sigaltstack(struct pt_regs *regs); asmlinkage long sys_rt_sigaction(int, const struct sigaction __user *, -- cgit v1.2.3 From a53bb24e7666870bbc195e295a936aa0a58ce313 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 24 Apr 2012 02:30:16 -0400 Subject: xtensa: add handling of TIF_NOTIFY_RESUME Signed-off-by: Al Viro --- arch/xtensa/include/asm/thread_info.h | 1 + arch/xtensa/kernel/entry.S | 5 +++-- arch/xtensa/kernel/signal.c | 20 ++++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) (limited to 'arch/xtensa') diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h index 6abbedd09d8..81abfd5d01a 100644 --- a/arch/xtensa/include/asm/thread_info.h +++ b/arch/xtensa/include/asm/thread_info.h @@ -131,6 +131,7 @@ static inline struct thread_info *current_thread_info(void) #define TIF_IRET 4 /* return with iret */ #define TIF_MEMDIE 5 /* is terminating due to OOM killer */ #define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */ +#define TIF_NOTIFY_RESUME 7 /* callback before returning to user */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define _TIF_SYSCALL_TRACE (1< #include #include +#include #include #include @@ -446,16 +447,13 @@ asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. */ -void do_signal(struct pt_regs *regs) +static void do_signal(struct pt_regs *regs) { siginfo_t info; int signr; struct k_sigaction ka; sigset_t oldset; - if (!user_mode(regs)) - return; - if (try_to_freeze()) goto no_signal; @@ -542,3 +540,17 @@ no_signal: return; } +void do_notify_resume(struct pt_regs *regs) +{ + if (!user_mode(regs)) + return; + + if (test_thread_flag(TIF_SIGPENDING)) + do_signal(regs); + + if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) { + tracehook_notify_resume(regs); + if (current->replacement_session_keyring) + key_replace_session_keyring(); + } +} -- cgit v1.2.3