aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/signal32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r--arch/mips/kernel/signal32.c79
1 files changed, 38 insertions, 41 deletions
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 2e74075ac0ca..a0ed0e052b2e 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -32,14 +32,22 @@
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
39static int (*save_fp_context32)(struct sigcontext32 __user *sc);
40static int (*restore_fp_context32)(struct sigcontext32 __user *sc);
41
42extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc);
43extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc);
44
45extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc);
46extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user *sc);
47
38/* 48/*
39 * 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 ...
40 */ 50 */
41#define __NR_O32_sigreturn 4119
42#define __NR_O32_rt_sigreturn 4193
43#define __NR_O32_restart_syscall 4253 51#define __NR_O32_restart_syscall 4253
44 52
45/* 32-bit compatibility types */ 53/* 32-bit compatibility types */
@@ -68,47 +76,20 @@ struct ucontext32 {
68 compat_sigset_t uc_sigmask; /* mask last for extensibility */ 76 compat_sigset_t uc_sigmask; /* mask last for extensibility */
69}; 77};
70 78
71/*
72 * Horribly complicated - with the bloody RM9000 workarounds enabled
73 * the signal trampolines is moving to the end of the structure so we can
74 * increase the alignment without breaking software compatibility.
75 */
76#if ICACHE_REFILLS_WORKAROUND_WAR == 0
77
78struct sigframe32 { 79struct sigframe32 {
79 u32 sf_ass[4]; /* argument save space for o32 */ 80 u32 sf_ass[4]; /* argument save space for o32 */
80 u32 sf_code[2]; /* signal trampoline */ 81 u32 sf_pad[2]; /* Was: signal trampoline */
81 struct sigcontext32 sf_sc; 82 struct sigcontext32 sf_sc;
82 compat_sigset_t sf_mask; 83 compat_sigset_t sf_mask;
83}; 84};
84 85
85struct rt_sigframe32 { 86struct rt_sigframe32 {
86 u32 rs_ass[4]; /* argument save space for o32 */ 87 u32 rs_ass[4]; /* argument save space for o32 */
87 u32 rs_code[2]; /* signal trampoline */ 88 u32 rs_pad[2]; /* Was: signal trampoline */
88 compat_siginfo_t rs_info;
89 struct ucontext32 rs_uc;
90};
91
92#else /* ICACHE_REFILLS_WORKAROUND_WAR */
93
94struct sigframe32 {
95 u32 sf_ass[4]; /* argument save space for o32 */
96 u32 sf_pad[2];
97 struct sigcontext32 sf_sc; /* hw context */
98 compat_sigset_t sf_mask;
99 u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */
100};
101
102struct rt_sigframe32 {
103 u32 rs_ass[4]; /* argument save space for o32 */
104 u32 rs_pad[2];
105 compat_siginfo_t rs_info; 89 compat_siginfo_t rs_info;
106 struct ucontext32 rs_uc; 90 struct ucontext32 rs_uc;
107 u32 rs_code[8] __attribute__((aligned(32))); /* signal trampoline */
108}; 91};
109 92
110#endif /* !ICACHE_REFILLS_WORKAROUND_WAR */
111
112/* 93/*
113 * sigcontext handlers 94 * sigcontext handlers
114 */ 95 */
@@ -589,8 +570,8 @@ badframe:
589 force_sig(SIGSEGV, current); 570 force_sig(SIGSEGV, current);
590} 571}
591 572
592static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, 573static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
593 int signr, sigset_t *set) 574 struct pt_regs *regs, int signr, sigset_t *set)
594{ 575{
595 struct sigframe32 __user *frame; 576 struct sigframe32 __user *frame;
596 int err = 0; 577 int err = 0;
@@ -599,8 +580,6 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
599 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 580 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
600 goto give_sigsegv; 581 goto give_sigsegv;
601 582
602 err |= install_sigtramp(frame->sf_code, __NR_O32_sigreturn);
603
604 err |= setup_sigcontext32(regs, &frame->sf_sc); 583 err |= setup_sigcontext32(regs, &frame->sf_sc);
605 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); 584 err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
606 585
@@ -621,7 +600,7 @@ static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
621 regs->regs[ 5] = 0; 600 regs->regs[ 5] = 0;
622 regs->regs[ 6] = (unsigned long) &frame->sf_sc; 601 regs->regs[ 6] = (unsigned long) &frame->sf_sc;
623 regs->regs[29] = (unsigned long) frame; 602 regs->regs[29] = (unsigned long) frame;
624 regs->regs[31] = (unsigned long) frame->sf_code; 603 regs->regs[31] = (unsigned long) sig_return;
625 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;
626 605
627 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",
@@ -635,8 +614,9 @@ give_sigsegv:
635 return -EFAULT; 614 return -EFAULT;
636} 615}
637 616
638static 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,
639 int signr, sigset_t *set, siginfo_t *info) 618 struct pt_regs *regs, int signr, sigset_t *set,
619 siginfo_t *info)
640{ 620{
641 struct rt_sigframe32 __user *frame; 621 struct rt_sigframe32 __user *frame;
642 int err = 0; 622 int err = 0;
@@ -646,8 +626,6 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
646 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) 626 if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
647 goto give_sigsegv; 627 goto give_sigsegv;
648 628
649 err |= install_sigtramp(frame->rs_code, __NR_O32_rt_sigreturn);
650
651 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ 629 /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
652 err |= copy_siginfo_to_user32(&frame->rs_info, info); 630 err |= copy_siginfo_to_user32(&frame->rs_info, info);
653 631
@@ -681,7 +659,7 @@ static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
681 regs->regs[ 5] = (unsigned long) &frame->rs_info; 659 regs->regs[ 5] = (unsigned long) &frame->rs_info;
682 regs->regs[ 6] = (unsigned long) &frame->rs_uc; 660 regs->regs[ 6] = (unsigned long) &frame->rs_uc;
683 regs->regs[29] = (unsigned long) frame; 661 regs->regs[29] = (unsigned long) frame;
684 regs->regs[31] = (unsigned long) frame->rs_code; 662 regs->regs[31] = (unsigned long) sig_return;
685 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;
686 664
687 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",
@@ -700,7 +678,11 @@ give_sigsegv:
700 */ 678 */
701struct mips_abi mips_abi_32 = { 679struct mips_abi mips_abi_32 = {
702 .setup_frame = setup_frame_32, 680 .setup_frame = setup_frame_32,
681 .signal_return_offset =
682 offsetof(struct mips_vdso, o32_signal_trampoline),
703 .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),
704 .restart = __NR_O32_restart_syscall 686 .restart = __NR_O32_restart_syscall
705}; 687};
706 688
@@ -828,3 +810,18 @@ SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
828 info.si_code |= __SI_CHLD; 810 info.si_code |= __SI_CHLD;
829 return copy_siginfo_to_user32(uinfo, &info); 811 return copy_siginfo_to_user32(uinfo, &info);
830} 812}
813
814static int signal32_init(void)
815{
816 if (cpu_has_fpu) {
817 save_fp_context32 = _save_fp_context32;
818 restore_fp_context32 = _restore_fp_context32;
819 } else {
820 save_fp_context32 = fpu_emulator_save_context32;
821 restore_fp_context32 = fpu_emulator_restore_context32;
822 }
823
824 return 0;
825}
826
827arch_initcall(signal32_init);