aboutsummaryrefslogtreecommitdiffstats
path: root/arch/h8300
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/h8300
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/h8300')
-rw-r--r--arch/h8300/include/asm/unistd.h1
-rw-r--r--arch/h8300/kernel/signal.c122
-rw-r--r--arch/h8300/kernel/syscalls.S6
3 files changed, 40 insertions, 89 deletions
diff --git a/arch/h8300/include/asm/unistd.h b/arch/h8300/include/asm/unistd.h
index 2c3f8e60b1e0..718511303b4e 100644
--- a/arch/h8300/include/asm/unistd.h
+++ b/arch/h8300/include/asm/unistd.h
@@ -356,6 +356,7 @@
356#define __ARCH_WANT_SYS_SIGPENDING 356#define __ARCH_WANT_SYS_SIGPENDING
357#define __ARCH_WANT_SYS_SIGPROCMASK 357#define __ARCH_WANT_SYS_SIGPROCMASK
358#define __ARCH_WANT_SYS_RT_SIGACTION 358#define __ARCH_WANT_SYS_RT_SIGACTION
359#define __ARCH_WANT_SYS_RT_SIGSUSPEND
359 360
360/* 361/*
361 * "Conditional" syscalls 362 * "Conditional" syscalls
diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c
index af842c369d24..d4b0555d2904 100644
--- a/arch/h8300/kernel/signal.c
+++ b/arch/h8300/kernel/signal.c
@@ -49,60 +49,15 @@
49 49
50#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 50#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
51 51
52asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
53
54/* 52/*
55 * Atomically swap in the new signal mask, and wait for a signal. 53 * Atomically swap in the new signal mask, and wait for a signal.
56 */ 54 */
57asmlinkage int do_sigsuspend(struct pt_regs *regs)
58{
59 old_sigset_t mask = regs->er3;
60 sigset_t saveset;
61
62 mask &= _BLOCKABLE;
63 spin_lock_irq(&current->sighand->siglock);
64 saveset = current->blocked;
65 siginitset(&current->blocked, mask);
66 recalc_sigpending();
67 spin_unlock_irq(&current->sighand->siglock);
68
69 regs->er0 = -EINTR;
70 while (1) {
71 current->state = TASK_INTERRUPTIBLE;
72 schedule();
73 if (do_signal(regs, &saveset))
74 return -EINTR;
75 }
76}
77
78asmlinkage int 55asmlinkage int
79do_rt_sigsuspend(struct pt_regs *regs) 56sys_sigsuspend(int unused1, int unused2, old_sigset_t mask)
80{ 57{
81 sigset_t *unewset = (sigset_t *)regs->er1; 58 sigset_t blocked;
82 size_t sigsetsize = (size_t)regs->er2; 59 siginitset(&blocked, mask);
83 sigset_t saveset, newset; 60 return sigsuspend(&blocked);
84
85 /* XXX: Don't preclude handling different sized sigset_t's. */
86 if (sigsetsize != sizeof(sigset_t))
87 return -EINVAL;
88
89 if (copy_from_user(&newset, unewset, sizeof(newset)))
90 return -EFAULT;
91 sigdelsetmask(&newset, ~_BLOCKABLE);
92
93 spin_lock_irq(&current->sighand->siglock);
94 saveset = current->blocked;
95 current->blocked = newset;
96 recalc_sigpending();
97 spin_unlock_irq(&current->sighand->siglock);
98
99 regs->er0 = -EINTR;
100 while (1) {
101 current->state = TASK_INTERRUPTIBLE;
102 schedule();
103 if (do_signal(regs, &saveset))
104 return -EINTR;
105 }
106} 61}
107 62
108asmlinkage int 63asmlinkage int
@@ -116,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
116 old_sigset_t mask; 71 old_sigset_t mask;
117 if (!access_ok(VERIFY_READ, act, sizeof(*act)) || 72 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
118 __get_user(new_ka.sa.sa_handler, &act->sa_handler) || 73 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
119 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) 74 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
75 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
76 __get_user(mask, &act->sa_mask))
120 return -EFAULT; 77 return -EFAULT;
121 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
122 __get_user(mask, &act->sa_mask);
123 siginitset(&new_ka.sa.sa_mask, mask); 78 siginitset(&new_ka.sa.sa_mask, mask);
124 } 79 }
125 80
@@ -128,10 +83,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
128 if (!ret && oact) { 83 if (!ret && oact) {
129 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || 84 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
130 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || 85 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
131 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) 86 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
87 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
88 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
132 return -EFAULT; 89 return -EFAULT;
133 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
134 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
135 } 90 }
136 91
137 return ret; 92 return ret;
@@ -232,10 +187,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
232 goto badframe; 187 goto badframe;
233 188
234 sigdelsetmask(&set, ~_BLOCKABLE); 189 sigdelsetmask(&set, ~_BLOCKABLE);
235 spin_lock_irq(&current->sighand->siglock); 190 set_current_blocked(&set);
236 current->blocked = set;
237 recalc_sigpending();
238 spin_unlock_irq(&current->sighand->siglock);
239 191
240 if (restore_sigcontext(regs, &frame->sc, &er0)) 192 if (restore_sigcontext(regs, &frame->sc, &er0))
241 goto badframe; 193 goto badframe;
@@ -260,10 +212,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
260 goto badframe; 212 goto badframe;
261 213
262 sigdelsetmask(&set, ~_BLOCKABLE); 214 sigdelsetmask(&set, ~_BLOCKABLE);
263 spin_unlock_irq(&current->sighand->siglock); 215 set_current_blocked(&set);
264 current->blocked = set;
265 recalc_sigpending();
266 spin_lock_irq(&current->sighand->siglock);
267 216
268 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) 217 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
269 goto badframe; 218 goto badframe;
@@ -314,7 +263,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
314 return (void *)((usp - frame_size) & -8UL); 263 return (void *)((usp - frame_size) & -8UL);
315} 264}
316 265
317static void setup_frame (int sig, struct k_sigaction *ka, 266static int setup_frame (int sig, struct k_sigaction *ka,
318 sigset_t *set, struct pt_regs *regs) 267 sigset_t *set, struct pt_regs *regs)
319{ 268{
320 struct sigframe *frame; 269 struct sigframe *frame;
@@ -375,13 +324,14 @@ static void setup_frame (int sig, struct k_sigaction *ka,
375 regs->er1 = (unsigned long)&(frame->sc); 324 regs->er1 = (unsigned long)&(frame->sc);
376 regs->er5 = current->mm->start_data; /* GOT base */ 325 regs->er5 = current->mm->start_data; /* GOT base */
377 326
378 return; 327 return 0;
379 328
380give_sigsegv: 329give_sigsegv:
381 force_sigsegv(sig, current); 330 force_sigsegv(sig, current);
331 return -EFAULT;
382} 332}
383 333
384static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, 334static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
385 sigset_t *set, struct pt_regs *regs) 335 sigset_t *set, struct pt_regs *regs)
386{ 336{
387 struct rt_sigframe *frame; 337 struct rt_sigframe *frame;
@@ -450,10 +400,11 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
450 regs->er2 = (unsigned long)&frame->uc; 400 regs->er2 = (unsigned long)&frame->uc;
451 regs->er5 = current->mm->start_data; /* GOT base */ 401 regs->er5 = current->mm->start_data; /* GOT base */
452 402
453 return; 403 return 0;
454 404
455give_sigsegv: 405give_sigsegv:
456 force_sigsegv(sig, current); 406 force_sigsegv(sig, current);
407 return -EFAULT;
457} 408}
458 409
459/* 410/*
@@ -463,6 +414,7 @@ static void
463handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, 414handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
464 sigset_t *oldset, struct pt_regs * regs) 415 sigset_t *oldset, struct pt_regs * regs)
465{ 416{
417 int ret;
466 /* are we from a system call? */ 418 /* are we from a system call? */
467 if (regs->orig_er0 >= 0) { 419 if (regs->orig_er0 >= 0) {
468 switch (regs->er0) { 420 switch (regs->er0) {
@@ -485,16 +437,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
485 437
486 /* set up the stack frame */ 438 /* set up the stack frame */
487 if (ka->sa.sa_flags & SA_SIGINFO) 439 if (ka->sa.sa_flags & SA_SIGINFO)
488 setup_rt_frame(sig, ka, info, oldset, regs); 440 ret = setup_rt_frame(sig, ka, info, oldset, regs);
489 else 441 else
490 setup_frame(sig, ka, oldset, regs); 442 ret = setup_frame(sig, ka, oldset, regs);
491 443
492 spin_lock_irq(&current->sighand->siglock); 444 if (!ret) {
493 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 445 block_sigmask(ka, sig);
494 if (!(ka->sa.sa_flags & SA_NODEFER)) 446 clear_thread_flag(TIF_RESTORE_SIGMASK);
495 sigaddset(&current->blocked,sig); 447 }
496 recalc_sigpending();
497 spin_unlock_irq(&current->sighand->siglock);
498} 448}
499 449
500/* 450/*
@@ -502,11 +452,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
502 * want to handle. Thus you cannot kill init even with a SIGKILL even by 452 * want to handle. Thus you cannot kill init even with a SIGKILL even by
503 * mistake. 453 * mistake.
504 */ 454 */
505asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset) 455statis void do_signal(struct pt_regs *regs)
506{ 456{
507 siginfo_t info; 457 siginfo_t info;
508 int signr; 458 int signr;
509 struct k_sigaction ka; 459 struct k_sigaction ka;
460 sigset_t *oldset;
510 461
511 /* 462 /*
512 * We want the common case to go fast, which 463 * We want the common case to go fast, which
@@ -515,21 +466,23 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
515 * if so. 466 * if so.
516 */ 467 */
517 if ((regs->ccr & 0x10)) 468 if ((regs->ccr & 0x10))
518 return 1; 469 return;
519 470
520 if (try_to_freeze()) 471 if (try_to_freeze())
521 goto no_signal; 472 goto no_signal;
522 473
523 current->thread.esp0 = (unsigned long) regs; 474 current->thread.esp0 = (unsigned long) regs;
524 475
525 if (!oldset) 476 if (test_thread_flag(TIF_RESTORE_SIGMASK))
477 oldset = &current->saved_sigmask;
478 else
526 oldset = &current->blocked; 479 oldset = &current->blocked;
527 480
528 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 481 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
529 if (signr > 0) { 482 if (signr > 0) {
530 /* Whee! Actually deliver the signal. */ 483 /* Whee! Actually deliver the signal. */
531 handle_signal(signr, &info, &ka, oldset, regs); 484 handle_signal(signr, &info, &ka, oldset, regs);
532 return 1; 485 return;
533 } 486 }
534 no_signal: 487 no_signal:
535 /* Did we come from a system call? */ 488 /* Did we come from a system call? */
@@ -546,13 +499,16 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
546 regs->pc -= 2; 499 regs->pc -= 2;
547 } 500 }
548 } 501 }
549 return 0; 502
503 /* If there's no signal to deliver, we just restore the saved mask. */
504 if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
505 set_current_blocked(&current->saved_sigmask);
550} 506}
551 507
552asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) 508asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
553{ 509{
554 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) 510 if (thread_info_flags & _TIF_SIGPENDING)
555 do_signal(regs, NULL); 511 do_signal(regs);
556 512
557 if (thread_info_flags & _TIF_NOTIFY_RESUME) { 513 if (thread_info_flags & _TIF_NOTIFY_RESUME) {
558 clear_thread_flag(TIF_NOTIFY_RESUME); 514 clear_thread_flag(TIF_NOTIFY_RESUME);
diff --git a/arch/h8300/kernel/syscalls.S b/arch/h8300/kernel/syscalls.S
index 4be2ea2fbe26..9d77e715a2ed 100644
--- a/arch/h8300/kernel/syscalls.S
+++ b/arch/h8300/kernel/syscalls.S
@@ -343,12 +343,6 @@ SYMBOL_NAME_LABEL(sys_call_table)
343SYMBOL_NAME_LABEL(sys_clone) 343SYMBOL_NAME_LABEL(sys_clone)
344 call_sp h8300_clone 344 call_sp h8300_clone
345 345
346SYMBOL_NAME_LABEL(sys_sigsuspend)
347 call_sp do_sigsuspend
348
349SYMBOL_NAME_LABEL(sys_rt_sigsuspend)
350 call_sp do_rt_sigsuspend
351
352SYMBOL_NAME_LABEL(sys_sigreturn) 346SYMBOL_NAME_LABEL(sys_sigreturn)
353 call_sp do_sigreturn 347 call_sp do_sigreturn
354 348