diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /arch/mips/kernel/signal32.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'arch/mips/kernel/signal32.c')
-rw-r--r-- | arch/mips/kernel/signal32.c | 79 |
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 | ||
39 | static int (*save_fp_context32)(struct sigcontext32 __user *sc); | ||
40 | static int (*restore_fp_context32)(struct sigcontext32 __user *sc); | ||
41 | |||
42 | extern asmlinkage int _save_fp_context32(struct sigcontext32 __user *sc); | ||
43 | extern asmlinkage int _restore_fp_context32(struct sigcontext32 __user *sc); | ||
44 | |||
45 | extern asmlinkage int fpu_emulator_save_context32(struct sigcontext32 __user *sc); | ||
46 | extern 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 | |||
78 | struct sigframe32 { | 79 | struct 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 | ||
85 | struct rt_sigframe32 { | 86 | struct 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 | |||
94 | struct 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 | |||
102 | struct 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 | ||
592 | 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, |
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 | ||
638 | 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, |
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 | */ |
701 | struct mips_abi mips_abi_32 = { | 679 | struct 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 | |||
814 | static 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 | |||
827 | arch_initcall(signal32_init); | ||