diff options
| -rw-r--r-- | arch/mips/kernel/process.c | 33 | ||||
| -rw-r--r-- | arch/mips/kernel/signal.c | 18 | ||||
| -rw-r--r-- | arch/mips/kernel/signal32.c | 118 | ||||
| -rw-r--r-- | arch/mips/kernel/signal_n32.c | 8 | ||||
| -rw-r--r-- | include/asm-mips/abi.h | 2 | ||||
| -rw-r--r-- | include/asm-mips/compat-signal.h | 3 | ||||
| -rw-r--r-- | include/asm-mips/signal.h | 17 |
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 | */ | ||
| 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) |
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 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 | ||
| 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/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 | ||
| 15 | struct mips_abi { | 15 | struct 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 | ||
| 10 | static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d, | 13 | static 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 | ||
| 140 | struct pt_regs; | ||
| 141 | extern void do_signal(struct pt_regs *regs); | ||
| 142 | extern void do_signal32(struct pt_regs *regs); | ||
| 143 | |||
| 144 | extern int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, | ||
| 145 | int signr, sigset_t *set); | ||
| 146 | extern int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, | ||
| 147 | int signr, sigset_t *set, siginfo_t *info); | ||
| 148 | |||
| 149 | extern int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | ||
| 150 | int signr, sigset_t *set); | ||
| 151 | extern int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, | ||
| 152 | int signr, sigset_t *set, siginfo_t *info); | ||
| 153 | |||
| 154 | extern 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 */ |
