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

Commit 7e243643 authored by Al Viro's avatar Al Viro
Browse files

arm: switch to struct ksignal * passing



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent cfd60c07
Loading
Loading
Loading
Loading
+47 −61
Original line number Original line Diff line number Diff line
@@ -318,17 +318,11 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
}
}


static inline void __user *
static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize)
{
{
	unsigned long sp = regs->ARM_sp;
	unsigned long sp = sigsp(regs->ARM_sp, ksig);
	void __user *frame;
	void __user *frame;


	/*
	 * This is the X/Open sanctioned signal stack switching.
	 */
	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
		sp = current->sas_ss_sp + current->sas_ss_size;

	/*
	/*
	 * ATPCS B01 mandates 8-byte alignment
	 * ATPCS B01 mandates 8-byte alignment
	 */
	 */
@@ -343,11 +337,22 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
	return frame;
	return frame;
}
}


/*
 * translate the signal
 */
static inline int map_sig(int sig)
{
	struct thread_info *thread = current_thread_info();
	if (sig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
		sig = thread->exec_domain->signal_invmap[sig];
	return sig;
}

static int
static int
setup_return(struct pt_regs *regs, struct k_sigaction *ka,
setup_return(struct pt_regs *regs, struct ksignal *ksig,
	     unsigned long __user *rc, void __user *frame, int usig)
	     unsigned long __user *rc, void __user *frame)
{
{
	unsigned long handler = (unsigned long)ka->sa.sa_handler;
	unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
	unsigned long retcode;
	unsigned long retcode;
	int thumb = 0;
	int thumb = 0;
	unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
	unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
@@ -357,7 +362,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
	/*
	/*
	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
	 */
	 */
	if (ka->sa.sa_flags & SA_THIRTYTWO)
	if (ksig->ka.sa.sa_flags & SA_THIRTYTWO)
		cpsr = (cpsr & ~MODE_MASK) | USR_MODE;
		cpsr = (cpsr & ~MODE_MASK) | USR_MODE;


#ifdef CONFIG_ARM_THUMB
#ifdef CONFIG_ARM_THUMB
@@ -379,12 +384,12 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
	}
	}
#endif
#endif


	if (ka->sa.sa_flags & SA_RESTORER) {
	if (ksig->ka.sa.sa_flags & SA_RESTORER) {
		retcode = (unsigned long)ka->sa.sa_restorer;
		retcode = (unsigned long)ksig->ka.sa.sa_restorer;
	} else {
	} else {
		unsigned int idx = thumb << 1;
		unsigned int idx = thumb << 1;


		if (ka->sa.sa_flags & SA_SIGINFO)
		if (ksig->ka.sa.sa_flags & SA_SIGINFO)
			idx += 3;
			idx += 3;


		if (__put_user(sigreturn_codes[idx],   rc) ||
		if (__put_user(sigreturn_codes[idx],   rc) ||
@@ -409,7 +414,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
		}
		}
	}
	}


	regs->ARM_r0 = usig;
	regs->ARM_r0 = map_sig(ksig->sig);
	regs->ARM_sp = (unsigned long)frame;
	regs->ARM_sp = (unsigned long)frame;
	regs->ARM_lr = retcode;
	regs->ARM_lr = retcode;
	regs->ARM_pc = handler;
	regs->ARM_pc = handler;
@@ -419,9 +424,9 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
}
}


static int
static int
setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs)
setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
{
	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
	struct sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame));
	int err = 0;
	int err = 0;


	if (!frame)
	if (!frame)
@@ -434,22 +439,21 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg


	err |= setup_sigframe(frame, regs, set);
	err |= setup_sigframe(frame, regs, set);
	if (err == 0)
	if (err == 0)
		err = setup_return(regs, ka, frame->retcode, frame, usig);
		err = setup_return(regs, ksig, frame->retcode, frame);


	return err;
	return err;
}
}


static int
static int
setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
	       sigset_t *set, struct pt_regs *regs)
{
{
	struct rt_sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
	struct rt_sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame));
	int err = 0;
	int err = 0;


	if (!frame)
	if (!frame)
		return 1;
		return 1;


	err |= copy_siginfo_to_user(&frame->info, info);
	err |= copy_siginfo_to_user(&frame->info, &ksig->info);


	__put_user_error(0, &frame->sig.uc.uc_flags, err);
	__put_user_error(0, &frame->sig.uc.uc_flags, err);
	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
	__put_user_error(NULL, &frame->sig.uc.uc_link, err);
@@ -457,7 +461,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
	err |= __save_altstack(&frame->sig.uc.uc_stack, regs->ARM_sp);
	err |= __save_altstack(&frame->sig.uc.uc_stack, regs->ARM_sp);
	err |= setup_sigframe(&frame->sig, regs, set);
	err |= setup_sigframe(&frame->sig, regs, set);
	if (err == 0)
	if (err == 0)
		err = setup_return(regs, ka, frame->sig.retcode, frame, usig);
		err = setup_return(regs, ksig, frame->sig.retcode, frame);


	if (err == 0) {
	if (err == 0) {
		/*
		/*
@@ -475,40 +479,25 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
/*
/*
 * OK, we're invoking a handler
 * OK, we're invoking a handler
 */	
 */	
static void
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
handle_signal(unsigned long sig, struct k_sigaction *ka,
	      siginfo_t *info, struct pt_regs *regs)
{
{
	struct thread_info *thread = current_thread_info();
	struct task_struct *tsk = current;
	sigset_t *oldset = sigmask_to_save();
	sigset_t *oldset = sigmask_to_save();
	int usig = sig;
	int ret;
	int ret;


	/*
	 * translate the signal
	 */
	if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
		usig = thread->exec_domain->signal_invmap[usig];

	/*
	/*
	 * Set up the stack frame
	 * Set up the stack frame
	 */
	 */
	if (ka->sa.sa_flags & SA_SIGINFO)
	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
		ret = setup_rt_frame(usig, ka, info, oldset, regs);
		ret = setup_rt_frame(ksig, oldset, regs);
	else
	else
		ret = setup_frame(usig, ka, oldset, regs);
		ret = setup_frame(ksig, oldset, regs);


	/*
	/*
	 * Check that the resulting registers are actually sane.
	 * Check that the resulting registers are actually sane.
	 */
	 */
	ret |= !valid_user_regs(regs);
	ret |= !valid_user_regs(regs);


	if (ret != 0) {
	signal_setup_done(ret, ksig, 0);
		force_sigsegv(sig, tsk);
		return;
	}
	signal_delivered(sig, info, ka, regs, 0);
}
}


/*
/*
@@ -523,9 +512,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
static int do_signal(struct pt_regs *regs, int syscall)
static int do_signal(struct pt_regs *regs, int syscall)
{
{
	unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
	unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
	struct k_sigaction ka;
	struct ksignal ksig;
	siginfo_t info;
	int signr;
	int restart = 0;
	int restart = 0;


	/*
	/*
@@ -557,34 +544,33 @@ static int do_signal(struct pt_regs *regs, int syscall)
	 * Get the signal to deliver.  When running under ptrace, at this
	 * Get the signal to deliver.  When running under ptrace, at this
	 * point the debugger may change all our registers ...
	 * point the debugger may change all our registers ...
	 */
	 */
	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
	/*
	/*
	 * Depending on the signal settings we may need to revert the
	 * Depending on the signal settings we may need to revert the
	 * decision to restart the system call.  But skip this if a
	 * decision to restart the system call.  But skip this if a
	 * debugger has chosen to restart at a different PC.
	 * debugger has chosen to restart at a different PC.
	 */
	 */
	if (regs->ARM_pc != restart_addr)
	if (get_signal(&ksig)) {
		restart = 0;
		/* handler */
	if (signr > 0) {
		if (unlikely(restart) && regs->ARM_pc == restart_addr) {
		if (unlikely(restart)) {
			if (retval == -ERESTARTNOHAND ||
			if (retval == -ERESTARTNOHAND ||
			    retval == -ERESTART_RESTARTBLOCK
			    retval == -ERESTART_RESTARTBLOCK
			    || (retval == -ERESTARTSYS
			    || (retval == -ERESTARTSYS
				&& !(ka.sa.sa_flags & SA_RESTART))) {
				&& !(ksig.ka.sa.sa_flags & SA_RESTART))) {
				regs->ARM_r0 = -EINTR;
				regs->ARM_r0 = -EINTR;
				regs->ARM_pc = continue_addr;
				regs->ARM_pc = continue_addr;
			}
			}
		}
		}

		handle_signal(&ksig, regs);
		handle_signal(signr, &ka, &info, regs);
	} else {
		return 0;
		/* no handler */
	}

		restore_saved_sigmask();
		restore_saved_sigmask();
	if (unlikely(restart))
		if (unlikely(restart) && regs->ARM_pc == restart_addr) {
			regs->ARM_pc = continue_addr;
			regs->ARM_pc = continue_addr;
			return restart;
			return restart;
		}
		}
	}
	return 0;
}


asmlinkage int
asmlinkage int
do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)