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

Commit cfd60c07 authored by Al Viro's avatar Al Viro
Browse files

alpha: pass k_sigaction and siginfo_t using ksignal pointer



... and use the new helpers

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent d64008a8
Loading
Loading
Loading
Loading
+45 −66
Original line number Diff line number Diff line
@@ -272,12 +272,9 @@ give_sigsegv:
 */

static inline void __user *
get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
{
	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
		sp = current->sas_ss_sp + current->sas_ss_size;

	return (void __user *)((sp - frame_size) & -32ul);
	return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul);
}

static long
@@ -338,14 +335,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
}

static int
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
	    struct pt_regs *regs)
setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
	unsigned long oldsp, r26, err = 0;
	struct sigframe __user *frame;

	oldsp = rdusp();
	frame = get_sigframe(ka, oldsp, sizeof(*frame));
	frame = get_sigframe(ksig, oldsp, sizeof(*frame));
	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		return -EFAULT;

@@ -355,9 +351,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,

	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
	if (ka->ka_restorer) {
		r26 = (unsigned long) ka->ka_restorer;
	} else {
	r26 = (unsigned long) ksig->ka.ka_restorer;
	if (!r26) {
		err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
		err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
		err |= __put_user(INSN_CALLSYS, frame->retcode+2);
@@ -371,8 +366,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,

	/* "Return" to the handler */
	regs->r26 = r26;
	regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
	regs->r16 = sig;			/* a0: signal number */
	regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
	regs->r16 = ksig->sig;			/* a0: signal number */
	regs->r17 = 0;				/* a1: exception code */
	regs->r18 = (unsigned long) &frame->sc;	/* a2: sigcontext pointer */
	wrusp((unsigned long) frame);
@@ -385,18 +380,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
}

static int
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
	       sigset_t *set, struct pt_regs *regs)
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
{
	unsigned long oldsp, r26, err = 0;
	struct rt_sigframe __user *frame;

	oldsp = rdusp();
	frame = get_sigframe(ka, oldsp, sizeof(*frame));
	frame = get_sigframe(ksig, oldsp, sizeof(*frame));
	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		return -EFAULT;

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

	/* Create the ucontext.  */
	err |= __put_user(0, &frame->uc.uc_flags);
@@ -411,9 +405,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,

	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
	if (ka->ka_restorer) {
		r26 = (unsigned long) ka->ka_restorer;
	} else {
	r26 = (unsigned long) ksig->ka.ka_restorer;
	if (!r26) {
		err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
		err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
				  frame->retcode+1);
@@ -427,8 +420,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,

	/* "Return" to the handler */
	regs->r26 = r26;
	regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler;
	regs->r16 = sig;			  /* a0: signal number */
	regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
	regs->r16 = ksig->sig;			  /* a0: signal number */
	regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
	regs->r18 = (unsigned long) &frame->uc;	  /* a2: ucontext pointer */
	wrusp((unsigned long) frame);
@@ -446,22 +439,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 * OK, we're invoking a handler.
 */
static inline void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
	      struct pt_regs * regs)
handle_signal(struct ksignal *ksig, struct pt_regs *regs)
{
	sigset_t *oldset = sigmask_to_save();
	int ret;

	if (ka->sa.sa_flags & SA_SIGINFO)
		ret = setup_rt_frame(sig, ka, info, oldset, regs);
	if (ksig->ka.sa.sa_flags & SA_SIGINFO)
		ret = setup_rt_frame(ksig, oldset, regs);
	else
		ret = setup_frame(sig, ka, oldset, regs);
		ret = setup_frame(ksig, oldset, regs);

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

static inline void
@@ -504,27 +492,19 @@ syscall_restart(unsigned long r0, unsigned long r19,
static void
do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
{
	siginfo_t info;
	int signr;
	unsigned long single_stepping = ptrace_cancel_bpt(current);
	struct k_sigaction ka;
	struct ksignal ksig;

	/* This lets the debugger run, ... */
	signr = get_signal_to_deliver(&info, &ka, regs, NULL);

	if (get_signal(&ksig)) {
		/* ... so re-check the single stepping. */
		single_stepping |= ptrace_cancel_bpt(current);

	if (signr > 0) {
		/* Whee!  Actually deliver the signal.  */
		if (r0)
			syscall_restart(r0, r19, regs, &ka);
		handle_signal(signr, &ka, &info, regs);
		if (single_stepping) 
			ptrace_set_bpt(current); /* re-set bpt */
		return;
	}

			syscall_restart(r0, r19, regs, &ksig.ka);
		handle_signal(&ksig, regs);
	} else {
		single_stepping |= ptrace_cancel_bpt(current);
		if (r0) {
			switch (regs->r0) {
			case ERESTARTNOHAND:
@@ -536,15 +516,14 @@ do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
				regs->pc -= 4;
				break;
			case ERESTART_RESTARTBLOCK:
			/* Force v0 to the restart syscall and reply.  */
				/* Set v0 to the restart_syscall and replay */
				regs->r0 = __NR_restart_syscall;
				regs->pc -= 4;
				break;
			}
		}

	/* If there's no signal to deliver, we just restore the saved mask.  */
		restore_saved_sigmask();
	}
	if (single_stepping)
		ptrace_set_bpt(current);	/* re-set breakpoint */
}