aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/signal32.c
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2010-02-18 19:13:05 -0500
committerRalf Baechle <ralf@linux-mips.org>2010-04-12 12:26:15 -0400
commitd814c28ceca8f659c0012eaec8e21eee43710716 (patch)
treeadd2c533054febaa51de021eb5b984e1b4818411 /arch/mips/kernel/signal32.c
parentc52d0d30aef84aa8893b34e5254716c8ab5c4472 (diff)
MIPS: Move signal trampolines off of the stack.
This is a follow on to the vdso patch. Since all processes now have signal trampolines permanently mapped, we can use those instead of putting the trampoline on the stack and invalidating the corresponding icache across all CPUs. We also get rid of a bunch of ICACHE_REFILLS_WORKAROUND_WAR code. [Ralf: GDB 7.1 which has the necessary modifications to allow backtracing over signal frames will supposedly be released tomorrow. The old signal frame format obsoleted by this patch exists in two variations, for sane processors and for those requiring ICACHE_REFILLS_WORKAROUND_WAR. So there was never a GDB which did support backtracing over signal frames on all MIPS systems. This convinved me this series should be applied and pushed upstream as soon as possible.] Signed-off-by: David Daney <ddaney@caviumnetworks.com> To: linux-mips@linux-mips.org Patchwork: http://patchwork.linux-mips.org/patch/974/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r--arch/mips/kernel/signal32.c55
1 files changed, 14 insertions, 41 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 03abaf048f09..a0ed0e052b2e 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -32,6 +32,7 @@
32#include <asm/system.h> 32#include <asm/system.h>
33#include <asm/fpu.h> 33#include <asm/fpu.h>
34#include <asm/war.h> 34#include <asm/war.h>
35#include <asm/vdso.h>
35 36
36#include "signal-common.h" 37#include "signal-common.h"
37 38
@@ -47,8 +48,6 @@ extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user
47/* 48/*
48 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... 49 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
49 */ 50 */
50#define __NR_O32_sigreturn 4119
51#define __NR_O32_rt_sigreturn 4193
52#define __NR_O32_restart_syscall 4253 51#define __NR_O32_restart_syscall 4253
53 52
54/* 32-bit compatibility types */ 53/* 32-bit compatibility types */
@@ -77,47 +76,20 @@ struct ucontext32 {
77 compat_sigset_t uc_sigmask; /* mask last for extensibility */ 76 compat_sigset_t uc_sigmask; /* mask last for extensibility */
78}; 77};
79 78
80/*
81 * Horribly complicated - with the bloody RM9000 workarounds enabled
82 * the signal trampolines is moving to the end of the structure so we can
83 * increase the alignment without breaking software compatibility.
84 */
85#if ICACHE_REFILLS_WORKAROUND_WAR == 0
86
87struct sigframe32 { 79struct sigframe32 {
88 u32 sf_ass[4]; /* argument save space for o32 */ 80 u32 sf_ass[4]; /* argument save space for o32 */
89 u32 sf_code[2]; /* signal trampoline */ 81 u32 sf_pad[2]; /* Was: signal trampoline */
90 struct sigcontext32 sf_sc; 82 struct sigcontext32 sf_sc;
91 compat_sigset_t sf_mask; 83 compat_sigset_t sf_mask;
92}; 84};
93 85
94struct rt_sigframe32 { 86struct rt_sigframe32 {
95 u32 rs_ass[4]; /* argument save space for o32 */ 87 u32 rs_ass[4]; /* argument save space for o32 */
96 u32 rs_code[2]; /* signal trampoline */ 88 u32 rs_pad[2]; /* Was: signal trampoline */
97 compat_siginfo_t rs_info; 89 compat_siginfo_t rs_info;
98 struct ucontext32 rs_uc; 90 struct ucontext32 rs_uc;
99}; 91};
100 92
101#else /* ICACHE_REFILLS_WORKAROUND_WAR */
102
103struct sigframe32 {
104 u32 sf_ass[4]; /* argument save space for o32 */
105 u32 sf_pad[2];
106 struct sigcontext32 sf_sc; /* hw context */
107 compat_sigset_t sf_mask;
108 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
109};
110
111struct rt_sigframe32 {
112 u32 rs_ass[4]; /* argument save space for o32 */
113 u32 rs_pad[2];
114 compat_siginfo_t rs_info;
115 struct ucontext32 rs_uc;
116 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
117};
118
119#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
120
121/* 93/*
122 * sigcontext handlers 94 * sigcontext handlers
123 */ 95 */
@@ -598,8 +570,8 @@ badframe:
598 force_sig(SIGSEGV, current); 570 force_sig(SIGSEGV, current);
599} 571}
600 572
601static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, 573static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
602 int signr, sigset_t *set) 574 struct pt_regs *regs, int signr, sigset_t *set)
603{ 575{
604 struct sigframe32 __user *frame; 576 struct sigframe32 __user *frame;
605 int err = 0; 577 int err = 0;
@@ -608,8 +580,6 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
608 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 580 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
609 goto give_sigsegv; 581 goto give_sigsegv;
610 582
611 err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
612
613 err |= setup_sigcontext32(regs, &frame->sf_sc); 583 err |= setup_sigcontext32(regs, &frame->sf_sc);
614 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); 584 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
615 585
@@ -630,7 +600,7 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
630 regs->regs[ 5] = 0; 600 regs->regs[ 5] = 0;
631 regs->regs[ 6] = (unsigned long) &frame->sf_sc; 601 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
632 regs->regs[29] = (unsigned long) frame; 602 regs->regs[29] = (unsigned long) frame;
633 regs->regs[31] = (unsigned long) frame->sf_code; 603 regs->regs[31] = (unsigned long) sig_return;
634 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 604 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
635 605
636 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 606 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@@ -644,8 +614,9 @@ give_sigsegv:
644 return -EFAULT; 614 return -EFAULT;
645} 615}
646 616
647static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, 617static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
648 int signr, sigset_t *set, siginfo_t *info) 618 struct pt_regs *regs, int signr, sigset_t *set,
619 siginfo_t *info)
649{ 620{
650 struct rt_sigframe32 __user *frame; 621 struct rt_sigframe32 __user *frame;
651 int err = 0; 622 int err = 0;
@@ -655,8 +626,6 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
655 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 626 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
656 goto give_sigsegv; 627 goto give_sigsegv;
657 628
658 err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
659
660 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ 629 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
661 err |= copy_siginfo_to_user32(&frame->rs_info, info); 630 err |= copy_siginfo_to_user32(&frame->rs_info, info);
662 631
@@ -690,7 +659,7 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
690 regs->regs[ 5] = (unsigned long) &frame->rs_info; 659 regs->regs[ 5] = (unsigned long) &frame->rs_info;
691 regs->regs[ 6] = (unsigned long) &frame->rs_uc; 660 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
692 regs->regs[29] = (unsigned long) frame; 661 regs->regs[29] = (unsigned long) frame;
693 regs->regs[31] = (unsigned long) frame->rs_code; 662 regs->regs[31] = (unsigned long) sig_return;
694 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; 663 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
695 664
696 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", 665 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
@@ -709,7 +678,11 @@ give_sigsegv:
709 */ 678 */
710struct mips_abi mips_abi_32 = { 679struct mips_abi mips_abi_32 = {
711 .setup_frame = setup_frame_32, 680 .setup_frame = setup_frame_32,
681 .signal_return_offset =
682 offsetof(struct mips_vdso, o32_signal_trampoline),
712 .setup_rt_frame = setup_rt_frame_32, 683 .setup_rt_frame = setup_rt_frame_32,
684 .rt_signal_return_offset =
685 offsetof(struct mips_vdso, o32_rt_signal_trampoline),
713 .restart = __NR_O32_restart_syscall 686 .restart = __NR_O32_restart_syscall
714}; 687};
715 688