Commit d814c28ceca8f659c0012eaec8e21eee43710716

Authored by David Daney
Committed by Ralf Baechle
1 parent c52d0d30ae

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>

Showing 5 changed files with 43 additions and 135 deletions Side-by-side Diff

arch/mips/include/asm/abi.h
... ... @@ -13,12 +13,14 @@
13 13 #include <asm/siginfo.h>
14 14  
15 15 struct mips_abi {
16   - int (* const setup_frame)(struct k_sigaction * ka,
  16 + int (* const setup_frame)(void *sig_return, struct k_sigaction *ka,
17 17 struct pt_regs *regs, int signr,
18 18 sigset_t *set);
19   - int (* const setup_rt_frame)(struct k_sigaction * ka,
  19 + const unsigned long signal_return_offset;
  20 + int (* const setup_rt_frame)(void *sig_return, struct k_sigaction *ka,
20 21 struct pt_regs *regs, int signr,
21 22 sigset_t *set, siginfo_t *info);
  23 + const unsigned long rt_signal_return_offset;
22 24 const unsigned long restart;
23 25 };
24 26  
arch/mips/kernel/signal-common.h
... ... @@ -26,11 +26,6 @@
26 26 */
27 27 extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
28 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 29 /* Check and clear pending FPU exceptions in saved CSR */
35 30 extern int fpcsr_pending(unsigned int __user *fpcsr);
36 31  
arch/mips/kernel/signal.c
... ... @@ -32,6 +32,7 @@
32 32 #include <asm/ucontext.h>
33 33 #include <asm/cpu-features.h>
34 34 #include <asm/war.h>
  35 +#include <asm/vdso.h>
35 36  
36 37 #include "signal-common.h"
37 38  
38 39  
39 40  
40 41  
... ... @@ -44,47 +45,20 @@
44 45 extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
45 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 48 struct sigframe {
55 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 51 struct sigcontext sf_sc;
58 52 sigset_t sf_mask;
59 53 };
60 54  
61 55 struct rt_sigframe {
62 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 58 struct siginfo rs_info;
65 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 63 * Helper routines
90 64 */
... ... @@ -266,32 +240,6 @@
266 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 244 * Atomically swap in the new signal mask, and wait for a signal.
297 245 */
... ... @@ -484,8 +432,8 @@
484 432 }
485 433  
486 434 #ifdef CONFIG_TRAD_SIGNALS
487   -static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
488   - int signr, sigset_t *set)
  435 +static int setup_frame(void *sig_return, struct k_sigaction *ka,
  436 + struct pt_regs *regs, int signr, sigset_t *set)
489 437 {
490 438 struct sigframe __user *frame;
491 439 int err = 0;
... ... @@ -494,8 +442,6 @@
494 442 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
495 443 goto give_sigsegv;
496 444  
497   - err |= install_sigtramp(frame->sf_code, __NR_sigreturn);
498   -
499 445 err |= setup_sigcontext(regs, &frame->sf_sc);
500 446 err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
501 447 if (err)
... ... @@ -515,7 +461,7 @@
515 461 regs->regs[ 5] = 0;
516 462 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
517 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 465 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
520 466  
521 467 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
... ... @@ -529,8 +475,9 @@
529 475 }
530 476 #endif
531 477  
532   -static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
533   - int signr, sigset_t *set, siginfo_t *info)
  478 +static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
  479 + struct pt_regs *regs, int signr, sigset_t *set,
  480 + siginfo_t *info)
534 481 {
535 482 struct rt_sigframe __user *frame;
536 483 int err = 0;
... ... @@ -539,8 +486,6 @@
539 486 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
540 487 goto give_sigsegv;
541 488  
542   - err |= install_sigtramp(frame->rs_code, __NR_rt_sigreturn);
543   -
544 489 /* Create siginfo. */
545 490 err |= copy_siginfo_to_user(&frame->rs_info, info);
546 491  
... ... @@ -573,7 +518,7 @@
573 518 regs->regs[ 5] = (unsigned long) &frame->rs_info;
574 519 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
575 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 522 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
578 523  
579 524 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
580 525  
... ... @@ -590,8 +535,11 @@
590 535 struct mips_abi mips_abi = {
591 536 #ifdef CONFIG_TRAD_SIGNALS
592 537 .setup_frame = setup_frame,
  538 + .signal_return_offset = offsetof(struct mips_vdso, signal_trampoline),
593 539 #endif
594 540 .setup_rt_frame = setup_rt_frame,
  541 + .rt_signal_return_offset =
  542 + offsetof(struct mips_vdso, rt_signal_trampoline),
595 543 .restart = __NR_restart_syscall
596 544 };
597 545  
... ... @@ -599,6 +547,8 @@
599 547 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
600 548 {
601 549 int ret;
  550 + struct mips_abi *abi = current->thread.abi;
  551 + void *vdso = current->mm->context.vdso;
602 552  
603 553 switch(regs->regs[0]) {
604 554 case ERESTART_RESTARTBLOCK:
605 555  
... ... @@ -619,9 +569,11 @@
619 569 regs->regs[0] = 0; /* Don't deal with this again. */
620 570  
621 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 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 578 spin_lock_irq(&current->sighand->siglock);
627 579 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
arch/mips/kernel/signal32.c
... ... @@ -32,6 +32,7 @@
32 32 #include <asm/system.h>
33 33 #include <asm/fpu.h>
34 34 #include <asm/war.h>
  35 +#include <asm/vdso.h>
35 36  
36 37 #include "signal-common.h"
37 38  
... ... @@ -47,8 +48,6 @@
47 48 /*
48 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 51 #define __NR_O32_restart_syscall 4253
53 52  
54 53 /* 32-bit compatibility types */
55 54  
56 55  
57 56  
... ... @@ -77,47 +76,20 @@
77 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 79 struct sigframe32 {
88 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 82 struct sigcontext32 sf_sc;
91 83 compat_sigset_t sf_mask;
92 84 };
93 85  
94 86 struct rt_sigframe32 {
95 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 89 compat_siginfo_t rs_info;
98 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 94 * sigcontext handlers
123 95 */
... ... @@ -598,8 +570,8 @@
598 570 force_sig(SIGSEGV, current);
599 571 }
600 572  
601   -static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
602   - int signr, sigset_t *set)
  573 +static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
  574 + struct pt_regs *regs, int signr, sigset_t *set)
603 575 {
604 576 struct sigframe32 __user *frame;
605 577 int err = 0;
... ... @@ -608,8 +580,6 @@
608 580 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
609 581 goto give_sigsegv;
610 582  
611   - err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
612   -
613 583 err |= setup_sigcontext32(regs, &frame->sf_sc);
614 584 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
615 585  
... ... @@ -630,7 +600,7 @@
630 600 regs->regs[ 5] = 0;
631 601 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
632 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 604 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
635 605  
636 606 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
... ... @@ -644,8 +614,9 @@
644 614 return -EFAULT;
645 615 }
646 616  
647   -static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
648   - int signr, sigset_t *set, siginfo_t *info)
  617 +static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
  618 + struct pt_regs *regs, int signr, sigset_t *set,
  619 + siginfo_t *info)
649 620 {
650 621 struct rt_sigframe32 __user *frame;
651 622 int err = 0;
... ... @@ -655,8 +626,6 @@
655 626 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
656 627 goto give_sigsegv;
657 628  
658   - err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
659   -
660 629 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
661 630 err |= copy_siginfo_to_user32(&frame->rs_info, info);
662 631  
... ... @@ -690,7 +659,7 @@
690 659 regs->regs[ 5] = (unsigned long) &frame->rs_info;
691 660 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
692 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 663 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
695 664  
696 665 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
697 666  
... ... @@ -709,7 +678,11 @@
709 678 */
710 679 struct mips_abi mips_abi_32 = {
711 680 .setup_frame = setup_frame_32,
  681 + .signal_return_offset =
  682 + offsetof(struct mips_vdso, o32_signal_trampoline),
712 683 .setup_rt_frame = setup_rt_frame_32,
  684 + .rt_signal_return_offset =
  685 + offsetof(struct mips_vdso, o32_rt_signal_trampoline),
713 686 .restart = __NR_O32_restart_syscall
714 687 };
715 688  
arch/mips/kernel/signal_n32.c
... ... @@ -39,13 +39,13 @@
39 39 #include <asm/fpu.h>
40 40 #include <asm/cpu-features.h>
41 41 #include <asm/war.h>
  42 +#include <asm/vdso.h>
42 43  
43 44 #include "signal-common.h"
44 45  
45 46 /*
46 47 * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
47 48 */
48   -#define __NR_N32_rt_sigreturn 6211
49 49 #define __NR_N32_restart_syscall 6214
50 50  
51 51 extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
52 52  
53 53  
... ... @@ -67,27 +67,13 @@
67 67 compat_sigset_t uc_sigmask; /* mask last for extensibility */
68 68 };
69 69  
70   -#if ICACHE_REFILLS_WORKAROUND_WAR == 0
71   -
72 70 struct rt_sigframe_n32 {
73 71 u32 rs_ass[4]; /* argument save space for o32 */
74   - u32 rs_code[2]; /* signal trampoline */
  72 + u32 rs_pad[2]; /* Was: signal trampoline */
75 73 struct compat_siginfo rs_info;
76 74 struct ucontextn32 rs_uc;
77 75 };
78 76  
79   -#else /* ICACHE_REFILLS_WORKAROUND_WAR */
80   -
81   -struct rt_sigframe_n32 {
82   - u32 rs_ass[4]; /* argument save space for o32 */
83   - u32 rs_pad[2];
84   - struct compat_siginfo rs_info;
85   - struct ucontextn32 rs_uc;
86   - u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */
87   -};
88   -
89   -#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
90   -
91 77 extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
92 78  
93 79 asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
... ... @@ -173,7 +159,7 @@
173 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 163 struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
178 164 {
179 165 struct rt_sigframe_n32 __user *frame;
... ... @@ -184,8 +170,6 @@
184 170 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
185 171 goto give_sigsegv;
186 172  
187   - install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
188   -
189 173 /* Create siginfo. */
190 174 err |= copy_siginfo_to_user32(&frame->rs_info, info);
191 175  
... ... @@ -219,7 +203,7 @@
219 203 regs->regs[ 5] = (unsigned long) &frame->rs_info;
220 204 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
221 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 207 regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
224 208  
225 209 DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
... ... @@ -235,6 +219,8 @@
235 219  
236 220 struct mips_abi mips_abi_n32 = {
237 221 .setup_rt_frame = setup_rt_frame_n32,
  222 + .rt_signal_return_offset =
  223 + offsetof(struct mips_vdso, n32_rt_signal_trampoline),
238 224 .restart = __NR_N32_restart_syscall
239 225 };