aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/signal_64.c
diff options
context:
space:
mode:
authorPaul Mackerras <paulus@samba.org>2007-07-10 23:28:26 -0400
committerPaul Mackerras <paulus@samba.org>2007-07-10 23:28:26 -0400
commitbf22f6fe2d72b4d7e9035be8ceb340414cf490e3 (patch)
tree14085d90de0428316479fe6de8a0c6d32e6e65e2 /arch/powerpc/kernel/signal_64.c
parent4eb6bf6bfb580afaf1e1a1d30cba17a078530cf4 (diff)
parent93ab471889c6662b42ce7da257f31f24c08d7d9e (diff)
Merge branch 'for-2.6.23' into merge
Diffstat (limited to 'arch/powerpc/kernel/signal_64.c')
-rw-r--r--arch/powerpc/kernel/signal_64.c182
1 files changed, 5 insertions, 177 deletions
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index b27e26852fd..de895e6d8c6 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -34,9 +34,9 @@
34#include <asm/syscalls.h> 34#include <asm/syscalls.h>
35#include <asm/vdso.h> 35#include <asm/vdso.h>
36 36
37#define DEBUG_SIG 0 37#include "signal.h"
38 38
39#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 39#define DEBUG_SIG 0
40 40
41#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs)) 41#define GP_REGS_SIZE min(sizeof(elf_gregset_t), sizeof(struct pt_regs))
42#define FP_REGS_SIZE sizeof(elf_fpregset_t) 42#define FP_REGS_SIZE sizeof(elf_fpregset_t)
@@ -64,14 +64,6 @@ struct rt_sigframe {
64 char abigap[288]; 64 char abigap[288];
65} __attribute__ ((aligned (16))); 65} __attribute__ ((aligned (16)));
66 66
67long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, unsigned long r5,
68 unsigned long r6, unsigned long r7, unsigned long r8,
69 struct pt_regs *regs)
70{
71 return do_sigaltstack(uss, uoss, regs->gpr[1]);
72}
73
74
75/* 67/*
76 * Set up the sigcontext for the signal frame. 68 * Set up the sigcontext for the signal frame.
77 */ 69 */
@@ -208,25 +200,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
208} 200}
209 201
210/* 202/*
211 * Allocate space for the signal frame
212 */
213static inline void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
214 size_t frame_size)
215{
216 unsigned long newsp;
217
218 /* Default to using normal stack */
219 newsp = regs->gpr[1];
220
221 if ((ka->sa.sa_flags & SA_ONSTACK) && current->sas_ss_size) {
222 if (! on_sig_stack(regs->gpr[1]))
223 newsp = (current->sas_ss_sp + current->sas_ss_size);
224 }
225
226 return (void __user *)((newsp - frame_size) & -16ul);
227}
228
229/*
230 * Setup the trampoline code on the stack 203 * Setup the trampoline code on the stack
231 */ 204 */
232static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) 205static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
@@ -253,19 +226,6 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp)
253} 226}
254 227
255/* 228/*
256 * Restore the user process's signal mask (also used by signal32.c)
257 */
258void restore_sigmask(sigset_t *set)
259{
260 sigdelsetmask(set, ~_BLOCKABLE);
261 spin_lock_irq(&current->sighand->siglock);
262 current->blocked = *set;
263 recalc_sigpending();
264 spin_unlock_irq(&current->sighand->siglock);
265}
266
267
268/*
269 * Handle {get,set,swap}_context operations 229 * Handle {get,set,swap}_context operations
270 */ 230 */
271int sys_swapcontext(struct ucontext __user *old_ctx, 231int sys_swapcontext(struct ucontext __user *old_ctx,
@@ -359,7 +319,7 @@ badframe:
359 return 0; 319 return 0;
360} 320}
361 321
362static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, 322int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
363 sigset_t *set, struct pt_regs *regs) 323 sigset_t *set, struct pt_regs *regs)
364{ 324{
365 /* Handler is *really* a pointer to the function descriptor for 325 /* Handler is *really* a pointer to the function descriptor for
@@ -373,8 +333,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
373 long err = 0; 333 long err = 0;
374 334
375 frame = get_sigframe(ka, regs, sizeof(*frame)); 335 frame = get_sigframe(ka, regs, sizeof(*frame));
376 336 if (unlikely(frame == NULL))
377 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
378 goto badframe; 337 goto badframe;
379 338
380 err |= __put_user(&frame->info, &frame->pinfo); 339 err |= __put_user(&frame->info, &frame->pinfo);
@@ -411,7 +370,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
411 funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler; 370 funct_desc_ptr = (func_descr_t __user *) ka->sa.sa_handler;
412 371
413 /* Allocate a dummy caller frame for the signal handler. */ 372 /* Allocate a dummy caller frame for the signal handler. */
414 newsp = (unsigned long)frame - __SIGNAL_FRAMESIZE; 373 newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE;
415 err |= put_user(regs->gpr[1], (unsigned long __user *)newsp); 374 err |= put_user(regs->gpr[1], (unsigned long __user *)newsp);
416 375
417 /* Set up "regs" so we "return" to the signal handler. */ 376 /* Set up "regs" so we "return" to the signal handler. */
@@ -442,134 +401,3 @@ badframe:
442 force_sigsegv(signr, current); 401 force_sigsegv(signr, current);
443 return 0; 402 return 0;
444} 403}
445
446
447/*
448 * OK, we're invoking a handler
449 */
450static int handle_signal(unsigned long sig, struct k_sigaction *ka,
451 siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
452{
453 int ret;
454
455 /* Set up Signal Frame */
456 ret = setup_rt_frame(sig, ka, info, oldset, regs);
457
458 if (ret) {
459 spin_lock_irq(&current->sighand->siglock);
460 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
461 if (!(ka->sa.sa_flags & SA_NODEFER))
462 sigaddset(&current->blocked,sig);
463 recalc_sigpending();
464 spin_unlock_irq(&current->sighand->siglock);
465 }
466
467 return ret;
468}
469
470static inline void syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
471{
472 switch ((int)regs->result) {
473 case -ERESTART_RESTARTBLOCK:
474 case -ERESTARTNOHAND:
475 /* ERESTARTNOHAND means that the syscall should only be
476 * restarted if there was no handler for the signal, and since
477 * we only get here if there is a handler, we dont restart.
478 */
479 regs->result = -EINTR;
480 regs->gpr[3] = EINTR;
481 regs->ccr |= 0x10000000;
482 break;
483 case -ERESTARTSYS:
484 /* ERESTARTSYS means to restart the syscall if there is no
485 * handler or the handler was registered with SA_RESTART
486 */
487 if (!(ka->sa.sa_flags & SA_RESTART)) {
488 regs->result = -EINTR;
489 regs->gpr[3] = EINTR;
490 regs->ccr |= 0x10000000;
491 break;
492 }
493 /* fallthrough */
494 case -ERESTARTNOINTR:
495 /* ERESTARTNOINTR means that the syscall should be
496 * called again after the signal handler returns.
497 */
498 regs->gpr[3] = regs->orig_gpr3;
499 regs->nip -= 4;
500 regs->result = 0;
501 break;
502 }
503}
504
505/*
506 * Note that 'init' is a special process: it doesn't get signals it doesn't
507 * want to handle. Thus you cannot kill init even with a SIGKILL even by
508 * mistake.
509 */
510int do_signal(sigset_t *oldset, struct pt_regs *regs)
511{
512 siginfo_t info;
513 int signr;
514 struct k_sigaction ka;
515
516 /*
517 * If the current thread is 32 bit - invoke the
518 * 32 bit signal handling code
519 */
520 if (test_thread_flag(TIF_32BIT))
521 return do_signal32(oldset, regs);
522
523 if (test_thread_flag(TIF_RESTORE_SIGMASK))
524 oldset = &current->saved_sigmask;
525 else if (!oldset)
526 oldset = &current->blocked;
527
528 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
529 if (signr > 0) {
530 int ret;
531
532 /* Whee! Actually deliver the signal. */
533 if (TRAP(regs) == 0x0C00)
534 syscall_restart(regs, &ka);
535
536 /*
537 * Reenable the DABR before delivering the signal to
538 * user space. The DABR will have been cleared if it
539 * triggered inside the kernel.
540 */
541 if (current->thread.dabr)
542 set_dabr(current->thread.dabr);
543
544 ret = handle_signal(signr, &ka, &info, oldset, regs);
545
546 /* If a signal was successfully delivered, the saved sigmask is in
547 its frame, and we can clear the TIF_RESTORE_SIGMASK flag */
548 if (ret && test_thread_flag(TIF_RESTORE_SIGMASK))
549 clear_thread_flag(TIF_RESTORE_SIGMASK);
550
551 return ret;
552 }
553
554 if (TRAP(regs) == 0x0C00) { /* System Call! */
555 if ((int)regs->result == -ERESTARTNOHAND ||
556 (int)regs->result == -ERESTARTSYS ||
557 (int)regs->result == -ERESTARTNOINTR) {
558 regs->gpr[3] = regs->orig_gpr3;
559 regs->nip -= 4; /* Back up & retry system call */
560 regs->result = 0;
561 } else if ((int)regs->result == -ERESTART_RESTARTBLOCK) {
562 regs->gpr[0] = __NR_restart_syscall;
563 regs->nip -= 4;
564 regs->result = 0;
565 }
566 }
567 /* No signal to deliver -- put the saved sigmask back */
568 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
569 clear_thread_flag(TIF_RESTORE_SIGMASK);
570 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
571 }
572
573 return 0;
574}
575EXPORT_SYMBOL(do_signal);