aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2007-02-15 06:40:37 -0500
committerRalf Baechle <ralf@linux-mips.org>2007-02-18 16:31:35 -0500
commit151fd6acd94e12ef3a7d5fa0911a2590690c493f (patch)
tree33623a4cf6c6ce7c134f3cc5624dbcac26817238
parent38201fb23cd554f942702cd938c3215a76296c87 (diff)
[MIPS] signals: Share even more code.
native and compat do_signal and handle_signal are identical and can easily be unified. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/process.c33
-rw-r--r--arch/mips/kernel/signal.c18
-rw-r--r--arch/mips/kernel/signal32.c118
-rw-r--r--arch/mips/kernel/signal_n32.c8
-rw-r--r--include/asm-mips/abi.h2
-rw-r--r--include/asm-mips/compat-signal.h3
-rw-r--r--include/asm-mips/signal.h17
7 files changed, 35 insertions, 164 deletions
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 04e5b38d327d..9704c21607a2 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -26,7 +26,6 @@
26#include <linux/completion.h> 26#include <linux/completion.h>
27#include <linux/kallsyms.h> 27#include <linux/kallsyms.h>
28 28
29#include <asm/abi.h>
30#include <asm/bootinfo.h> 29#include <asm/bootinfo.h>
31#include <asm/cpu.h> 30#include <asm/cpu.h>
32#include <asm/dsp.h> 31#include <asm/dsp.h>
@@ -66,38 +65,6 @@ ATTRIB_NORET void cpu_idle(void)
66 } 65 }
67} 66}
68 67
69/*
70 * Native o32 and N64 ABI without DSP ASE
71 */
72struct mips_abi mips_abi = {
73 .do_signal = do_signal,
74#ifdef CONFIG_TRAD_SIGNALS
75 .setup_frame = setup_frame,
76#endif
77 .setup_rt_frame = setup_rt_frame
78};
79
80#ifdef CONFIG_MIPS32_O32
81/*
82 * o32 compatibility on 64-bit kernels, without DSP ASE
83 */
84struct mips_abi mips_abi_32 = {
85 .do_signal = do_signal32,
86 .setup_frame = setup_frame_32,
87 .setup_rt_frame = setup_rt_frame_32
88};
89#endif /* CONFIG_MIPS32_O32 */
90
91#ifdef CONFIG_MIPS32_N32
92/*
93 * N32 on 64-bit kernels, without DSP ASE
94 */
95struct mips_abi mips_abi_n32 = {
96 .do_signal = do_signal,
97 .setup_rt_frame = setup_rt_frame_n32
98};
99#endif /* CONFIG_MIPS32_N32 */
100
101asmlinkage void ret_from_fork(void); 68asmlinkage void ret_from_fork(void);
102 69
103void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) 70void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c
index b2e9ab1bb101..adbfb95e42d0 100644
--- a/arch/mips/kernel/signal.c
+++ b/arch/mips/kernel/signal.c
@@ -398,7 +398,7 @@ badframe:
398} 398}
399 399
400#ifdef CONFIG_TRAD_SIGNALS 400#ifdef CONFIG_TRAD_SIGNALS
401int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, 401static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
402 int signr, sigset_t *set) 402 int signr, sigset_t *set)
403{ 403{
404 struct sigframe __user *frame; 404 struct sigframe __user *frame;
@@ -443,7 +443,7 @@ give_sigsegv:
443} 443}
444#endif 444#endif
445 445
446int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, 446static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
447 int signr, sigset_t *set, siginfo_t *info) 447 int signr, sigset_t *set, siginfo_t *info)
448{ 448{
449 struct rt_sigframe __user *frame; 449 struct rt_sigframe __user *frame;
@@ -501,6 +501,14 @@ give_sigsegv:
501 return -EFAULT; 501 return -EFAULT;
502} 502}
503 503
504struct mips_abi mips_abi = {
505#ifdef CONFIG_TRAD_SIGNALS
506 .setup_frame = setup_frame,
507#endif
508 .setup_rt_frame = setup_rt_frame,
509 .restart = __NR_restart_syscall
510};
511
504static int handle_signal(unsigned long sig, siginfo_t *info, 512static int handle_signal(unsigned long sig, siginfo_t *info,
505 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) 513 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
506{ 514{
@@ -539,7 +547,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
539 return ret; 547 return ret;
540} 548}
541 549
542void do_signal(struct pt_regs *regs) 550static void do_signal(struct pt_regs *regs)
543{ 551{
544 struct k_sigaction ka; 552 struct k_sigaction ka;
545 sigset_t *oldset; 553 sigset_t *oldset;
@@ -589,7 +597,7 @@ void do_signal(struct pt_regs *regs)
589 regs->cp0_epc -= 8; 597 regs->cp0_epc -= 8;
590 } 598 }
591 if (regs->regs[2] == ERESTART_RESTARTBLOCK) { 599 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
592 regs->regs[2] = __NR_restart_syscall; 600 regs->regs[2] = current->thread.abi->restart;
593 regs->regs[7] = regs->regs[26]; 601 regs->regs[7] = regs->regs[26];
594 regs->cp0_epc -= 4; 602 regs->cp0_epc -= 4;
595 } 603 }
@@ -615,5 +623,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
615{ 623{
616 /* deal with pending signal delivery */ 624 /* deal with pending signal delivery */
617 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) 625 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
618 current->thread.abi->do_signal(regs); 626 do_signal(regs);
619} 627}
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index 9f829f63024b..02062fc59f77 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -104,7 +104,7 @@ typedef struct compat_siginfo {
104 */ 104 */
105#define __NR_O32_sigreturn 4119 105#define __NR_O32_sigreturn 4119
106#define __NR_O32_rt_sigreturn 4193 106#define __NR_O32_rt_sigreturn 4193
107#define __NR_O32_restart_syscall 4253 107#define __NR_O32_restart_syscall 4253
108 108
109/* 32-bit compatibility types */ 109/* 32-bit compatibility types */
110 110
@@ -598,7 +598,7 @@ badframe:
598 force_sig(SIGSEGV, current); 598 force_sig(SIGSEGV, current);
599} 599}
600 600
601int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, 601static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
602 int signr, sigset_t *set) 602 int signr, sigset_t *set)
603{ 603{
604 struct sigframe32 __user *frame; 604 struct sigframe32 __user *frame;
@@ -644,7 +644,7 @@ give_sigsegv:
644 return -EFAULT; 644 return -EFAULT;
645} 645}
646 646
647int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, 647static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
648 int signr, sigset_t *set, siginfo_t *info) 648 int signr, sigset_t *set, siginfo_t *info)
649{ 649{
650 struct rt_sigframe32 __user *frame; 650 struct rt_sigframe32 __user *frame;
@@ -704,110 +704,14 @@ give_sigsegv:
704 return -EFAULT; 704 return -EFAULT;
705} 705}
706 706
707static inline int handle_signal(unsigned long sig, siginfo_t *info, 707/*
708 struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) 708 * o32 compatibility on 64-bit kernels, without DSP ASE
709{ 709 */
710 int ret; 710struct mips_abi mips_abi_32 = {
711 711 .setup_frame = setup_frame_32,
712 switch (regs->regs[0]) { 712 .setup_rt_frame = setup_rt_frame_32,
713 case ERESTART_RESTARTBLOCK: 713 .restart = __NR_O32_restart_syscall
714 case ERESTARTNOHAND: 714};
715 regs->regs[2] = EINTR;
716 break;
717 case ERESTARTSYS:
718 if (!(ka->sa.sa_flags & SA_RESTART)) {
719 regs->regs[2] = EINTR;
720 break;
721 }
722 /* fallthrough */
723 case ERESTARTNOINTR: /* Userland will reload $v0. */
724 regs->regs[7] = regs->regs[26];
725 regs->cp0_epc -= 8;
726 }
727
728 regs->regs[0] = 0; /* Don't deal with this again. */
729
730 if (ka->sa.sa_flags & SA_SIGINFO)
731 ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
732 else
733 ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
734
735 spin_lock_irq(&current->sighand->siglock);
736 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
737 if (!(ka->sa.sa_flags & SA_NODEFER))
738 sigaddset(&current->blocked,sig);
739 recalc_sigpending();
740 spin_unlock_irq(&current->sighand->siglock);
741
742 return ret;
743}
744
745void do_signal32(struct pt_regs *regs)
746{
747 struct k_sigaction ka;
748 sigset_t *oldset;
749 siginfo_t info;
750 int signr;
751
752 /*
753 * We want the common case to go fast, which is why we may in certain
754 * cases get here from kernel mode. Just return without doing anything
755 * if so.
756 */
757 if (!user_mode(regs))
758 return;
759
760 if (test_thread_flag(TIF_RESTORE_SIGMASK))
761 oldset = &current->saved_sigmask;
762 else
763 oldset = &current->blocked;
764
765 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
766 if (signr > 0) {
767 /* Whee! Actually deliver the signal. */
768 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
769 /*
770 * A signal was successfully delivered; the saved
771 * sigmask will have been stored in the signal frame,
772 * and will be restored by sigreturn, so we can simply
773 * clear the TIF_RESTORE_SIGMASK flag.
774 */
775 if (test_thread_flag(TIF_RESTORE_SIGMASK))
776 clear_thread_flag(TIF_RESTORE_SIGMASK);
777 }
778
779 return;
780 }
781
782 /*
783 * Who's code doesn't conform to the restartable syscall convention
784 * dies here!!! The li instruction, a single machine instruction,
785 * must directly be followed by the syscall instruction.
786 */
787 if (regs->regs[0]) {
788 if (regs->regs[2] == ERESTARTNOHAND ||
789 regs->regs[2] == ERESTARTSYS ||
790 regs->regs[2] == ERESTARTNOINTR) {
791 regs->regs[7] = regs->regs[26];
792 regs->cp0_epc -= 8;
793 }
794 if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
795 regs->regs[2] = __NR_O32_restart_syscall;
796 regs->regs[7] = regs->regs[26];
797 regs->cp0_epc -= 4;
798 }
799 regs->regs[0] = 0; /* Don't deal with this again. */
800 }
801
802 /*
803 * If there's no signal to deliver, we just put the saved sigmask
804 * back
805 */
806 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
807 clear_thread_flag(TIF_RESTORE_SIGMASK);
808 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
809 }
810}
811 715
812asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, 716asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
813 struct sigaction32 __user *oact, 717 struct sigaction32 __user *oact,
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 7ca2a078841f..ecf1f7ecaad9 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -29,6 +29,7 @@
29#include <linux/compat.h> 29#include <linux/compat.h>
30#include <linux/bitops.h> 30#include <linux/bitops.h>
31 31
32#include <asm/abi.h>
32#include <asm/asm.h> 33#include <asm/asm.h>
33#include <asm/cacheflush.h> 34#include <asm/cacheflush.h>
34#include <asm/compat-signal.h> 35#include <asm/compat-signal.h>
@@ -169,7 +170,7 @@ badframe:
169 force_sig(SIGSEGV, current); 170 force_sig(SIGSEGV, current);
170} 171}
171 172
172int setup_rt_frame_n32(struct k_sigaction * ka, 173static int setup_rt_frame_n32(struct k_sigaction * ka,
173 struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) 174 struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
174{ 175{
175 struct rt_sigframe_n32 __user *frame; 176 struct rt_sigframe_n32 __user *frame;
@@ -228,3 +229,8 @@ give_sigsegv:
228 force_sigsegv(signr, current); 229 force_sigsegv(signr, current);
229 return -EFAULT; 230 return -EFAULT;
230} 231}
232
233struct mips_abi mips_abi_n32 = {
234 .setup_rt_frame = setup_rt_frame_n32,
235 .restart = __NR_N32_restart_syscall
236};
diff --git a/include/asm-mips/abi.h b/include/asm-mips/abi.h
index 1ce0518ace2e..1dd74fbdc09b 100644
--- a/include/asm-mips/abi.h
+++ b/include/asm-mips/abi.h
@@ -13,13 +13,13 @@
13#include <asm/siginfo.h> 13#include <asm/siginfo.h>
14 14
15struct mips_abi { 15struct mips_abi {
16 void (* const do_signal)(struct pt_regs *regs);
17 int (* const setup_frame)(struct k_sigaction * ka, 16 int (* const setup_frame)(struct k_sigaction * ka,
18 struct pt_regs *regs, int signr, 17 struct pt_regs *regs, int signr,
19 sigset_t *set); 18 sigset_t *set);
20 int (* const setup_rt_frame)(struct k_sigaction * ka, 19 int (* const setup_rt_frame)(struct k_sigaction * ka,
21 struct pt_regs *regs, int signr, 20 struct pt_regs *regs, int signr,
22 sigset_t *set, siginfo_t *info); 21 sigset_t *set, siginfo_t *info);
22 const unsigned long restart;
23}; 23};
24 24
25#endif /* _ASM_ABI_H */ 25#endif /* _ASM_ABI_H */
diff --git a/include/asm-mips/compat-signal.h b/include/asm-mips/compat-signal.h
index 20ac29ffa7c8..6599a901b63e 100644
--- a/include/asm-mips/compat-signal.h
+++ b/include/asm-mips/compat-signal.h
@@ -5,6 +5,9 @@
5#include <linux/compat.h> 5#include <linux/compat.h>
6#include <linux/compiler.h> 6#include <linux/compiler.h>
7 7
8#include <asm/signal.h>
9#include <asm/siginfo.h>
10
8#include <asm/uaccess.h> 11#include <asm/uaccess.h>
9 12
10static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d, 13static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
diff --git a/include/asm-mips/signal.h b/include/asm-mips/signal.h
index 8b391a2f0814..7a28989f7ee3 100644
--- a/include/asm-mips/signal.h
+++ b/include/asm-mips/signal.h
@@ -137,23 +137,6 @@ typedef struct sigaltstack {
137 137
138#define ptrace_signal_deliver(regs, cookie) do { } while (0) 138#define ptrace_signal_deliver(regs, cookie) do { } while (0)
139 139
140struct pt_regs;
141extern void do_signal(struct pt_regs *regs);
142extern void do_signal32(struct pt_regs *regs);
143
144extern int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
145 int signr, sigset_t *set);
146extern int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
147 int signr, sigset_t *set, siginfo_t *info);
148
149extern int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
150 int signr, sigset_t *set);
151extern int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
152 int signr, sigset_t *set, siginfo_t *info);
153
154extern int setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs,
155 int signr, sigset_t *set, siginfo_t *info);
156
157#endif /* __KERNEL__ */ 140#endif /* __KERNEL__ */
158 141
159#endif /* _ASM_SIGNAL_H */ 142#endif /* _ASM_SIGNAL_H */