diff options
Diffstat (limited to 'arch/mips/kernel')
-rw-r--r-- | arch/mips/kernel/Makefile | 4 | ||||
-rw-r--r-- | arch/mips/kernel/cpu-probe.c | 1 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 35 | ||||
-rw-r--r-- | arch/mips/kernel/signal.c | 18 | ||||
-rw-r--r-- | arch/mips/kernel/signal32.c | 122 | ||||
-rw-r--r-- | arch/mips/kernel/signal_n32.c | 8 | ||||
-rw-r--r-- | arch/mips/kernel/traps.c | 10 |
7 files changed, 40 insertions, 158 deletions
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 1bf2c8448912..8faf1b40cd66 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile | |||
@@ -53,9 +53,9 @@ obj-$(CONFIG_MIPS_BOARDS_GEN) += irq-msc01.o | |||
53 | obj-$(CONFIG_32BIT) += scall32-o32.o | 53 | obj-$(CONFIG_32BIT) += scall32-o32.o |
54 | obj-$(CONFIG_64BIT) += scall64-64.o | 54 | obj-$(CONFIG_64BIT) += scall64-64.o |
55 | obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o | 55 | obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o |
56 | obj-$(CONFIG_MIPS32_COMPAT) += linux32.o signal32.o | 56 | obj-$(CONFIG_MIPS32_COMPAT) += linux32.o ptrace32.o signal32.o |
57 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o | 57 | obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o |
58 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o | 58 | obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o |
59 | 59 | ||
60 | obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o | 60 | obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o |
61 | obj-$(CONFIG_PROC_FS) += proc.o | 61 | obj-$(CONFIG_PROC_FS) += proc.o |
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index f59ef271d247..50ed6d58ae71 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/ptrace.h> | 16 | #include <linux/ptrace.h> |
17 | #include <linux/stddef.h> | 17 | #include <linux/stddef.h> |
18 | 18 | ||
19 | #include <asm/bugs.h> | ||
19 | #include <asm/cpu.h> | 20 | #include <asm/cpu.h> |
20 | #include <asm/fpu.h> | 21 | #include <asm/fpu.h> |
21 | #include <asm/mipsregs.h> | 22 | #include <asm/mipsregs.h> |
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index 04e5b38d327d..a669089e4672 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 | */ | ||
72 | struct 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 | */ | ||
84 | struct 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 | */ | ||
95 | struct 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 | |||
101 | asmlinkage void ret_from_fork(void); | 68 | asmlinkage void ret_from_fork(void); |
102 | 69 | ||
103 | void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) | 70 | void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) |
@@ -246,7 +213,7 @@ int dump_task_fpu (struct task_struct *t, elf_fpregset_t *fpr) | |||
246 | /* | 213 | /* |
247 | * Create a kernel thread | 214 | * Create a kernel thread |
248 | */ | 215 | */ |
249 | ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) | 216 | static ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) |
250 | { | 217 | { |
251 | do_exit(fn(arg)); | 218 | do_exit(fn(arg)); |
252 | } | 219 | } |
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 |
401 | int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | 401 | static 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 | ||
446 | int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | 446 | static 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 | ||
504 | struct 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 | |||
504 | static int handle_signal(unsigned long sig, siginfo_t *info, | 512 | static 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 | ||
542 | void do_signal(struct pt_regs *regs) | 550 | static 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 c28cb21514c8..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 | ||
@@ -150,7 +150,7 @@ struct sigframe32 { | |||
150 | u32 sf_ass[4]; /* argument save space for o32 */ | 150 | u32 sf_ass[4]; /* argument save space for o32 */ |
151 | u32 sf_code[2]; /* signal trampoline */ | 151 | u32 sf_code[2]; /* signal trampoline */ |
152 | struct sigcontext32 sf_sc; | 152 | struct sigcontext32 sf_sc; |
153 | sigset_t sf_mask; | 153 | compat_sigset_t sf_mask; |
154 | }; | 154 | }; |
155 | 155 | ||
156 | struct rt_sigframe32 { | 156 | struct rt_sigframe32 { |
@@ -166,7 +166,7 @@ struct sigframe32 { | |||
166 | u32 sf_ass[4]; /* argument save space for o32 */ | 166 | u32 sf_ass[4]; /* argument save space for o32 */ |
167 | u32 sf_pad[2]; | 167 | u32 sf_pad[2]; |
168 | struct sigcontext32 sf_sc; /* hw context */ | 168 | struct sigcontext32 sf_sc; /* hw context */ |
169 | sigset_t sf_mask; | 169 | compat_sigset_t sf_mask; |
170 | u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */ | 170 | u32 sf_code[8] ____cacheline_aligned; /* signal trampoline */ |
171 | }; | 171 | }; |
172 | 172 | ||
@@ -598,7 +598,7 @@ badframe: | |||
598 | force_sig(SIGSEGV, current); | 598 | force_sig(SIGSEGV, current); |
599 | } | 599 | } |
600 | 600 | ||
601 | int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 601 | static 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 | ||
647 | int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | 647 | static 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 | ||
707 | static 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; | 710 | struct 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(¤t->sighand->siglock); | ||
736 | sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); | ||
737 | if (!(ka->sa.sa_flags & SA_NODEFER)) | ||
738 | sigaddset(¤t->blocked,sig); | ||
739 | recalc_sigpending(); | ||
740 | spin_unlock_irq(¤t->sighand->siglock); | ||
741 | |||
742 | return ret; | ||
743 | } | ||
744 | |||
745 | void 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 = ¤t->saved_sigmask; | ||
762 | else | ||
763 | oldset = ¤t->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, ¤t->saved_sigmask, NULL); | ||
809 | } | ||
810 | } | ||
811 | 715 | ||
812 | asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, | 716 | asmlinkage 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 | ||
172 | int setup_rt_frame_n32(struct k_sigaction * ka, | 173 | static 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 | |||
233 | struct mips_abi mips_abi_n32 = { | ||
234 | .setup_rt_frame = setup_rt_frame_n32, | ||
235 | .restart = __NR_N32_restart_syscall | ||
236 | }; | ||
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 2a932cada244..f663c63d5dd3 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c | |||
@@ -340,13 +340,9 @@ NORET_TYPE void ATTRIB_NORET die(const char * str, struct pt_regs * regs) | |||
340 | extern const struct exception_table_entry __start___dbe_table[]; | 340 | extern const struct exception_table_entry __start___dbe_table[]; |
341 | extern const struct exception_table_entry __stop___dbe_table[]; | 341 | extern const struct exception_table_entry __stop___dbe_table[]; |
342 | 342 | ||
343 | void __declare_dbe_table(void) | 343 | __asm__( |
344 | { | 344 | " .section __dbe_table, \"a\"\n" |
345 | __asm__ __volatile__( | 345 | " .previous \n"); |
346 | ".section\t__dbe_table,\"a\"\n\t" | ||
347 | ".previous" | ||
348 | ); | ||
349 | } | ||
350 | 346 | ||
351 | /* Given an address, look for it in the exception tables. */ | 347 | /* Given an address, look for it in the exception tables. */ |
352 | static const struct exception_table_entry *search_dbe_tables(unsigned long addr) | 348 | static const struct exception_table_entry *search_dbe_tables(unsigned long addr) |