Commit cfd60c07 authored by Al Viro's avatar Al Viro

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
...@@ -272,12 +272,9 @@ do_rt_sigreturn(struct rt_sigframe __user *frame) ...@@ -272,12 +272,9 @@ do_rt_sigreturn(struct rt_sigframe __user *frame)
*/ */
static inline void __user * 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)) return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul);
sp = current->sas_ss_sp + current->sas_ss_size;
return (void __user *)((sp - frame_size) & -32ul);
} }
static long static long
...@@ -338,14 +335,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -338,14 +335,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
} }
static int static int
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
struct pt_regs *regs)
{ {
unsigned long oldsp, r26, err = 0; unsigned long oldsp, r26, err = 0;
struct sigframe __user *frame; struct sigframe __user *frame;
oldsp = rdusp(); oldsp = rdusp();
frame = get_sigframe(ka, oldsp, sizeof(*frame)); frame = get_sigframe(ksig, oldsp, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return -EFAULT; return -EFAULT;
...@@ -355,9 +351,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -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 /* Set up to return from userspace. If provided, use a stub
already in userspace. */ already in userspace. */
if (ka->ka_restorer) { r26 = (unsigned long) ksig->ka.ka_restorer;
r26 = (unsigned long) ka->ka_restorer; if (!r26) {
} else {
err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 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_LDI_R0+__NR_sigreturn, frame->retcode+1);
err |= __put_user(INSN_CALLSYS, frame->retcode+2); err |= __put_user(INSN_CALLSYS, frame->retcode+2);
...@@ -371,8 +366,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -371,8 +366,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
/* "Return" to the handler */ /* "Return" to the handler */
regs->r26 = r26; regs->r26 = r26;
regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
regs->r16 = sig; /* a0: signal number */ regs->r16 = ksig->sig; /* a0: signal number */
regs->r17 = 0; /* a1: exception code */ regs->r17 = 0; /* a1: exception code */
regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */ regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
wrusp((unsigned long) frame); wrusp((unsigned long) frame);
...@@ -385,18 +380,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -385,18 +380,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
} }
static int static int
setup_rt_frame(int sig, 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)
{ {
unsigned long oldsp, r26, err = 0; unsigned long oldsp, r26, err = 0;
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
oldsp = rdusp(); oldsp = rdusp();
frame = get_sigframe(ka, oldsp, sizeof(*frame)); frame = get_sigframe(ksig, oldsp, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return -EFAULT; return -EFAULT;
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_flags);
...@@ -411,9 +405,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -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 /* Set up to return from userspace. If provided, use a stub
already in userspace. */ already in userspace. */
if (ka->ka_restorer) { r26 = (unsigned long) ksig->ka.ka_restorer;
r26 = (unsigned long) ka->ka_restorer; if (!r26) {
} else {
err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn, err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
frame->retcode+1); frame->retcode+1);
...@@ -427,8 +420,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -427,8 +420,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* "Return" to the handler */ /* "Return" to the handler */
regs->r26 = r26; regs->r26 = r26;
regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
regs->r16 = sig; /* a0: signal number */ regs->r16 = ksig->sig; /* a0: signal number */
regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */ regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */
wrusp((unsigned long) frame); wrusp((unsigned long) frame);
...@@ -446,22 +439,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -446,22 +439,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* OK, we're invoking a handler. * OK, we're invoking a handler.
*/ */
static inline void static inline void
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct pt_regs * regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
if (ka->sa.sa_flags & SA_SIGINFO) if (ksig->ka.sa.sa_flags & SA_SIGINFO)
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(ksig, oldset, regs);
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(ksig, oldset, regs);
if (ret) { signal_setup_done(ret, ksig, 0);
force_sigsegv(sig, current);
return;
}
signal_delivered(sig, info, ka, regs, 0);
} }
static inline void static inline void
...@@ -504,47 +492,38 @@ syscall_restart(unsigned long r0, unsigned long r19, ...@@ -504,47 +492,38 @@ syscall_restart(unsigned long r0, unsigned long r19,
static void static void
do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) 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); unsigned long single_stepping = ptrace_cancel_bpt(current);
struct k_sigaction ka; struct ksignal ksig;
/* This lets the debugger run, ... */ /* This lets the debugger run, ... */
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
/* ... so re-check the single stepping. */
/* ... so re-check the single stepping. */ single_stepping |= ptrace_cancel_bpt(current);
single_stepping |= ptrace_cancel_bpt(current);
if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (r0) if (r0)
syscall_restart(r0, r19, regs, &ka); syscall_restart(r0, r19, regs, &ksig.ka);
handle_signal(signr, &ka, &info, regs); handle_signal(&ksig, regs);
if (single_stepping) } else {
ptrace_set_bpt(current); /* re-set bpt */ single_stepping |= ptrace_cancel_bpt(current);
return; if (r0) {
} switch (regs->r0) {
case ERESTARTNOHAND:
if (r0) { case ERESTARTSYS:
switch (regs->r0) { case ERESTARTNOINTR:
case ERESTARTNOHAND: /* Reset v0 and a3 and replay syscall. */
case ERESTARTSYS: regs->r0 = r0;
case ERESTARTNOINTR: regs->r19 = r19;
/* Reset v0 and a3 and replay syscall. */ regs->pc -= 4;
regs->r0 = r0; break;
regs->r19 = r19; case ERESTART_RESTARTBLOCK:
regs->pc -= 4; /* Set v0 to the restart_syscall and replay */
break; regs->r0 = __NR_restart_syscall;
case ERESTART_RESTARTBLOCK: regs->pc -= 4;
/* Force v0 to the restart syscall and reply. */ break;
regs->r0 = __NR_restart_syscall; }
regs->pc -= 4;
break;
} }
restore_saved_sigmask();
} }
/* If there's no signal to deliver, we just restore the saved mask. */
restore_saved_sigmask();
if (single_stepping) if (single_stepping)
ptrace_set_bpt(current); /* re-set breakpoint */ ptrace_set_bpt(current); /* re-set breakpoint */
} }
......
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