aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/signal.c')
-rw-r--r--arch/mips/kernel/signal.c86
1 files changed, 19 insertions, 67 deletions
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);
44extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc); 45extern asmlinkage int fpu_emulator_save_context(struct sigcontext __user *sc);
45extern asmlinkage int fpu_emulator_restore_context(struct sigcontext __user *sc); 46extern 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
54struct sigframe { 48struct 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
61struct rt_sigframe { 55struct 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
70struct 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
78struct 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
269int 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
487static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, 435static 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
532static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, 478static 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:
590struct mips_abi mips_abi = { 535struct 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(&current->sighand->siglock); 578 spin_lock_irq(&current->sighand->siglock);
627 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask); 579 sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);