aboutsummaryrefslogtreecommitdiffstats
path: root/arch/xtensa
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 21:11:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 21:11:45 -0400
commitf9369910a6225b8d4892c3f20ae740a711cd5ace (patch)
tree8650ff79d7607bceb35509c028400ecf1c317de0 /arch/xtensa
parent05f144a0d5c2207a0349348127f996e104ad7404 (diff)
parent415d04d08fec74b226c92c1fb54ad117c9c6bac4 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull first series of signal handling cleanups from Al Viro: "This is just the first part of the queue (about a half of it); assorted fixes all over the place in signal handling. This one ends with all sigsuspend() implementations switched to generic one (->saved_sigmask-based). With this, a bunch of assorted old buglets are fixed and most of the missing bits of NOTIFY_RESUME hookup are in place. Two more fixes sit in arm and um trees respectively, and there's a couple of broken ones that need obvious fixes - parisc and avr32 check TIF_NOTIFY_RESUME only on one of two codepaths; fixes for that will happen in the next series" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (55 commits) unicore32: if there's no handler we need to restore sigmask, syscall or no syscall xtensa: add handling of TIF_NOTIFY_RESUME microblaze: drop 'oldset' argument of do_notify_resume() microblaze: handle TIF_NOTIFY_RESUME score: add handling of NOTIFY_RESUME to do_notify_resume() m68k: add TIF_NOTIFY_RESUME and handle it. sparc: kill ancient comment in sparc_sigaction() h8300: missing checks of __get_user()/__put_user() return values frv: missing checks of __get_user()/__put_user() return values cris: missing checks of __get_user()/__put_user() return values powerpc: missing checks of __get_user()/__put_user() return values sh: missing checks of __get_user()/__put_user() return values sparc: missing checks of __get_user()/__put_user() return values avr32: struct old_sigaction is never used m32r: struct old_sigaction is never used xtensa: xtensa_sigaction doesn't exist alpha: tidy signal delivery up score: don't open-code force_sigsegv() cris: don't open-code force_sigsegv() blackfin: don't open-code force_sigsegv() ...
Diffstat (limited to 'arch/xtensa')
-rw-r--r--arch/xtensa/include/asm/signal.h7
-rw-r--r--arch/xtensa/include/asm/syscall.h4
-rw-r--r--arch/xtensa/include/asm/thread_info.h1
-rw-r--r--arch/xtensa/include/asm/unistd.h2
-rw-r--r--arch/xtensa/kernel/entry.S6
-rw-r--r--arch/xtensa/kernel/signal.c73
6 files changed, 37 insertions, 56 deletions
diff --git a/arch/xtensa/include/asm/signal.h b/arch/xtensa/include/asm/signal.h
index 633ba73bc4d2..7f201b9d4195 100644
--- a/arch/xtensa/include/asm/signal.h
+++ b/arch/xtensa/include/asm/signal.h
@@ -120,13 +120,6 @@ typedef void (*__sighandler_t)(int);
120#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */ 120#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
121 121
122#ifdef __KERNEL__ 122#ifdef __KERNEL__
123struct old_sigaction {
124 __sighandler_t sa_handler;
125 old_sigset_t sa_mask;
126 unsigned long sa_flags;
127 void (*sa_restorer)(void);
128};
129
130struct sigaction { 123struct sigaction {
131 __sighandler_t sa_handler; 124 __sighandler_t sa_handler;
132 unsigned long sa_flags; 125 unsigned long sa_flags;
diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h
index efcf33b92e4c..0b9f2e13c781 100644
--- a/arch/xtensa/include/asm/syscall.h
+++ b/arch/xtensa/include/asm/syscall.h
@@ -15,10 +15,6 @@ asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
15asmlinkage long xtensa_ptrace(long, long, long, long); 15asmlinkage long xtensa_ptrace(long, long, long, long);
16asmlinkage long xtensa_sigreturn(struct pt_regs*); 16asmlinkage long xtensa_sigreturn(struct pt_regs*);
17asmlinkage long xtensa_rt_sigreturn(struct pt_regs*); 17asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
18asmlinkage long xtensa_sigsuspend(struct pt_regs*);
19asmlinkage long xtensa_rt_sigsuspend(struct pt_regs*);
20asmlinkage long xtensa_sigaction(int, const struct old_sigaction*,
21 struct old_sigaction*);
22asmlinkage long xtensa_sigaltstack(struct pt_regs *regs); 18asmlinkage long xtensa_sigaltstack(struct pt_regs *regs);
23asmlinkage long sys_rt_sigaction(int, 19asmlinkage long sys_rt_sigaction(int,
24 const struct sigaction __user *, 20 const struct sigaction __user *,
diff --git a/arch/xtensa/include/asm/thread_info.h b/arch/xtensa/include/asm/thread_info.h
index 6abbedd09d85..81abfd5d01ac 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)
131#define TIF_IRET 4 /* return with iret */ 131#define TIF_IRET 4 /* return with iret */
132#define TIF_MEMDIE 5 /* is terminating due to OOM killer */ 132#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
133#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */ 133#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
134#define TIF_NOTIFY_RESUME 7 /* callback before returning to user */
134#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ 135#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
135 136
136#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 137#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h
index 798ee6d285a1..bc7e005faa60 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)
507#define __NR_rt_sigqueueinfo 230 507#define __NR_rt_sigqueueinfo 230
508__SYSCALL(230, sys_rt_sigqueueinfo, 3) 508__SYSCALL(230, sys_rt_sigqueueinfo, 3)
509#define __NR_rt_sigsuspend 231 509#define __NR_rt_sigsuspend 231
510__SYSCALL(231, xtensa_rt_sigsuspend, 2) 510__SYSCALL(231, sys_rt_sigsuspend, 2)
511 511
512/* Message */ 512/* Message */
513 513
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S
index 6223f3346b5c..7e6236073397 100644
--- a/arch/xtensa/kernel/entry.S
+++ b/arch/xtensa/kernel/entry.S
@@ -409,16 +409,16 @@ common_exception_return:
409 l32i a4, a2, TI_FLAGS 409 l32i a4, a2, TI_FLAGS
410 410
411 _bbsi.l a4, TIF_NEED_RESCHED, 3f 411 _bbsi.l a4, TIF_NEED_RESCHED, 3f
412 _bbsi.l a4, TIF_NOTIFY_RESUME, 2f
412 _bbci.l a4, TIF_SIGPENDING, 4f 413 _bbci.l a4, TIF_SIGPENDING, 4f
413 414
414 l32i a4, a1, PT_DEPC 4152: l32i a4, a1, PT_DEPC
415 bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f 416 bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
416 417
417 /* Call do_signal() */ 418 /* Call do_signal() */
418 419
419 movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*) 420 movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*)
420 mov a6, a1 421 mov a6, a1
421 movi a7, 0
422 callx4 a4 422 callx4 a4
423 j 1b 423 j 1b
424 424
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c
index d78869a00b11..c5e4ec0598d2 100644
--- a/arch/xtensa/kernel/signal.c
+++ b/arch/xtensa/kernel/signal.c
@@ -20,6 +20,7 @@
20#include <linux/ptrace.h> 20#include <linux/ptrace.h>
21#include <linux/personality.h> 21#include <linux/personality.h>
22#include <linux/freezer.h> 22#include <linux/freezer.h>
23#include <linux/tracehook.h>
23 24
24#include <asm/ucontext.h> 25#include <asm/ucontext.h>
25#include <asm/uaccess.h> 26#include <asm/uaccess.h>
@@ -31,8 +32,6 @@
31 32
32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 33#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
33 34
34asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
35
36extern struct task_struct *coproc_owners[]; 35extern struct task_struct *coproc_owners[];
37 36
38struct rt_sigframe 37struct rt_sigframe
@@ -248,6 +247,9 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
248 sigset_t set; 247 sigset_t set;
249 int ret; 248 int ret;
250 249
250 /* Always make any pending restarted system calls return -EINTR */
251 current_thread_info()->restart_block.fn = do_no_restart_syscall;
252
251 if (regs->depc > 64) 253 if (regs->depc > 64)
252 panic("rt_sigreturn in double exception!\n"); 254 panic("rt_sigreturn in double exception!\n");
253 255
@@ -426,37 +428,6 @@ give_sigsegv:
426 return -EFAULT; 428 return -EFAULT;
427} 429}
428 430
429/*
430 * Atomically swap in the new signal mask, and wait for a signal.
431 */
432
433asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset,
434 size_t sigsetsize,
435 long a2, long a3, long a4, long a5,
436 struct pt_regs *regs)
437{
438 sigset_t saveset, newset;
439
440 /* XXX: Don't preclude handling different sized sigset_t's. */
441 if (sigsetsize != sizeof(sigset_t))
442 return -EINVAL;
443
444 if (copy_from_user(&newset, unewset, sizeof(newset)))
445 return -EFAULT;
446
447 sigdelsetmask(&newset, ~_BLOCKABLE);
448 saveset = current->blocked;
449 set_current_blocked(&newset);
450
451 regs->areg[2] = -EINTR;
452 while (1) {
453 current->state = TASK_INTERRUPTIBLE;
454 schedule();
455 if (do_signal(regs, &saveset))
456 return -EINTR;
457 }
458}
459
460asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, 431asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
461 stack_t __user *uoss, 432 stack_t __user *uoss,
462 long a2, long a3, long a4, long a5, 433 long a2, long a3, long a4, long a5,
@@ -476,19 +447,19 @@ asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
476 * the kernel can handle, and then we build all the user-level signal handling 447 * the kernel can handle, and then we build all the user-level signal handling
477 * stack-frames in one go after that. 448 * stack-frames in one go after that.
478 */ 449 */
479int do_signal(struct pt_regs *regs, sigset_t *oldset) 450static void do_signal(struct pt_regs *regs)
480{ 451{
481 siginfo_t info; 452 siginfo_t info;
482 int signr; 453 int signr;
483 struct k_sigaction ka; 454 struct k_sigaction ka;
484 455 sigset_t oldset;
485 if (!user_mode(regs))
486 return 0;
487 456
488 if (try_to_freeze()) 457 if (try_to_freeze())
489 goto no_signal; 458 goto no_signal;
490 459
491 if (!oldset) 460 if (test_thread_flag(TIF_RESTORE_SIGMASK))
461 oldset = &current->saved_sigmask;
462 else
492 oldset = &current->blocked; 463 oldset = &current->blocked;
493 464
494 task_pt_regs(current)->icountlevel = 0; 465 task_pt_regs(current)->icountlevel = 0;
@@ -532,13 +503,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
532 /* Set up the stack frame */ 503 /* Set up the stack frame */
533 ret = setup_frame(signr, &ka, &info, oldset, regs); 504 ret = setup_frame(signr, &ka, &info, oldset, regs);
534 if (ret) 505 if (ret)
535 return ret; 506 return;
536 507
508 clear_thread_flag(TIF_RESTORE_SIGMASK);
537 block_sigmask(&ka, signr); 509 block_sigmask(&ka, signr);
538 if (current->ptrace & PT_SINGLESTEP) 510 if (current->ptrace & PT_SINGLESTEP)
539 task_pt_regs(current)->icountlevel = 1; 511 task_pt_regs(current)->icountlevel = 1;
540 512
541 return 1; 513 return;
542 } 514 }
543 515
544no_signal: 516no_signal:
@@ -558,8 +530,27 @@ no_signal:
558 break; 530 break;
559 } 531 }
560 } 532 }
533
534 /* If there's no signal to deliver, we just restore the saved mask. */
535 if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
536 set_current_blocked(&current->saved_sigmask);
537
561 if (current->ptrace & PT_SINGLESTEP) 538 if (current->ptrace & PT_SINGLESTEP)
562 task_pt_regs(current)->icountlevel = 1; 539 task_pt_regs(current)->icountlevel = 1;
563 return 0; 540 return;
564} 541}
565 542
543void do_notify_resume(struct pt_regs *regs)
544{
545 if (!user_mode(regs))
546 return;
547
548 if (test_thread_flag(TIF_SIGPENDING))
549 do_signal(regs);
550
551 if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
552 tracehook_notify_resume(regs);
553 if (current->replacement_session_keyring)
554 key_replace_session_keyring();
555 }
556}