diff options
author | David Daney <ddaney@caviumnetworks.com> | 2010-02-18 19:13:05 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-04-12 12:26:15 -0400 |
commit | d814c28ceca8f659c0012eaec8e21eee43710716 (patch) | |
tree | add2c533054febaa51de021eb5b984e1b4818411 /arch/mips/kernel | |
parent | c52d0d30aef84aa8893b34e5254716c8ab5c4472 (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')
-rw-r--r-- | arch/mips/kernel/signal-common.h | 5 | ||||
-rw-r--r-- | arch/mips/kernel/signal.c | 86 | ||||
-rw-r--r-- | arch/mips/kernel/signal32.c | 55 | ||||
-rw-r--r-- | arch/mips/kernel/signal_n32.c | 26 |
4 files changed, 39 insertions, 133 deletions
diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h index 6c8e8c4246f7..10263b405981 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h | |||
@@ -26,11 +26,6 @@ | |||
26 | */ | 26 | */ |
27 | extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | 27 | extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, |
28 | size_t frame_size); | 28 | size_t frame_size); |
29 | /* | ||
30 | * install trampoline code to get back from the sig handler | ||
31 | */ | ||
32 | extern int install_sigtramp(unsigned int __user *tramp, unsigned int syscall); | ||
33 | |||
34 | /* Check and clear pending FPU exceptions in saved CSR */ | 29 | /* Check and clear pending FPU exceptions in saved CSR */ |
35 | extern int fpcsr_pending(unsigned int __user *fpcsr); | 30 | extern int fpcsr_pending(unsigned int __user *fpcsr); |
36 | 31 | ||
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index d0c68b5d717b..2099d5a4c4b7 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <asm/ucontext.h> | 32 | #include <asm/ucontext.h> |
33 | #include <asm/cpu-features.h> | 33 | #include <asm/cpu-features.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 | ||
@@ -44,47 +45,20 @@ extern asmlinkage int _restore_fp_context(struct sigcontext __user *sc); | |||
44 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); | 45 | extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); |
45 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); | 46 | extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); |
46 | 47 | ||
47 | /* | ||
48 | * Horribly complicated - with the bloody RM9000 workarounds enabled | ||
49 | * the signal trampolines is moving to the end of the structure so we can | ||
50 | * increase the alignment without breaking software compatibility. | ||
51 | */ | ||
52 | #if ICACHE_REFILLS_WORKAROUND_WAR == 0 | ||
53 | |||
54 | struct sigframe { | 48 | struct sigframe { |
55 | u32 sf_ass[4]; /* argument save space for o32 */ | 49 | u32 sf_ass[4]; /* argument save space for o32 */ |
56 | u32 sf_code[2]; /* signal trampoline */ | 50 | u32 sf_pad[2]; /* Was: signal trampoline */ |
57 | struct sigcontext sf_sc; | 51 | struct sigcontext sf_sc; |
58 | sigset_t sf_mask; | 52 | sigset_t sf_mask; |
59 | }; | 53 | }; |
60 | 54 | ||
61 | struct rt_sigframe { | 55 | struct rt_sigframe { |
62 | u32 rs_ass[4]; /* argument save space for o32 */ | 56 | u32 rs_ass[4]; /* argument save space for o32 */ |
63 | u32 rs_code[2]; /* signal trampoline */ | 57 | u32 rs_pad[2]; /* Was: signal trampoline */ |
64 | struct siginfo rs_info; | 58 | struct siginfo rs_info; |
65 | struct ucontext rs_uc; | 59 | struct ucontext rs_uc; |
66 | }; | 60 | }; |
67 | 61 | ||
68 | #else | ||
69 | |||
70 | struct sigframe { | ||
71 | u32 sf_ass[4]; /* argument save space for o32 */ | ||
72 | u32 sf_pad[2]; | ||
73 | struct sigcontext sf_sc; /* hw context */ | ||
74 | sigset_t sf_mask; | ||
75 | u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */ | ||
76 | }; | ||
77 | |||
78 | struct rt_sigframe { | ||
79 | u32 rs_ass[4]; /* argument save space for o32 */ | ||
80 | u32 rs_pad[2]; | ||
81 | struct siginfo rs_info; | ||
82 | struct ucontext rs_uc; | ||
83 | u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */ | ||
84 | }; | ||
85 | |||
86 | #endif | ||
87 | |||
88 | /* | 62 | /* |
89 | * Helper routines | 63 | * Helper routines |
90 | */ | 64 | */ |
@@ -266,32 +240,6 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, | |||
266 | return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); | 240 | return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); |
267 | } | 241 | } |
268 | 242 | ||
269 | int install_sigtramp(unsigned int __user *tramp, unsigned int syscall) | ||
270 | { | ||
271 | int err; | ||
272 | |||
273 | /* | ||
274 | * Set up the return code ... | ||
275 | * | ||
276 | * li v0, __NR__foo_sigreturn | ||
277 | * syscall | ||
278 | */ | ||
279 | |||
280 | err = __put_user(0x24020000 + syscall, tramp + 0); | ||
281 | err |= __put_user(0x0000000c , tramp + 1); | ||
282 | if (ICACHE_REFILLS_WORKAROUND_WAR) { | ||
283 | err |= __put_user(0, tramp + 2); | ||
284 | err |= __put_user(0, tramp + 3); | ||
285 | err |= __put_user(0, tramp + 4); | ||
286 | err |= __put_user(0, tramp + 5); | ||
287 | err |= __put_user(0, tramp + 6); | ||
288 | err |= __put_user(0, tramp + 7); | ||
289 | } | ||
290 | flush_cache_sigtramp((unsigned long) tramp); | ||
291 | |||
292 | return err; | ||
293 | } | ||
294 | |||
295 | /* | 243 | /* |
296 | * Atomically swap in the new signal mask, and wait for a signal. | 244 | * Atomically swap in the new signal mask, and wait for a signal. |
297 | */ | 245 | */ |
@@ -484,8 +432,8 @@ badframe: | |||
484 | } | 432 | } |
485 | 433 | ||
486 | #ifdef CONFIG_TRAD_SIGNALS | 434 | #ifdef CONFIG_TRAD_SIGNALS |
487 | static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | 435 | static int setup_frame(void *sig_return, struct k_sigaction *ka, |
488 | int signr, sigset_t *set) | 436 | struct pt_regs *regs, int signr, sigset_t *set) |
489 | { | 437 | { |
490 | struct sigframe __user *frame; | 438 | struct sigframe __user *frame; |
491 | int err = 0; | 439 | int err = 0; |
@@ -494,8 +442,6 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
494 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 442 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
495 | goto give_sigsegv; | 443 | goto give_sigsegv; |
496 | 444 | ||
497 | err |= install_sigtramp(frame->sf_code, __NR_sigreturn); | ||
498 | |||
499 | err |= setup_sigcontext(regs, &frame->sf_sc); | 445 | err |= setup_sigcontext(regs, &frame->sf_sc); |
500 | err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); | 446 | err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); |
501 | if (err) | 447 | if (err) |
@@ -515,7 +461,7 @@ static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
515 | regs->regs[ 5] = 0; | 461 | regs->regs[ 5] = 0; |
516 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; | 462 | regs->regs[ 6] = (unsigned long) &frame->sf_sc; |
517 | regs->regs[29] = (unsigned long) frame; | 463 | regs->regs[29] = (unsigned long) frame; |
518 | regs->regs[31] = (unsigned long) frame->sf_code; | 464 | regs->regs[31] = (unsigned long) sig_return; |
519 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; | 465 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; |
520 | 466 | ||
521 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | 467 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
@@ -529,8 +475,9 @@ give_sigsegv: | |||
529 | } | 475 | } |
530 | #endif | 476 | #endif |
531 | 477 | ||
532 | static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | 478 | static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, |
533 | int signr, sigset_t *set, siginfo_t *info) | 479 | struct pt_regs *regs, int signr, sigset_t *set, |
480 | siginfo_t *info) | ||
534 | { | 481 | { |
535 | struct rt_sigframe __user *frame; | 482 | struct rt_sigframe __user *frame; |
536 | int err = 0; | 483 | int err = 0; |
@@ -539,8 +486,6 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
539 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 486 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
540 | goto give_sigsegv; | 487 | goto give_sigsegv; |
541 | 488 | ||
542 | err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn); | ||
543 | |||
544 | /* Create siginfo. */ | 489 | /* Create siginfo. */ |
545 | err |= copy_siginfo_to_user(&frame->rs_info, info); | 490 | err |= copy_siginfo_to_user(&frame->rs_info, info); |
546 | 491 | ||
@@ -573,7 +518,7 @@ static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | |||
573 | regs->regs[ 5] = (unsigned long) &frame->rs_info; | 518 | regs->regs[ 5] = (unsigned long) &frame->rs_info; |
574 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; | 519 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; |
575 | regs->regs[29] = (unsigned long) frame; | 520 | regs->regs[29] = (unsigned long) frame; |
576 | regs->regs[31] = (unsigned long) frame->rs_code; | 521 | regs->regs[31] = (unsigned long) sig_return; |
577 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; | 522 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; |
578 | 523 | ||
579 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | 524 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
@@ -590,8 +535,11 @@ give_sigsegv: | |||
590 | struct mips_abi mips_abi = { | 535 | struct mips_abi mips_abi = { |
591 | #ifdef CONFIG_TRAD_SIGNALS | 536 | #ifdef CONFIG_TRAD_SIGNALS |
592 | .setup_frame = setup_frame, | 537 | .setup_frame = setup_frame, |
538 | .signal_return_offset = offsetof(struct mips_vdso, signal_trampoline), | ||
593 | #endif | 539 | #endif |
594 | .setup_rt_frame = setup_rt_frame, | 540 | .setup_rt_frame = setup_rt_frame, |
541 | .rt_signal_return_offset = | ||
542 | offsetof(struct mips_vdso, rt_signal_trampoline), | ||
595 | .restart = __NR_restart_syscall | 543 | .restart = __NR_restart_syscall |
596 | }; | 544 | }; |
597 | 545 | ||
@@ -599,6 +547,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
599 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) | 547 | struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) |
600 | { | 548 | { |
601 | int ret; | 549 | int ret; |
550 | struct mips_abi *abi = current->thread.abi; | ||
551 | void *vdso = current->mm->context.vdso; | ||
602 | 552 | ||
603 | switch(regs->regs[0]) { | 553 | switch(regs->regs[0]) { |
604 | case ERESTART_RESTARTBLOCK: | 554 | case ERESTART_RESTARTBLOCK: |
@@ -619,9 +569,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
619 | regs->regs[0] = 0; /* Don't deal with this again. */ | 569 | regs->regs[0] = 0; /* Don't deal with this again. */ |
620 | 570 | ||
621 | if (sig_uses_siginfo(ka)) | 571 | if (sig_uses_siginfo(ka)) |
622 | ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info); | 572 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, |
573 | ka, regs, sig, oldset, info); | ||
623 | else | 574 | else |
624 | ret = current->thread.abi->setup_frame(ka, regs, sig, oldset); | 575 | ret = abi->setup_frame(vdso + abi->signal_return_offset, |
576 | ka, regs, sig, oldset); | ||
625 | 577 | ||
626 | spin_lock_irq(¤t->sighand->siglock); | 578 | spin_lock_irq(¤t->sighand->siglock); |
627 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 579 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
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 | |||
87 | struct sigframe32 { | 79 | struct 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 | ||
94 | struct rt_sigframe32 { | 86 | struct 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 | |||
103 | struct 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 | |||
111 | struct 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 | ||
601 | static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 573 | static 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 | ||
647 | static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 617 | static 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 | */ |
710 | struct mips_abi mips_abi_32 = { | 679 | struct 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 | ||
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index bb277e82d421..2c5df818c65a 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c | |||
@@ -39,13 +39,13 @@ | |||
39 | #include <asm/fpu.h> | 39 | #include <asm/fpu.h> |
40 | #include <asm/cpu-features.h> | 40 | #include <asm/cpu-features.h> |
41 | #include <asm/war.h> | 41 | #include <asm/war.h> |
42 | #include <asm/vdso.h> | ||
42 | 43 | ||
43 | #include "signal-common.h" | 44 | #include "signal-common.h" |
44 | 45 | ||
45 | /* | 46 | /* |
46 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... | 47 | * Including <asm/unistd.h> would give use the 64-bit syscall numbers ... |
47 | */ | 48 | */ |
48 | #define __NR_N32_rt_sigreturn 6211 | ||
49 | #define __NR_N32_restart_syscall 6214 | 49 | #define __NR_N32_restart_syscall 6214 |
50 | 50 | ||
51 | extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *); | 51 | extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *); |
@@ -67,27 +67,13 @@ struct ucontextn32 { | |||
67 | compat_sigset_t uc_sigmask; /* mask last for extensibility */ | 67 | compat_sigset_t uc_sigmask; /* mask last for extensibility */ |
68 | }; | 68 | }; |
69 | 69 | ||
70 | #if ICACHE_REFILLS_WORKAROUND_WAR == 0 | ||
71 | |||
72 | struct rt_sigframe_n32 { | ||
73 | u32 rs_ass[4]; /* argument save space for o32 */ | ||
74 | u32 rs_code[2]; /* signal trampoline */ | ||
75 | struct compat_siginfo rs_info; | ||
76 | struct ucontextn32 rs_uc; | ||
77 | }; | ||
78 | |||
79 | #else /* ICACHE_REFILLS_WORKAROUND_WAR */ | ||
80 | |||
81 | struct rt_sigframe_n32 { | 70 | struct rt_sigframe_n32 { |
82 | u32 rs_ass[4]; /* argument save space for o32 */ | 71 | u32 rs_ass[4]; /* argument save space for o32 */ |
83 | u32 rs_pad[2]; | 72 | u32 rs_pad[2]; /* Was: signal trampoline */ |
84 | struct compat_siginfo rs_info; | 73 | struct compat_siginfo rs_info; |
85 | struct ucontextn32 rs_uc; | 74 | struct ucontextn32 rs_uc; |
86 | u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */ | ||
87 | }; | 75 | }; |
88 | 76 | ||
89 | #endif /* !ICACHE_REFILLS_WORKAROUND_WAR */ | ||
90 | |||
91 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); | 77 | extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); |
92 | 78 | ||
93 | asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) | 79 | asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs) |
@@ -173,7 +159,7 @@ badframe: | |||
173 | force_sig(SIGSEGV, current); | 159 | force_sig(SIGSEGV, current); |
174 | } | 160 | } |
175 | 161 | ||
176 | static int setup_rt_frame_n32(struct k_sigaction * ka, | 162 | static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka, |
177 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) | 163 | struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) |
178 | { | 164 | { |
179 | struct rt_sigframe_n32 __user *frame; | 165 | struct rt_sigframe_n32 __user *frame; |
@@ -184,8 +170,6 @@ static int setup_rt_frame_n32(struct k_sigaction * ka, | |||
184 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) | 170 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
185 | goto give_sigsegv; | 171 | goto give_sigsegv; |
186 | 172 | ||
187 | install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn); | ||
188 | |||
189 | /* Create siginfo. */ | 173 | /* Create siginfo. */ |
190 | err |= copy_siginfo_to_user32(&frame->rs_info, info); | 174 | err |= copy_siginfo_to_user32(&frame->rs_info, info); |
191 | 175 | ||
@@ -219,7 +203,7 @@ static int setup_rt_frame_n32(struct k_sigaction * ka, | |||
219 | regs->regs[ 5] = (unsigned long) &frame->rs_info; | 203 | regs->regs[ 5] = (unsigned long) &frame->rs_info; |
220 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; | 204 | regs->regs[ 6] = (unsigned long) &frame->rs_uc; |
221 | regs->regs[29] = (unsigned long) frame; | 205 | regs->regs[29] = (unsigned long) frame; |
222 | regs->regs[31] = (unsigned long) frame->rs_code; | 206 | regs->regs[31] = (unsigned long) sig_return; |
223 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; | 207 | regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; |
224 | 208 | ||
225 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", | 209 | DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", |
@@ -235,5 +219,7 @@ give_sigsegv: | |||
235 | 219 | ||
236 | struct mips_abi mips_abi_n32 = { | 220 | struct mips_abi mips_abi_n32 = { |
237 | .setup_rt_frame = setup_rt_frame_n32, | 221 | .setup_rt_frame = setup_rt_frame_n32, |
222 | .rt_signal_return_offset = | ||
223 | offsetof(struct mips_vdso, n32_rt_signal_trampoline), | ||
238 | .restart = __NR_N32_restart_syscall | 224 | .restart = __NR_N32_restart_syscall |
239 | }; | 225 | }; |