diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2007-06-04 03:22:48 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-06-14 08:29:58 -0400 |
commit | a3f61dc0a5335334958ec3b97d0b1946b4ae5375 (patch) | |
tree | e7b151d724dca73220d8346c2a0c2a3525c5c91c /arch/powerpc/kernel/signal_32.c | |
parent | 5f9f375a62d3fd3d7f0d5adc23039ade523e62ba (diff) |
[POWERPC] Merge creation of signal frame
The code for creating signal frames was still duplicated and split
in strange ways between 32 and 64 bits, including the SA_ONSTACK
handling being in do_signal on 32 bits but inside handle_rt_signal
on 64 bits etc...
This moves the 64 bits get_sigframe() to the generic signal.c,
cleans it a bit, moves the access_ok() call done by all callers to
it as well, and adapts/cleanups the 3 different signal handling cases
to use that common function.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/signal_32.c')
-rw-r--r-- | arch/powerpc/kernel/signal_32.c | 52 |
1 files changed, 24 insertions, 28 deletions
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 32481e71d71e..590057e9e987 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -282,14 +282,17 @@ long sys_sigaction(int sig, struct old_sigaction __user *act, | |||
282 | /* | 282 | /* |
283 | * When we have signals to deliver, we set up on the | 283 | * When we have signals to deliver, we set up on the |
284 | * user stack, going down from the original stack pointer: | 284 | * user stack, going down from the original stack pointer: |
285 | * a sigregs struct | 285 | * an ABI gap of 56 words |
286 | * an mcontext struct | ||
286 | * a sigcontext struct | 287 | * a sigcontext struct |
287 | * a gap of __SIGNAL_FRAMESIZE bytes | 288 | * a gap of __SIGNAL_FRAMESIZE bytes |
288 | * | 289 | * |
289 | * Each of these things must be a multiple of 16 bytes in size. | 290 | * Each of these things must be a multiple of 16 bytes in size. The following |
291 | * structure represent all of this except the __SIGNAL_FRAMESIZE gap | ||
290 | * | 292 | * |
291 | */ | 293 | */ |
292 | struct sigregs { | 294 | struct sigframe { |
295 | struct sigcontext sctx; /* the sigcontext */ | ||
293 | struct mcontext mctx; /* all the register values */ | 296 | struct mcontext mctx; /* all the register values */ |
294 | /* | 297 | /* |
295 | * Programs using the rs6000/xcoff abi can save up to 19 gp | 298 | * Programs using the rs6000/xcoff abi can save up to 19 gp |
@@ -698,21 +701,16 @@ int compat_sys_sigaltstack(u32 __new, u32 __old, int r5, | |||
698 | */ | 701 | */ |
699 | int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | 702 | int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, |
700 | siginfo_t *info, sigset_t *oldset, | 703 | siginfo_t *info, sigset_t *oldset, |
701 | struct pt_regs *regs, unsigned long newsp) | 704 | struct pt_regs *regs) |
702 | { | 705 | { |
703 | struct rt_sigframe __user *rt_sf; | 706 | struct rt_sigframe __user *rt_sf; |
704 | struct mcontext __user *frame; | 707 | struct mcontext __user *frame; |
705 | unsigned long origsp = newsp; | 708 | unsigned long newsp = 0; |
706 | 709 | ||
707 | /* Set up Signal Frame */ | 710 | /* Set up Signal Frame */ |
708 | /* Put a Real Time Context onto stack */ | 711 | /* Put a Real Time Context onto stack */ |
709 | newsp -= sizeof(*rt_sf); | 712 | rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf)); |
710 | rt_sf = (struct rt_sigframe __user *)newsp; | 713 | if (unlikely(rt_sf == NULL)) |
711 | |||
712 | /* create a stack frame for the caller of the handler */ | ||
713 | newsp -= __SIGNAL_FRAMESIZE + 16; | ||
714 | |||
715 | if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp)) | ||
716 | goto badframe; | 714 | goto badframe; |
717 | 715 | ||
718 | /* Put the siginfo & fill in most of the ucontext */ | 716 | /* Put the siginfo & fill in most of the ucontext */ |
@@ -742,8 +740,12 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
742 | 740 | ||
743 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 741 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ |
744 | 742 | ||
743 | /* create a stack frame for the caller of the handler */ | ||
744 | newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); | ||
745 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 745 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
746 | goto badframe; | 746 | goto badframe; |
747 | |||
748 | /* Fill registers for signal handler */ | ||
747 | regs->gpr[1] = newsp; | 749 | regs->gpr[1] = newsp; |
748 | regs->gpr[3] = sig; | 750 | regs->gpr[3] = sig; |
749 | regs->gpr[4] = (unsigned long) &rt_sf->info; | 751 | regs->gpr[4] = (unsigned long) &rt_sf->info; |
@@ -988,26 +990,17 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
988 | * OK, we're invoking a handler | 990 | * OK, we're invoking a handler |
989 | */ | 991 | */ |
990 | int handle_signal32(unsigned long sig, struct k_sigaction *ka, | 992 | int handle_signal32(unsigned long sig, struct k_sigaction *ka, |
991 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, | 993 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) |
992 | unsigned long newsp) | ||
993 | { | 994 | { |
994 | struct sigcontext __user *sc; | 995 | struct sigcontext __user *sc; |
995 | struct sigregs __user *frame; | 996 | struct sigframe __user *frame; |
996 | unsigned long origsp = newsp; | 997 | unsigned long newsp = 0; |
997 | 998 | ||
998 | /* Set up Signal Frame */ | 999 | /* Set up Signal Frame */ |
999 | newsp -= sizeof(struct sigregs); | 1000 | frame = get_sigframe(ka, regs, sizeof(*frame)); |
1000 | frame = (struct sigregs __user *) newsp; | 1001 | if (unlikely(frame == NULL)) |
1001 | |||
1002 | /* Put a sigcontext on the stack */ | ||
1003 | newsp -= sizeof(*sc); | ||
1004 | sc = (struct sigcontext __user *) newsp; | ||
1005 | |||
1006 | /* create a stack frame for the caller of the handler */ | ||
1007 | newsp -= __SIGNAL_FRAMESIZE; | ||
1008 | |||
1009 | if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp)) | ||
1010 | goto badframe; | 1002 | goto badframe; |
1003 | sc = (struct sigcontext __user *) &frame->sctx; | ||
1011 | 1004 | ||
1012 | #if _NSIG != 64 | 1005 | #if _NSIG != 64 |
1013 | #error "Please adjust handle_signal()" | 1006 | #error "Please adjust handle_signal()" |
@@ -1019,7 +1012,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1019 | #else | 1012 | #else |
1020 | || __put_user(oldset->sig[1], &sc->_unused[3]) | 1013 | || __put_user(oldset->sig[1], &sc->_unused[3]) |
1021 | #endif | 1014 | #endif |
1022 | || __put_user(to_user_ptr(frame), &sc->regs) | 1015 | || __put_user(to_user_ptr(&frame->mctx), &sc->regs) |
1023 | || __put_user(sig, &sc->signal)) | 1016 | || __put_user(sig, &sc->signal)) |
1024 | goto badframe; | 1017 | goto badframe; |
1025 | 1018 | ||
@@ -1035,8 +1028,11 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1035 | 1028 | ||
1036 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 1029 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ |
1037 | 1030 | ||
1031 | /* create a stack frame for the caller of the handler */ | ||
1032 | newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; | ||
1038 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) | 1033 | if (put_user(regs->gpr[1], (u32 __user *)newsp)) |
1039 | goto badframe; | 1034 | goto badframe; |
1035 | |||
1040 | regs->gpr[1] = newsp; | 1036 | regs->gpr[1] = newsp; |
1041 | regs->gpr[3] = sig; | 1037 | regs->gpr[3] = sig; |
1042 | regs->gpr[4] = (unsigned long) sc; | 1038 | regs->gpr[4] = (unsigned long) sc; |