Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+0 −33
Original line number Original line Diff line number Diff line
@@ -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)
	}
	}
}
}


/*
 * 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)
+13 −5
Original line number Original line Diff line number Diff line
@@ -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,
}
}
#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,
	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,
	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)
			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,
{
{
	/* 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);
}
}
+11 −107
Original line number Original line Diff line number Diff line
@@ -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,
	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,
	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)
{
	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
 * o32 compatibility on 64-bit kernels, without DSP ASE
	 * dies here!!!  The li instruction, a single machine instruction,
	 * must directly be followed by the syscall instruction.
 */
 */
	if (regs->regs[0]) {
struct mips_abi mips_abi_32 = {
		if (regs->regs[2] == ERESTARTNOHAND ||
	.setup_frame	= setup_frame_32,
		    regs->regs[2] == ERESTARTSYS ||
	.setup_rt_frame	= setup_rt_frame_32,
		    regs->regs[2] == ERESTARTNOINTR) {
	.restart	= __NR_O32_restart_syscall
			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)) {
		clear_thread_flag(TIF_RESTORE_SIGMASK);
		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
	}
}


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,
+7 −1
Original line number Original line Diff line number Diff line
@@ -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)
	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,
	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
};
+1 −1
Original line number Original line Diff line number Diff line
@@ -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 */
Loading