Commit 151fd6ac authored by Ralf Baechle's avatar Ralf Baechle

[MIPS] signals: Share even more code.

native and compat do_signal and handle_signal are identical and can easily
be unified.
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 38201fb2
...@@ -26,7 +26,6 @@ ...@@ -26,7 +26,6 @@
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <asm/abi.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/cpu.h> #include <asm/cpu.h>
#include <asm/dsp.h> #include <asm/dsp.h>
...@@ -66,38 +65,6 @@ ATTRIB_NORET void cpu_idle(void) ...@@ -66,38 +65,6 @@ ATTRIB_NORET void cpu_idle(void)
} }
} }
/*
* Native o32 and N64 ABI without DSP ASE
*/
struct mips_abi mips_abi = {
.do_signal = do_signal,
#ifdef CONFIG_TRAD_SIGNALS
.setup_frame = setup_frame,
#endif
.setup_rt_frame = setup_rt_frame
};
#ifdef CONFIG_MIPS32_O32
/*
* o32 compatibility on 64-bit kernels, without DSP ASE
*/
struct mips_abi mips_abi_32 = {
.do_signal = do_signal32,
.setup_frame = setup_frame_32,
.setup_rt_frame = setup_rt_frame_32
};
#endif /* CONFIG_MIPS32_O32 */
#ifdef CONFIG_MIPS32_N32
/*
* N32 on 64-bit kernels, without DSP ASE
*/
struct mips_abi mips_abi_n32 = {
.do_signal = do_signal,
.setup_rt_frame = setup_rt_frame_n32
};
#endif /* CONFIG_MIPS32_N32 */
asmlinkage void ret_from_fork(void); asmlinkage void ret_from_fork(void);
void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
......
...@@ -398,7 +398,7 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) ...@@ -398,7 +398,7 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
} }
#ifdef CONFIG_TRAD_SIGNALS #ifdef CONFIG_TRAD_SIGNALS
int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, static int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set) int signr, sigset_t *set)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
...@@ -443,7 +443,7 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -443,7 +443,7 @@ int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
} }
#endif #endif
int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, static int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set, siginfo_t *info) int signr, sigset_t *set, siginfo_t *info)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
...@@ -501,6 +501,14 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -501,6 +501,14 @@ int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
return -EFAULT; return -EFAULT;
} }
struct mips_abi mips_abi = {
#ifdef CONFIG_TRAD_SIGNALS
.setup_frame = setup_frame,
#endif
.setup_rt_frame = setup_rt_frame,
.restart = __NR_restart_syscall
};
static int handle_signal(unsigned long sig, siginfo_t *info, static int handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
{ {
...@@ -539,7 +547,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info, ...@@ -539,7 +547,7 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
return ret; return ret;
} }
void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset; sigset_t *oldset;
...@@ -589,7 +597,7 @@ void do_signal(struct pt_regs *regs) ...@@ -589,7 +597,7 @@ void do_signal(struct pt_regs *regs)
regs->cp0_epc -= 8; regs->cp0_epc -= 8;
} }
if (regs->regs[2] == ERESTART_RESTARTBLOCK) { if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
regs->regs[2] = __NR_restart_syscall; regs->regs[2] = current->thread.abi->restart;
regs->regs[7] = regs->regs[26]; regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 4; regs->cp0_epc -= 4;
} }
...@@ -615,5 +623,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, ...@@ -615,5 +623,5 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
{ {
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
current->thread.abi->do_signal(regs); do_signal(regs);
} }
...@@ -598,7 +598,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) ...@@ -598,7 +598,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, static int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set) int signr, sigset_t *set)
{ {
struct sigframe32 __user *frame; struct sigframe32 __user *frame;
...@@ -644,7 +644,7 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -644,7 +644,7 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
return -EFAULT; return -EFAULT;
} }
int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, static int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set, siginfo_t *info) int signr, sigset_t *set, siginfo_t *info)
{ {
struct rt_sigframe32 __user *frame; struct rt_sigframe32 __user *frame;
...@@ -704,110 +704,14 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs, ...@@ -704,110 +704,14 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
return -EFAULT; return -EFAULT;
} }
static inline int handle_signal(unsigned long sig, siginfo_t *info, /*
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs * regs) * o32 compatibility on 64-bit kernels, without DSP ASE
{
int ret;
switch (regs->regs[0]) {
case ERESTART_RESTARTBLOCK:
case ERESTARTNOHAND:
regs->regs[2] = EINTR;
break;
case ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) {
regs->regs[2] = EINTR;
break;
}
/* fallthrough */
case ERESTARTNOINTR: /* Userland will reload $v0. */
regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 8;
}
regs->regs[0] = 0; /* Don't deal with this again. */
if (ka->sa.sa_flags & SA_SIGINFO)
ret = current->thread.abi->setup_rt_frame(ka, regs, sig, oldset, info);
else
ret = current->thread.abi->setup_frame(ka, regs, sig, oldset);
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
return ret;
}
void do_signal32(struct pt_regs *regs)
{
struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info;
int signr;
/*
* We want the common case to go fast, which is why we may in certain
* cases get here from kernel mode. Just return without doing anything
* if so.
*/
if (!user_mode(regs))
return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return;
}
/*
* Who's code doesn't conform to the restartable syscall convention
* dies here!!! The li instruction, a single machine instruction,
* must directly be followed by the syscall instruction.
*/
if (regs->regs[0]) {
if (regs->regs[2] == ERESTARTNOHAND ||
regs->regs[2] == ERESTARTSYS ||
regs->regs[2] == ERESTARTNOINTR) {
regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 8;
}
if (regs->regs[2] == ERESTART_RESTARTBLOCK) {
regs->regs[2] = __NR_O32_restart_syscall;
regs->regs[7] = regs->regs[26];
regs->cp0_epc -= 4;
}
regs->regs[0] = 0; /* Don't deal with this again. */
}
/*
* If there's no signal to deliver, we just put the saved sigmask
* back
*/ */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { struct mips_abi mips_abi_32 = {
clear_thread_flag(TIF_RESTORE_SIGMASK); .setup_frame = setup_frame_32,
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); .setup_rt_frame = setup_rt_frame_32,
} .restart = __NR_O32_restart_syscall
} };
asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, asmlinkage int sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
struct sigaction32 __user *oact, struct sigaction32 __user *oact,
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <asm/abi.h>
#include <asm/asm.h> #include <asm/asm.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/compat-signal.h> #include <asm/compat-signal.h>
...@@ -169,7 +170,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) ...@@ -169,7 +170,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
int setup_rt_frame_n32(struct k_sigaction * ka, static int setup_rt_frame_n32(struct k_sigaction * ka,
struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
{ {
struct rt_sigframe_n32 __user *frame; struct rt_sigframe_n32 __user *frame;
...@@ -228,3 +229,8 @@ int setup_rt_frame_n32(struct k_sigaction * ka, ...@@ -228,3 +229,8 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
force_sigsegv(signr, current); force_sigsegv(signr, current);
return -EFAULT; return -EFAULT;
} }
struct mips_abi mips_abi_n32 = {
.setup_rt_frame = setup_rt_frame_n32,
.restart = __NR_N32_restart_syscall
};
...@@ -13,13 +13,13 @@ ...@@ -13,13 +13,13 @@
#include <asm/siginfo.h> #include <asm/siginfo.h>
struct mips_abi { struct mips_abi {
void (* const do_signal)(struct pt_regs *regs);
int (* const setup_frame)(struct k_sigaction * ka, int (* const setup_frame)(struct k_sigaction * ka,
struct pt_regs *regs, int signr, struct pt_regs *regs, int signr,
sigset_t *set); sigset_t *set);
int (* const setup_rt_frame)(struct k_sigaction * ka, int (* const setup_rt_frame)(struct k_sigaction * ka,
struct pt_regs *regs, int signr, struct pt_regs *regs, int signr,
sigset_t *set, siginfo_t *info); sigset_t *set, siginfo_t *info);
const unsigned long restart;
}; };
#endif /* _ASM_ABI_H */ #endif /* _ASM_ABI_H */
...@@ -5,6 +5,9 @@ ...@@ -5,6 +5,9 @@
#include <linux/compat.h> #include <linux/compat.h>
#include <linux/compiler.h> #include <linux/compiler.h>
#include <asm/signal.h>
#include <asm/siginfo.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d, static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d,
......
...@@ -137,23 +137,6 @@ typedef struct sigaltstack { ...@@ -137,23 +137,6 @@ typedef struct sigaltstack {
#define ptrace_signal_deliver(regs, cookie) do { } while (0) #define ptrace_signal_deliver(regs, cookie) do { } while (0)
struct pt_regs;
extern void do_signal(struct pt_regs *regs);
extern void do_signal32(struct pt_regs *regs);
extern int setup_frame(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set);
extern int setup_rt_frame(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set, siginfo_t *info);
extern int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set);
extern int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set, siginfo_t *info);
extern int setup_rt_frame_n32(struct k_sigaction * ka, struct pt_regs *regs,
int signr, sigset_t *set, siginfo_t *info);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_SIGNAL_H */ #endif /* _ASM_SIGNAL_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment