Commit 63b12bdb authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'signal-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/misc

Pull arch signal handling cleanup from Richard Weinberger:
 "This patch series moves all remaining archs to the get_signal(),
  signal_setup_done() and sigsp() functions.

  Currently these archs use open coded variants of the said functions.
  Further, unused parameters get removed from get_signal_to_deliver(),
  tracehook_signal_handler() and signal_delivered().

  At the end of the day we save around 500 lines of code."

* 'signal-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/misc: (43 commits)
  powerpc: Use sigsp()
  openrisc: Use sigsp()
  mn10300: Use sigsp()
  mips: Use sigsp()
  microblaze: Use sigsp()
  metag: Use sigsp()
  m68k: Use sigsp()
  m32r: Use sigsp()
  hexagon: Use sigsp()
  frv: Use sigsp()
  cris: Use sigsp()
  c6x: Use sigsp()
  blackfin: Use sigsp()
  avr32: Use sigsp()
  arm64: Use sigsp()
  arc: Use sigsp()
  sas_ss_flags: Remove nested ternary if
  Rip out get_signal_to_deliver()
  Clean up signal_delivered()
  tracehook_signal_handler: Remove sig, info, ka and regs
  ...
parents ad1f5caf 059ade65
...@@ -141,17 +141,13 @@ SYSCALL_DEFINE0(rt_sigreturn) ...@@ -141,17 +141,13 @@ SYSCALL_DEFINE0(rt_sigreturn)
/* /*
* Determine which stack to use.. * Determine which stack to use..
*/ */
static inline void __user *get_sigframe(struct k_sigaction *ka, static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs, struct pt_regs *regs,
unsigned long framesize) unsigned long framesize)
{ {
unsigned long sp = regs->sp; unsigned long sp = sigsp(regs->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;
/* No matter what happens, 'sp' must be word /* No matter what happens, 'sp' must be word
* aligned otherwise nasty things could happen * aligned otherwise nasty things could happen
*/ */
...@@ -179,14 +175,13 @@ static inline int map_sig(int sig) ...@@ -179,14 +175,13 @@ static inline int map_sig(int sig)
} }
static int static int
setup_rt_frame(int signo, 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 *sf; struct rt_sigframe __user *sf;
unsigned int magic = 0; unsigned int magic = 0;
int err = 0; int err = 0;
sf = get_sigframe(ka, regs, sizeof(struct rt_sigframe)); sf = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
if (!sf) if (!sf)
return 1; return 1;
...@@ -205,8 +200,8 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, ...@@ -205,8 +200,8 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
* #2: struct siginfo * #2: struct siginfo
* #3: struct ucontext (completely populated) * #3: struct ucontext (completely populated)
*/ */
if (unlikely(ka->sa.sa_flags & SA_SIGINFO)) { if (unlikely(ksig->ka.sa.sa_flags & SA_SIGINFO)) {
err |= copy_siginfo_to_user(&sf->info, info); err |= copy_siginfo_to_user(&sf->info, &ksig->info);
err |= __put_user(0, &sf->uc.uc_flags); err |= __put_user(0, &sf->uc.uc_flags);
err |= __put_user(NULL, &sf->uc.uc_link); err |= __put_user(NULL, &sf->uc.uc_link);
err |= __save_altstack(&sf->uc.uc_stack, regs->sp); err |= __save_altstack(&sf->uc.uc_stack, regs->sp);
...@@ -227,16 +222,16 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info, ...@@ -227,16 +222,16 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
return err; return err;
/* #1 arg to the user Signal handler */ /* #1 arg to the user Signal handler */
regs->r0 = map_sig(signo); regs->r0 = map_sig(ksig->sig);
/* setup PC of user space signal handler */ /* setup PC of user space signal handler */
regs->ret = (unsigned long)ka->sa.sa_handler; regs->ret = (unsigned long)ksig->ka.sa.sa_handler;
/* /*
* handler returns using sigreturn stub provided already by userpsace * handler returns using sigreturn stub provided already by userpsace
*/ */
BUG_ON(!(ka->sa.sa_flags & SA_RESTORER)); BUG_ON(!(ksig->ka.sa.sa_flags & SA_RESTORER));
regs->blink = (unsigned long)ka->sa.sa_restorer; regs->blink = (unsigned long)ksig->ka.sa.sa_restorer;
/* User Stack for signal handler will be above the frame just carved */ /* User Stack for signal handler will be above the frame just carved */
regs->sp = (unsigned long)sf; regs->sp = (unsigned long)sf;
...@@ -298,38 +293,30 @@ static void arc_restart_syscall(struct k_sigaction *ka, struct pt_regs *regs) ...@@ -298,38 +293,30 @@ static void arc_restart_syscall(struct k_sigaction *ka, struct pt_regs *regs)
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void
handle_signal(unsigned long 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;
/* Set up the stack frame */ /* Set up the stack frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(ksig, oldset, regs);
if (ret) signal_setup_done(ret, ksig, 0);
force_sigsegv(sig, current);
else
signal_delivered(sig, info, ka, regs, 0);
} }
void do_signal(struct pt_regs *regs) void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct ksignal ksig;
siginfo_t info;
int signr;
int restart_scall; int restart_scall;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
restart_scall = in_syscall(regs) && syscall_restartable(regs); restart_scall = in_syscall(regs) && syscall_restartable(regs);
if (signr > 0) { if (get_signal(&ksig)) {
if (restart_scall) { if (restart_scall) {
arc_restart_syscall(&ka, regs); arc_restart_syscall(&ksig.ka, regs);
syscall_wont_restart(regs); /* No more restarts */ syscall_wont_restart(regs); /* No more restarts */
} }
handle_signal(signr, &ka, &info, regs); handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -24,22 +24,21 @@ ...@@ -24,22 +24,21 @@
extern const compat_ulong_t aarch32_sigret_code[6]; extern const compat_ulong_t aarch32_sigret_code[6];
int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs); struct pt_regs *regs);
int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs); struct pt_regs *regs);
void compat_setup_restart_syscall(struct pt_regs *regs); void compat_setup_restart_syscall(struct pt_regs *regs);
#else #else
static inline int compat_setup_frame(int usid, struct k_sigaction *ka, static inline int compat_setup_frame(int usid, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs) sigset_t *set, struct pt_regs *regs)
{ {
return -ENOSYS; return -ENOSYS;
} }
static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka, static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
siginfo_t *info, sigset_t *set,
struct pt_regs *regs) struct pt_regs *regs)
{ {
return -ENOSYS; return -ENOSYS;
......
...@@ -209,19 +209,13 @@ static int setup_sigframe(struct rt_sigframe __user *sf, ...@@ -209,19 +209,13 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
return err; return err;
} }
static struct rt_sigframe __user *get_sigframe(struct k_sigaction *ka, static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs) struct pt_regs *regs)
{ {
unsigned long sp, sp_top; unsigned long sp, sp_top;
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
sp = sp_top = regs->sp; sp = sp_top = sigsp(regs->sp, ksig);
/*
* This is the X/Open sanctioned signal stack switching.
*/
if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
sp = (sp - sizeof(struct rt_sigframe)) & ~15; sp = (sp - sizeof(struct rt_sigframe)) & ~15;
frame = (struct rt_sigframe __user *)sp; frame = (struct rt_sigframe __user *)sp;
...@@ -253,13 +247,13 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, ...@@ -253,13 +247,13 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
regs->regs[30] = (unsigned long)sigtramp; regs->regs[30] = (unsigned long)sigtramp;
} }
static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs); frame = get_sigframe(ksig, regs);
if (!frame) if (!frame)
return 1; return 1;
...@@ -269,9 +263,9 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, ...@@ -269,9 +263,9 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
err |= setup_sigframe(frame, regs, set); err |= setup_sigframe(frame, regs, set);
if (err == 0) { if (err == 0) {
setup_return(regs, ka, frame, usig); setup_return(regs, &ksig->ka, frame, usig);
if (ka->sa.sa_flags & SA_SIGINFO) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->regs[1] = (unsigned long)&frame->info; regs->regs[1] = (unsigned long)&frame->info;
regs->regs[2] = (unsigned long)&frame->uc; regs->regs[2] = (unsigned long)&frame->uc;
} }
...@@ -291,13 +285,12 @@ static void setup_restart_syscall(struct pt_regs *regs) ...@@ -291,13 +285,12 @@ static void setup_restart_syscall(struct pt_regs *regs)
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void handle_signal(unsigned long sig, struct k_sigaction *ka, static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
siginfo_t *info, struct pt_regs *regs)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current; struct task_struct *tsk = current;
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int usig = sig; int usig = ksig->sig;
int ret; int ret;
/* /*
...@@ -310,13 +303,12 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -310,13 +303,12 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
* Set up the stack frame * Set up the stack frame
*/ */
if (is_compat_task()) { if (is_compat_task()) {
if (ka->sa.sa_flags & SA_SIGINFO) if (ksig->ka.sa.sa_flags & SA_SIGINFO)
ret = compat_setup_rt_frame(usig, ka, info, oldset, ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
regs);
else else
ret = compat_setup_frame(usig, ka, oldset, regs); ret = compat_setup_frame(usig, ksig, oldset, regs);
} else { } else {
ret = setup_rt_frame(usig, ka, info, oldset, regs); ret = setup_rt_frame(usig, ksig, oldset, regs);
} }
/* /*
...@@ -324,18 +316,14 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -324,18 +316,14 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
*/ */
ret |= !valid_user_regs(&regs->user_regs); ret |= !valid_user_regs(&regs->user_regs);
if (ret != 0) {
force_sigsegv(sig, tsk);
return;
}
/* /*
* Fast forward the stepping logic so we step into the signal * Fast forward the stepping logic so we step into the signal
* handler. * handler.
*/ */
user_fastforward_single_step(tsk); if (!ret)
user_fastforward_single_step(tsk);
signal_delivered(sig, info, ka, regs, 0); signal_setup_done(ret, ksig, 0);
} }
/* /*
...@@ -350,10 +338,9 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -350,10 +338,9 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
unsigned long continue_addr = 0, restart_addr = 0; unsigned long continue_addr = 0, restart_addr = 0;
struct k_sigaction ka; int retval = 0;
siginfo_t info;
int signr, retval = 0;
int syscall = (int)regs->syscallno; int syscall = (int)regs->syscallno;
struct ksignal ksig;
/* /*
* If we were from a system call, check for system call restarting... * If we were from a system call, check for system call restarting...
...@@ -387,8 +374,7 @@ static void do_signal(struct pt_regs *regs) ...@@ -387,8 +374,7 @@ static void do_signal(struct pt_regs *regs)
* Get the signal to deliver. When running under ptrace, at this point * Get the signal to deliver. When running under ptrace, at this point
* the debugger may change all of our registers. * the debugger may change all of our registers.
*/ */
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* /*
* 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
...@@ -398,12 +384,12 @@ static void do_signal(struct pt_regs *regs) ...@@ -398,12 +384,12 @@ static void do_signal(struct pt_regs *regs)
(retval == -ERESTARTNOHAND || (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->regs[0] = -EINTR; regs->regs[0] = -EINTR;
regs->pc = continue_addr; regs->pc = continue_addr;
} }
handle_signal(signr, &ka, &info, regs); handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -407,19 +407,13 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs) ...@@ -407,19 +407,13 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
return 0; return 0;
} }
static void __user *compat_get_sigframe(struct k_sigaction *ka, static void __user *compat_get_sigframe(struct ksignal *ksig,
struct pt_regs *regs, struct pt_regs *regs,
int framesize) int framesize)
{ {
compat_ulong_t sp = regs->compat_sp; compat_ulong_t sp = sigsp(regs->compat_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
*/ */
...@@ -520,18 +514,18 @@ static int compat_setup_sigframe(struct compat_sigframe __user *sf, ...@@ -520,18 +514,18 @@ static int compat_setup_sigframe(struct compat_sigframe __user *sf,
/* /*
* 32-bit signal handling routines called from signal.c * 32-bit signal handling routines called from signal.c
*/ */
int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, int compat_setup_rt_frame(int usig, struct ksignal *ksig,
sigset_t *set, struct pt_regs *regs) sigset_t *set, struct pt_regs *regs)
{ {
struct compat_rt_sigframe __user *frame; struct compat_rt_sigframe __user *frame;
int err = 0; int err = 0;
frame = compat_get_sigframe(ka, regs, sizeof(*frame)); frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
if (!frame) if (!frame)
return 1; return 1;
err |= copy_siginfo_to_user32(&frame->info, info); err |= copy_siginfo_to_user32(&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(0, &frame->sig.uc.uc_link, err); __put_user_error(0, &frame->sig.uc.uc_link, err);
...@@ -541,7 +535,7 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, ...@@ -541,7 +535,7 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
err |= compat_setup_sigframe(&frame->sig, regs, set); err |= compat_setup_sigframe(&frame->sig, regs, set);
if (err == 0) { if (err == 0) {
compat_setup_return(regs, ka, frame->sig.retcode, frame, usig); compat_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info; regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc; regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
} }
...@@ -549,13 +543,13 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, ...@@ -549,13 +543,13 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
return err; return err;
} }
int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct compat_sigframe __user *frame; struct compat_sigframe __user *frame;
int err = 0; int err = 0;
frame = compat_get_sigframe(ka, regs, sizeof(*frame)); frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
if (!frame) if (!frame)
return 1; return 1;
...@@ -564,7 +558,7 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, ...@@ -564,7 +558,7 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
err |= compat_setup_sigframe(frame, regs, set); err |= compat_setup_sigframe(frame, regs, set);
if (err == 0) if (err == 0)
compat_setup_return(regs, ka, frame->retcode, frame, usig); compat_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
return err; return err;
} }
......
...@@ -127,24 +127,20 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) ...@@ -127,24 +127,20 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
} }
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->sp; unsigned long sp = sigsp(regs->sp, ksig);
if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
return (void __user *)((sp - framesize) & ~3); return (void __user *)((sp - framesize) & ~3);
} }
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)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
err = -EFAULT; err = -EFAULT;
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto out; goto out;
...@@ -164,7 +160,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -164,7 +160,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20), err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20),
&frame->retcode); &frame->retcode);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Set up the ucontext */ /* Set up the ucontext */
err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_flags);
...@@ -176,12 +172,12 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -176,12 +172,12 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (err) if (err)
goto out; goto out;
regs->r12 = sig; regs->r12 = ksig->sig;
regs->r11 = (unsigned long) &frame->info; regs->r11 = (unsigned long) &frame->info;
regs->r10 = (unsigned long) &frame->uc; regs->r10 = (unsigned long) &frame->uc;
regs->sp = (unsigned long) frame; regs->sp = (unsigned long) frame;
if (ka->sa.sa_flags & SA_RESTORER) if (ksig->ka.sa.sa_flags & SA_RESTORER)
regs->lr = (unsigned long)ka->sa.sa_restorer; regs->lr = (unsigned long)ksig->ka.sa.sa_restorer;
else { else {
printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n", printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n",
current->comm, current->pid); current->comm, current->pid);
...@@ -189,10 +185,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -189,10 +185,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n", pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n",
current->comm, current->pid, sig, regs->sp, current->comm, current->pid, ksig->sig, regs->sp,
regs->pc, ka->sa.sa_handler, regs->lr); regs->pc, ksig->ka.sa.sa_handler, regs->lr);
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
out: out:
return err; return err;
...@@ -208,15 +204,14 @@ static inline void setup_syscall_restart(struct pt_regs *regs) ...@@ -208,15 +204,14 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
} }
static inline void static inline void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall)
struct pt_regs *regs, int syscall)
{ {
int ret; int ret;
/* /*
* Set up the stack frame * Set up the stack frame
*/ */
ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
/* /*
* Check that the resulting registers are sane * Check that the resulting registers are sane
...@@ -226,10 +221,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -226,10 +221,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
/* /*
* Block the signal if we were successful. * Block the signal if we were successful.
*/ */
if (ret != 0) signal_setup_done(ret, ksig, 0);
force_sigsegv(sig, current);
else
signal_delivered(sig, info, ka, regs, 0);
} }
/* /*
...@@ -239,9 +231,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -239,9 +231,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void do_signal(struct pt_regs *regs, int syscall) static void do_signal(struct pt_regs *regs, int syscall)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
/* /*
* We want the common case to go fast, which is why we may in * We want the common case to go fast, which is why we may in
...@@ -251,18 +241,18 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -251,18 +241,18 @@ static void do_signal(struct pt_regs *regs, int syscall)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); get_signal(&ksig);
if (syscall) { if (syscall) {
switch (regs->r12) { switch (regs->r12) {
case -ERESTART_RESTARTBLOCK: case -ERESTART_RESTARTBLOCK:
case -ERESTARTNOHAND: case -ERESTARTNOHAND:
if (signr > 0) { if (ksig.sig > 0) {
regs->r12 = -EINTR; regs->r12 = -EINTR;
break; break;
} }
/* fall through */ /* fall through */
case -ERESTARTSYS: case -ERESTARTSYS:
if (signr > 0 && !(ka.sa.sa_flags & SA_RESTART)) { if (ksig.sig > 0 && !(ksig.ka.sa.sa_flags & SA_RESTART)) {
regs->r12 = -EINTR; regs->r12 = -EINTR;
break; break;
} }
...@@ -272,13 +262,13 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -272,13 +262,13 @@ static void do_signal(struct pt_regs *regs, int syscall)
} }
} }
if (signr == 0) { if (!ksig.sig) {
/* No signal to deliver -- put the saved sigmask back */ /* No signal to deliver -- put the saved sigmask back */
restore_saved_sigmask(); restore_saved_sigmask();
return; return;
} }
handle_signal(signr, &ka, &info, regs, syscall); handle_signal(&ksig, regs, syscall);
} }
asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
......
...@@ -135,40 +135,31 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg ...@@ -135,40 +135,31 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg
return err; return err;
} }
static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, static inline void *get_sigframe(struct ksignal *ksig,
size_t frame_size) size_t frame_size)
{ {
unsigned long usp; unsigned long usp = sigsp(rdusp(), ksig);
/* Default to using normal stack. */
usp = rdusp();
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (!on_sig_stack(usp))
usp = current->sas_ss_sp + current->sas_ss_size;
}
return (void *)((usp - frame_size) & -8UL); return (void *)((usp - frame_size) & -8UL);
} }
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)
{ {
struct rt_sigframe *frame; struct rt_sigframe *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, sizeof(*frame));
err |= __put_user((current_thread_info()->exec_domain err |= __put_user((current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
&& sig < 32 && ksig->sig < 32
? current_thread_info()->exec_domain-> ? current_thread_info()->exec_domain->
signal_invmap[sig] : sig), &frame->sig); signal_invmap[ksig->sig] : ksig->sig), &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
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);
...@@ -183,7 +174,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, ...@@ -183,7 +174,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
/* Set up registers for signal handler */ /* Set up registers for signal handler */
if (current->personality & FDPIC_FUNCPTRS) { if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr = struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor *) ka->sa.sa_handler; (struct fdpic_func_descriptor *) ksig->ka.sa.sa_handler;
u32 pc, p3; u32 pc, p3;
err |= __get_user(pc, &funcptr->text); err |= __get_user(pc, &funcptr->text);
err |= __get_user(p3, &funcptr->GOT); err |= __get_user(p3, &funcptr->GOT);
...@@ -192,7 +183,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, ...@@ -192,7 +183,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
regs->pc = pc; regs->pc = pc;
regs->p3 = p3; regs->p3 = p3;
} else } else
regs->pc = (unsigned long)ka->sa.sa_handler; regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
wrusp((unsigned long)frame); wrusp((unsigned long)frame);
regs->rets = SIGRETURN_STUB; regs->rets = SIGRETURN_STUB;
...@@ -237,20 +228,19 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) ...@@ -237,20 +228,19 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void
handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct pt_regs *regs)
{ {
int ret;
/* are we from a system call? to see pt_regs->orig_p0 */ /* are we from a system call? to see pt_regs->orig_p0 */
if (regs->orig_p0 >= 0) if (regs->orig_p0 >= 0)
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
handle_restart(regs, ka, 1); handle_restart(regs, &ksig->ka, 1);
/* set up the stack frame */ /* set up the stack frame */
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
force_sigsegv(sig, current);
else signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
...@@ -264,16 +254,13 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -264,16 +254,13 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
*/ */
asmlinkage void do_signal(struct pt_regs *regs) asmlinkage void do_signal(struct pt_regs *regs)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
current->thread.esp0 = (unsigned long)regs; current->thread.esp0 = (unsigned long)regs;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, regs); handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -127,17 +127,11 @@ static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -127,17 +127,11 @@ static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
return err; return err;
} }
static inline void __user *get_sigframe(struct k_sigaction *ka, static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs, struct pt_regs *regs,
unsigned long framesize) unsigned long framesize)
{ {
unsigned long sp = regs->sp; unsigned long sp = sigsp(regs->sp, ksig);
/*
* This is the X/Open sanctioned signal stack switching.
*/
if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(sp) == 0)
sp = current->sas_ss_sp + current->sas_ss_size;
/* /*
* No matter what happens, 'sp' must be dword * No matter what happens, 'sp' must be dword
...@@ -146,21 +140,21 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, ...@@ -146,21 +140,21 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
return (void __user *)((sp - framesize) & ~7); return (void __user *)((sp - framesize) & ~7);
} }
static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
unsigned long __user *retcode; unsigned long __user *retcode;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto segv_and_exit; return -EFAULT;
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Clear all the bits of the ucontext we don't use. */ /* Clear all the bits of the ucontext we don't use. */
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
...@@ -188,7 +182,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -188,7 +182,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
#undef COPY #undef COPY
if (err) if (err)
goto segv_and_exit; return -EFAULT;
flush_icache_range((unsigned long) &frame->retcode, flush_icache_range((unsigned long) &frame->retcode,
(unsigned long) &frame->retcode + RETCODE_SIZE); (unsigned long) &frame->retcode + RETCODE_SIZE);
...@@ -198,10 +192,10 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -198,10 +192,10 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
/* Change user context to branch to signal handler */ /* Change user context to branch to signal handler */
regs->sp = (unsigned long) frame - 8; regs->sp = (unsigned long) frame - 8;
regs->b3 = (unsigned long) retcode; regs->b3 = (unsigned long) retcode;
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
/* Give the signal number to the handler */ /* Give the signal number to the handler */
regs->a4 = signr; regs->a4 = ksig->sig;
/* /*
* For realtime signals we must also set the second and third * For realtime signals we must also set the second and third
...@@ -212,10 +206,6 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -212,10 +206,6 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
regs->a6 = (unsigned long)&frame->uc; regs->a6 = (unsigned long)&frame->uc;
return 0; return 0;
segv_and_exit:
force_sigsegv(signr, current);
return -EFAULT;
} }
static inline void static inline void
...@@ -245,10 +235,11 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) ...@@ -245,10 +235,11 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
/* /*
* handle the actual delivery of a signal to userspace * handle the actual delivery of a signal to userspace
*/ */
static void handle_signal(int sig, static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
siginfo_t *info, struct k_sigaction *ka, int syscall)
struct pt_regs *regs, int syscall)
{ {
int ret;
/* Are we from a system call? */ /* Are we from a system call? */
if (syscall) { if (syscall) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -259,7 +250,7 @@ static void handle_signal(int sig, ...@@ -259,7 +250,7 @@ static void handle_signal(int sig,
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->a4 = -EINTR; regs->a4 = -EINTR;
break; break;
} }
...@@ -272,9 +263,8 @@ static void handle_signal(int sig, ...@@ -272,9 +263,8 @@ static void handle_signal(int sig,
} }
/* Set up the stack frame */ /* Set up the stack frame */
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
return; signal_setup_done(ret, ksig, 0);
signal_delivered(sig, info, ka, regs, 0);
} }
/* /*
...@@ -282,18 +272,15 @@ static void handle_signal(int sig, ...@@ -282,18 +272,15 @@ static void handle_signal(int sig,
*/ */
static void do_signal(struct pt_regs *regs, int syscall) static void do_signal(struct pt_regs *regs, int syscall)
{ {
struct k_sigaction ka; struct ksignal ksig;
siginfo_t info;
int signr;
/* we want the common case to go fast, which is why we may in certain /* we want the common case to go fast, which is why we may in certain
* cases get here from kernel mode */ * cases get here from kernel mode */
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) { handle_signal(&ksig, regs, syscall);
handle_signal(signr, &info, &ka, regs, syscall);
return; return;
} }
......
...@@ -203,15 +203,9 @@ static int setup_sigcontext(struct sigcontext __user *sc, ...@@ -203,15 +203,9 @@ static int setup_sigcontext(struct sigcontext __user *sc,
* - usually on the stack. */ * - usually on the stack. */
static inline void __user * static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) get_sigframe(struct ksignal *ksig, size_t frame_size)
{ {
unsigned long sp = rdusp(); unsigned long sp = sigsp(rdusp(), ksig);
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (! on_sig_stack(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
}
/* make sure the frame is dword-aligned */ /* make sure the frame is dword-aligned */
...@@ -228,33 +222,33 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) ...@@ -228,33 +222,33 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
* user-mode trampoline. * user-mode trampoline.
*/ */
static int setup_frame(int sig, struct k_sigaction *ka, static int setup_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
unsigned long return_ip; unsigned long return_ip;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
if (_NSIG_WORDS > 1) { if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1], err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask)); sizeof(frame->extramask));
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
return_ip = (unsigned long)ka->sa.sa_restorer; return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
} else { } else {
/* trampoline - the desired return ip is the retcode itself */ /* trampoline - the desired return ip is the retcode itself */
return_ip = (unsigned long)&frame->retcode; return_ip = (unsigned long)&frame->retcode;
...@@ -265,42 +259,38 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -265,42 +259,38 @@ static int setup_frame(int sig, struct k_sigaction *ka,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->irp = (unsigned long) ka->sa.sa_handler; /* what we enter NOW */ regs->irp = (unsigned long) ksig->ka.sa.sa_handler; /* what we enter NOW */
regs->srp = return_ip; /* what we enter LATER */ regs->srp = return_ip; /* what we enter LATER */
regs->r10 = sig; /* first argument is signo */ regs->r10 = ksig->sig; /* first argument is signo */
/* actually move the usp to reflect the stacked frame */ /* actually move the usp to reflect the stacked frame */
wrusp((unsigned long)frame); wrusp((unsigned long)frame);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
unsigned long return_ip; unsigned long return_ip;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Clear all the bits of the ucontext we don't use. */ /* Clear all the bits of the ucontext we don't use. */
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
...@@ -312,12 +302,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -312,12 +302,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __save_altstack(&frame->uc.uc_stack, rdusp()); err |= __save_altstack(&frame->uc.uc_stack, rdusp());
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
return_ip = (unsigned long)ka->sa.sa_restorer; return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
} else { } else {
/* trampoline - the desired return ip is the retcode itself */ /* trampoline - the desired return ip is the retcode itself */
return_ip = (unsigned long)&frame->retcode; return_ip = (unsigned long)&frame->retcode;
...@@ -329,18 +319,18 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -329,18 +319,18 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* TODO what is the current->exec_domain stuff and invmap ? */ /* TODO what is the current->exec_domain stuff and invmap ? */
/* Set up registers for signal handler */ /* Set up registers for signal handler */
/* What we enter NOW */ /* What we enter NOW */
regs->irp = (unsigned long) ka->sa.sa_handler; regs->irp = (unsigned long) ksig->ka.sa.sa_handler;
/* What we enter LATER */ /* What we enter LATER */
regs->srp = return_ip; regs->srp = return_ip;
/* First argument is signo */ /* First argument is signo */
regs->r10 = sig; regs->r10 = ksig->sig;
/* Second argument is (siginfo_t *) */ /* Second argument is (siginfo_t *) */
regs->r11 = (unsigned long)&frame->info; regs->r11 = (unsigned long)&frame->info;
/* Third argument is unused */ /* Third argument is unused */
...@@ -350,19 +340,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -350,19 +340,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
wrusp((unsigned long)frame); wrusp((unsigned long)frame);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static inline void handle_signal(int canrestart, unsigned long sig, static inline void handle_signal(int canrestart, struct ksignal *ksig,
siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs)
struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
...@@ -383,7 +368,7 @@ static inline void handle_signal(int canrestart, unsigned long sig, ...@@ -383,7 +368,7 @@ static inline void handle_signal(int canrestart, unsigned long sig,
/* ERESTARTSYS means to restart the syscall if /* ERESTARTSYS means to restart the syscall if
* there is no handler or the handler was * there is no handler or the handler was
* registered with SA_RESTART */ * registered with SA_RESTART */
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->r10 = -EINTR; regs->r10 = -EINTR;
break; break;
} }
...@@ -396,13 +381,12 @@ static inline void handle_signal(int canrestart, unsigned long sig, ...@@ -396,13 +381,12 @@ static inline void handle_signal(int canrestart, unsigned long sig,
} }
/* 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(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 == 0) signal_setup_done(ret, ksig, 0);
signal_delivered(sig, info, ka, regs, 0);
} }
/* /*
...@@ -419,9 +403,7 @@ static inline void handle_signal(int canrestart, unsigned long sig, ...@@ -419,9 +403,7 @@ static inline void handle_signal(int canrestart, unsigned long sig,
void do_signal(int canrestart, struct pt_regs *regs) void do_signal(int canrestart, struct pt_regs *regs)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -432,10 +414,9 @@ void do_signal(int canrestart, struct pt_regs *regs) ...@@ -432,10 +414,9 @@ void do_signal(int canrestart, struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(canrestart, signr, &info, &ka, regs); handle_signal(canrestart, &ksig, regs);
return; return;
} }
......
...@@ -189,17 +189,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -189,17 +189,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
/* Figure out where to put the new signal frame - usually on the stack. */ /* Figure out where to put the new signal frame - usually on the stack. */
static inline void __user * static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) get_sigframe(struct ksignal *ksig, size_t frame_size)
{ {
unsigned long sp; unsigned long sp = sigsp(rdusp(), ksig);
sp = rdusp();
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (!on_sig_stack(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
}
/* Make sure the frame is dword-aligned. */ /* Make sure the frame is dword-aligned. */
sp &= ~3; sp &= ~3;
...@@ -215,23 +207,22 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) ...@@ -215,23 +207,22 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
* trampoline. * trampoline.
*/ */
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)
{ {
int err; int err;
unsigned long return_ip; unsigned long return_ip;
struct signal_frame __user *frame; struct signal_frame __user *frame;
err = 0; err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
if (_NSIG_WORDS > 1) { if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1], err |= __copy_to_user(frame->extramask, &set->sig[1],
...@@ -239,14 +230,14 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -239,14 +230,14 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Set up to return from user-space. If provided, use a stub * Set up to return from user-space. If provided, use a stub
* already located in user-space. * already located in user-space.
*/ */
if (ka->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
return_ip = (unsigned long)ka->sa.sa_restorer; return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
} else { } else {
/* Trampoline - the desired return ip is in the signal return page. */ /* Trampoline - the desired return ip is in the signal return page. */
return_ip = cris_signal_return_page; return_ip = cris_signal_return_page;
...@@ -264,7 +255,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -264,7 +255,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Set up registers for signal handler. * Set up registers for signal handler.
...@@ -273,42 +264,37 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -273,42 +264,37 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
* Where the code enter later. * Where the code enter later.
* First argument, signo. * First argument, signo.
*/ */
regs->erp = (unsigned long) ka->sa.sa_handler; regs->erp = (unsigned long) ksig->ka.sa.sa_handler;
regs->srp = return_ip; regs->srp = return_ip;
regs->r10 = sig; regs->r10 = ksig->sig;
/* Actually move the USP to reflect the stacked frame. */ /* Actually move the USP to reflect the stacked frame. */
wrusp((unsigned long)frame); wrusp((unsigned long)frame);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
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)
{ {
int err; int err;
unsigned long return_ip; unsigned long return_ip;
struct rt_signal_frame __user *frame; struct rt_signal_frame __user *frame;
err = 0; err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
/* TODO: what is the current->exec_domain stuff and invmap ? */ /* TODO: what is the current->exec_domain stuff and invmap ? */
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Clear all the bits of the ucontext we don't use. */ /* Clear all the bits of the ucontext we don't use. */
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
...@@ -317,14 +303,14 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -317,14 +303,14 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __save_altstack(&frame->uc.uc_stack, rdusp()); err |= __save_altstack(&frame->uc.uc_stack, rdusp());
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Set up to return from user-space. If provided, use a stub * Set up to return from user-space. If provided, use a stub
* already located in user-space. * already located in user-space.
*/ */
if (ka->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
return_ip = (unsigned long) ka->sa.sa_restorer; return_ip = (unsigned long) ksig->ka.sa.sa_restorer;
} else { } else {
/* Trampoline - the desired return ip is in the signal return page. */ /* Trampoline - the desired return ip is in the signal return page. */
return_ip = cris_signal_return_page + 6; return_ip = cris_signal_return_page + 6;
...@@ -345,7 +331,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -345,7 +331,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Set up registers for signal handler. * Set up registers for signal handler.
...@@ -356,9 +342,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -356,9 +342,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* Second argument is (siginfo_t *). * Second argument is (siginfo_t *).
* Third argument is unused. * Third argument is unused.
*/ */
regs->erp = (unsigned long) ka->sa.sa_handler; regs->erp = (unsigned long) ksig->ka.sa.sa_handler;
regs->srp = return_ip; regs->srp = return_ip;
regs->r10 = sig; regs->r10 = ksig->sig;
regs->r11 = (unsigned long) &frame->info; regs->r11 = (unsigned long) &frame->info;
regs->r12 = 0; regs->r12 = 0;
...@@ -366,17 +352,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -366,17 +352,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
wrusp((unsigned long)frame); wrusp((unsigned long)frame);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
/* Invoke a signal handler to, well, handle the signal. */ /* Invoke a signal handler to, well, handle the signal. */
static inline void static inline void
handle_signal(int canrestart, unsigned long sig, handle_signal(int canrestart, struct ksignal *ksig, struct pt_regs *regs)
siginfo_t *info, struct k_sigaction *ka,
struct pt_regs * regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
...@@ -404,7 +384,7 @@ handle_signal(int canrestart, unsigned long sig, ...@@ -404,7 +384,7 @@ handle_signal(int canrestart, unsigned long sig,
* there is no handler, or the handler * there is no handler, or the handler
* was registered with SA_RESTART. * was registered with SA_RESTART.
*/ */
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->r10 = -EINTR; regs->r10 = -EINTR;
break; break;
} }
...@@ -423,13 +403,12 @@ handle_signal(int canrestart, unsigned long sig, ...@@ -423,13 +403,12 @@ handle_signal(int canrestart, unsigned long sig,
} }
/* 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(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 == 0) signal_setup_done(ret, ksig, 0);
signal_delivered(sig, info, ka, regs, 0);
} }
/* /*
...@@ -446,9 +425,7 @@ handle_signal(int canrestart, unsigned long sig, ...@@ -446,9 +425,7 @@ handle_signal(int canrestart, unsigned long sig,
void void
do_signal(int canrestart, struct pt_regs *regs) do_signal(int canrestart, struct pt_regs *regs)
{ {
int signr; struct ksignal ksig;
siginfo_t info;
struct k_sigaction ka;
/* /*
* The common case should go fast, which is why this point is * The common case should go fast, which is why this point is
...@@ -458,11 +435,9 @@ do_signal(int canrestart, struct pt_regs *regs) ...@@ -458,11 +435,9 @@ do_signal(int canrestart, struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(canrestart, signr, &info, &ka, regs); handle_signal(canrestart, &ksig, regs);
return; return;
} }
......
...@@ -158,19 +158,10 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask) ...@@ -158,19 +158,10 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
/* /*
* Determine which stack to use.. * Determine which stack to use..
*/ */
static inline void __user *get_sigframe(struct k_sigaction *ka, static inline void __user *get_sigframe(struct ksignal *ksig,
size_t frame_size) size_t frame_size)
{ {
unsigned long sp; unsigned long sp = sigsp(__frame->sp, ksig);
/* Default to using normal stack */
sp = __frame->sp;
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (! sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
}
return (void __user *) ((sp - frame_size) & ~7UL); return (void __user *) ((sp - frame_size) & ~7UL);
...@@ -180,17 +171,17 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, ...@@ -180,17 +171,17 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
/* /*
* *
*/ */
static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) static int setup_frame(struct ksignal *ksig, sigset_t *set)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
int rsig; int rsig, sig = ksig->sig;
set_fs(USER_DS); set_fs(USER_DS);
frame = get_sigframe(ka, sizeof(*frame)); frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
rsig = sig; rsig = sig;
if (sig < 32 && if (sig < 32 &&
...@@ -199,22 +190,22 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) ...@@ -199,22 +190,22 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
rsig = __current_thread_info->exec_domain->signal_invmap[sig]; rsig = __current_thread_info->exec_domain->signal_invmap[sig];
if (__put_user(rsig, &frame->sig) < 0) if (__put_user(rsig, &frame->sig) < 0)
goto give_sigsegv; return -EFAULT;
if (setup_sigcontext(&frame->sc, set->sig[0])) if (setup_sigcontext(&frame->sc, set->sig[0]))
goto give_sigsegv; return -EFAULT;
if (_NSIG_WORDS > 1) { if (_NSIG_WORDS > 1) {
if (__copy_to_user(frame->extramask, &set->sig[1], if (__copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask))) sizeof(frame->extramask)))
goto give_sigsegv; return -EFAULT;
} }
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0) if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode) < 0)
goto give_sigsegv; return -EFAULT;
} }
else { else {
/* Set up the following code on the stack: /* Set up the following code on the stack:
...@@ -224,7 +215,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) ...@@ -224,7 +215,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
__put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) || __put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
__put_user(0xc0700000, &frame->retcode[1])) __put_user(0xc0700000, &frame->retcode[1]))
goto give_sigsegv; return -EFAULT;
flush_icache_range((unsigned long) frame->retcode, flush_icache_range((unsigned long) frame->retcode,
(unsigned long) (frame->retcode + 2)); (unsigned long) (frame->retcode + 2));
...@@ -233,14 +224,14 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) ...@@ -233,14 +224,14 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
/* Set up registers for the signal handler */ /* Set up registers for the signal handler */
if (current->personality & FDPIC_FUNCPTRS) { if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr = struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor __user *) ka->sa.sa_handler; (struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler;
struct fdpic_func_descriptor desc; struct fdpic_func_descriptor desc;
if (copy_from_user(&desc, funcptr, sizeof(desc))) if (copy_from_user(&desc, funcptr, sizeof(desc)))
goto give_sigsegv; return -EFAULT;
__frame->pc = desc.text; __frame->pc = desc.text;
__frame->gr15 = desc.GOT; __frame->gr15 = desc.GOT;
} else { } else {
__frame->pc = (unsigned long) ka->sa.sa_handler; __frame->pc = (unsigned long) ksig->ka.sa.sa_handler;
__frame->gr15 = 0; __frame->gr15 = 0;
} }
...@@ -255,29 +246,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) ...@@ -255,29 +246,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} /* end setup_frame() */ } /* end setup_frame() */
/*****************************************************************************/ /*****************************************************************************/
/* /*
* *
*/ */
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set)
sigset_t *set)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int rsig; int rsig, sig = ksig->sig;
set_fs(USER_DS); set_fs(USER_DS);
frame = get_sigframe(ka, sizeof(*frame)); frame = get_sigframe(ksig, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
rsig = sig; rsig = sig;
if (sig < 32 && if (sig < 32 &&
...@@ -288,28 +273,28 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -288,28 +273,28 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__put_user(rsig, &frame->sig) || if (__put_user(rsig, &frame->sig) ||
__put_user(&frame->info, &frame->pinfo) || __put_user(&frame->info, &frame->pinfo) ||
__put_user(&frame->uc, &frame->puc)) __put_user(&frame->uc, &frame->puc))
goto give_sigsegv; return -EFAULT;
if (copy_siginfo_to_user(&frame->info, info)) if (copy_siginfo_to_user(&frame->info, &ksig->info))
goto give_sigsegv; return -EFAULT;
/* Create the ucontext. */ /* Create the ucontext. */
if (__put_user(0, &frame->uc.uc_flags) || if (__put_user(0, &frame->uc.uc_flags) ||
__put_user(NULL, &frame->uc.uc_link) || __put_user(NULL, &frame->uc.uc_link) ||
__save_altstack(&frame->uc.uc_stack, __frame->sp)) __save_altstack(&frame->uc.uc_stack, __frame->sp))
goto give_sigsegv; return -EFAULT;
if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0])) if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
goto give_sigsegv; return -EFAULT;
if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
goto give_sigsegv; return -EFAULT;
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
if (__put_user(ka->sa.sa_restorer, &frame->pretcode)) if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
goto give_sigsegv; return -EFAULT;
} }
else { else {
/* Set up the following code on the stack: /* Set up the following code on the stack:
...@@ -319,7 +304,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -319,7 +304,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) || if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
__put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) || __put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
__put_user(0xc0700000, &frame->retcode[1])) __put_user(0xc0700000, &frame->retcode[1]))
goto give_sigsegv; return -EFAULT;
flush_icache_range((unsigned long) frame->retcode, flush_icache_range((unsigned long) frame->retcode,
(unsigned long) (frame->retcode + 2)); (unsigned long) (frame->retcode + 2));
...@@ -328,14 +313,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -328,14 +313,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */ /* Set up registers for signal handler */
if (current->personality & FDPIC_FUNCPTRS) { if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr = struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor __user *) ka->sa.sa_handler; (struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler;
struct fdpic_func_descriptor desc; struct fdpic_func_descriptor desc;
if (copy_from_user(&desc, funcptr, sizeof(desc))) if (copy_from_user(&desc, funcptr, sizeof(desc)))
goto give_sigsegv; return -EFAULT;
__frame->pc = desc.text; __frame->pc = desc.text;
__frame->gr15 = desc.GOT; __frame->gr15 = desc.GOT;
} else { } else {
__frame->pc = (unsigned long) ka->sa.sa_handler; __frame->pc = (unsigned long) ksig->ka.sa.sa_handler;
__frame->gr15 = 0; __frame->gr15 = 0;
} }
...@@ -349,21 +334,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -349,21 +334,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sig, current->comm, current->pid, frame, __frame->pc, sig, current->comm, current->pid, frame, __frame->pc,
frame->pretcode); frame->pretcode);
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} /* end setup_rt_frame() */ } /* end setup_rt_frame() */
/*****************************************************************************/ /*****************************************************************************/
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(struct ksignal *ksig)
struct k_sigaction *ka)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
...@@ -378,7 +357,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -378,7 +357,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
__frame->gr8 = -EINTR; __frame->gr8 = -EINTR;
break; break;
} }
...@@ -392,16 +371,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -392,16 +371,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
} }
/* 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(sig, ka, info, oldset); ret = setup_rt_frame(ksig, oldset);
else else
ret = setup_frame(sig, ka, oldset); ret = setup_frame(ksig, oldset);
if (ret)
return;
signal_delivered(sig, info, ka, __frame, signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
test_thread_flag(TIF_SINGLESTEP));
} /* end handle_signal() */ } /* end handle_signal() */
/*****************************************************************************/ /*****************************************************************************/
...@@ -412,13 +387,10 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -412,13 +387,10 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
*/ */
static void do_signal(void) static void do_signal(void)
{ {
struct k_sigaction ka; struct ksignal ksig;
siginfo_t info;
int signr;
signr = get_signal_to_deliver(&info, &ka, __frame, NULL); if (get_signal(&ksig)) {
if (signr > 0) { handle_signal(&ksig);
handle_signal(signr, &info, &ka);
return; return;
} }
......
...@@ -36,18 +36,10 @@ struct rt_sigframe { ...@@ -36,18 +36,10 @@ struct rt_sigframe {
struct ucontext uc; struct ucontext uc;
}; };
static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
size_t frame_size) size_t frame_size)
{ {
unsigned long sp = regs->r29; unsigned long sp = sigsp(regs->r29, ksig);
/* check if we would overflow the alt stack */
if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
return (void __user __force *)-1UL;
/* Switch to signal stack if appropriate */
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1)); return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
} }
...@@ -112,20 +104,20 @@ static int restore_sigcontext(struct pt_regs *regs, ...@@ -112,20 +104,20 @@ static int restore_sigcontext(struct pt_regs *regs,
/* /*
* Setup signal stack frame with siginfo structure * Setup signal stack frame with siginfo structure
*/ */
static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
int err = 0; int err = 0;
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
struct hexagon_vdso *vdso = current->mm->context.vdso; struct hexagon_vdso *vdso = current->mm->context.vdso;
frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe)); frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe))) if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
goto sigsegv; return -EFAULT;
if (copy_siginfo_to_user(&frame->info, info)) if (copy_siginfo_to_user(&frame->info, &ksig->info))
goto sigsegv; return -EFAULT;
/* The on-stack signal trampoline is no longer executed; /* The on-stack signal trampoline is no longer executed;
* however, the libgcc signal frame unwinding code checks for * however, the libgcc signal frame unwinding code checks for
...@@ -137,29 +129,26 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -137,29 +129,26 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs)); err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs));
if (err) if (err)
goto sigsegv; return -EFAULT;
/* Load r0/r1 pair with signumber/siginfo pointer... */ /* Load r0/r1 pair with signumber/siginfo pointer... */
regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32) regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
| (unsigned long long)signr; | (unsigned long long)ksig->sig;
regs->r02 = (unsigned long) &frame->uc; regs->r02 = (unsigned long) &frame->uc;
regs->r31 = (unsigned long) vdso->rt_signal_trampoline; regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
pt_psp(regs) = (unsigned long) frame; pt_psp(regs) = (unsigned long) frame;
pt_set_elr(regs, (unsigned long)ka->sa.sa_handler); pt_set_elr(regs, (unsigned long)ksig->ka.sa.sa_handler);
return 0; return 0;
sigsegv:
force_sigsegv(signr, current);
return -EFAULT;
} }
/* /*
* Setup invocation of signal handler * Setup invocation of signal handler
*/ */
static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct pt_regs *regs)
{ {
int ret;
/* /*
* If we're handling a signal that aborted a system call, * If we're handling a signal that aborted a system call,
* set up the error return value before adding the signal * set up the error return value before adding the signal
...@@ -173,7 +162,7 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -173,7 +162,7 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
regs->r00 = -EINTR; regs->r00 = -EINTR;
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->r00 = -EINTR; regs->r00 = -EINTR;
break; break;
} }
...@@ -193,11 +182,9 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -193,11 +182,9 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
* only set up the rt_frame flavor. * only set up the rt_frame flavor.
*/ */
/* If there was an error on setup, no signal was delivered. */ /* If there was an error on setup, no signal was delivered. */
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0) ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
return;
signal_delivered(sig, info, ka, regs, signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
...@@ -205,17 +192,13 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -205,17 +192,13 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
*/ */
void do_signal(struct pt_regs *regs) void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction sigact; struct ksignal ksig;
siginfo_t info;
int signo;
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signo = get_signal_to_deliver(&info, &sigact, regs, NULL); if (get_signal(&ksig)) {
handle_signal(&ksig, regs);
if (signo > 0) {
handle_signal(signo, &info, &sigact, regs);
return; return;
} }
......
...@@ -309,12 +309,11 @@ force_sigsegv_info (int sig, void __user *addr) ...@@ -309,12 +309,11 @@ force_sigsegv_info (int sig, void __user *addr)
si.si_uid = from_kuid_munged(current_user_ns(), current_uid()); si.si_uid = from_kuid_munged(current_user_ns(), current_uid());
si.si_addr = addr; si.si_addr = addr;
force_sig_info(SIGSEGV, &si, current); force_sig_info(SIGSEGV, &si, current);
return 0; return 1;
} }
static long static long
setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr)
struct sigscratch *scr)
{ {
extern char __kernel_sigtramp[]; extern char __kernel_sigtramp[];
unsigned long tramp_addr, new_rbs = 0, new_sp; unsigned long tramp_addr, new_rbs = 0, new_sp;
...@@ -323,7 +322,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, ...@@ -323,7 +322,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
new_sp = scr->pt.r12; new_sp = scr->pt.r12;
tramp_addr = (unsigned long) __kernel_sigtramp; tramp_addr = (unsigned long) __kernel_sigtramp;
if (ka->sa.sa_flags & SA_ONSTACK) { if (ksig->ka.sa.sa_flags & SA_ONSTACK) {
int onstack = sas_ss_flags(new_sp); int onstack = sas_ss_flags(new_sp);
if (onstack == 0) { if (onstack == 0) {
...@@ -347,29 +346,29 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, ...@@ -347,29 +346,29 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
*/ */
check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN; check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN;
if (!likely(on_sig_stack(check_sp))) if (!likely(on_sig_stack(check_sp)))
return force_sigsegv_info(sig, (void __user *) return force_sigsegv_info(ksig->sig, (void __user *)
check_sp); check_sp);
} }
} }
frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN); frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return force_sigsegv_info(sig, frame); return force_sigsegv_info(ksig->sig, frame);
err = __put_user(sig, &frame->arg0); err = __put_user(ksig->sig, &frame->arg0);
err |= __put_user(&frame->info, &frame->arg1); err |= __put_user(&frame->info, &frame->arg1);
err |= __put_user(&frame->sc, &frame->arg2); err |= __put_user(&frame->sc, &frame->arg2);
err |= __put_user(new_rbs, &frame->sc.sc_rbs_base); err |= __put_user(new_rbs, &frame->sc.sc_rbs_base);
err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */ err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */
err |= __put_user(ka->sa.sa_handler, &frame->handler); err |= __put_user(ksig->ka.sa.sa_handler, &frame->handler);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12); err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12);
err |= setup_sigcontext(&frame->sc, set, scr); err |= setup_sigcontext(&frame->sc, set, scr);
if (unlikely(err)) if (unlikely(err))
return force_sigsegv_info(sig, frame); return force_sigsegv_info(ksig->sig, frame);
scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */ scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */
scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */ scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */
...@@ -394,22 +393,20 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set, ...@@ -394,22 +393,20 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
#if DEBUG_SIG #if DEBUG_SIG
printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%p\n", printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%p\n",
current->comm, current->pid, sig, scr->pt.r12, frame->sc.sc_ip, frame->handler); current->comm, current->pid, ksig->sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
#endif #endif
return 1; return 0;
} }
static long static long
handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal (struct ksignal *ksig, struct sigscratch *scr)
struct sigscratch *scr)
{ {
if (!setup_frame(sig, ka, info, sigmask_to_save(), scr)) int ret = setup_frame(ksig, sigmask_to_save(), scr);
return 0;
signal_delivered(sig, info, ka, &scr->pt, if (!ret)
test_thread_flag(TIF_SINGLESTEP)); signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
return 1; return ret;
} }
/* /*
...@@ -419,17 +416,16 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -419,17 +416,16 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
void void
ia64_do_signal (struct sigscratch *scr, long in_syscall) ia64_do_signal (struct sigscratch *scr, long in_syscall)
{ {
struct k_sigaction ka;
siginfo_t info;
long restart = in_syscall; long restart = in_syscall;
long errno = scr->pt.r8; long errno = scr->pt.r8;
struct ksignal ksig;
/* /*
* This only loops in the rare cases of handle_signal() failing, in which case we * This only loops in the rare cases of handle_signal() failing, in which case we
* need to push through a forced SIGSEGV. * need to push through a forced SIGSEGV.
*/ */
while (1) { while (1) {
int signr = get_signal_to_deliver(&info, &ka, &scr->pt, NULL); get_signal(&ksig);
/* /*
* get_signal_to_deliver() may have run a debugger (via notify_parent()) * get_signal_to_deliver() may have run a debugger (via notify_parent())
...@@ -446,7 +442,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) ...@@ -446,7 +442,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
*/ */
restart = 0; restart = 0;
if (signr <= 0) if (ksig.sig <= 0)
break; break;
if (unlikely(restart)) { if (unlikely(restart)) {
...@@ -458,7 +454,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) ...@@ -458,7 +454,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
break; break;
case ERESTARTSYS: case ERESTARTSYS:
if ((ka.sa.sa_flags & SA_RESTART) == 0) { if ((ksig.ka.sa.sa_flags & SA_RESTART) == 0) {
scr->pt.r8 = EINTR; scr->pt.r8 = EINTR;
/* note: scr->pt.r10 is already -1 */ /* note: scr->pt.r10 is already -1 */
break; break;
...@@ -473,7 +469,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall) ...@@ -473,7 +469,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
* Whee! Actually deliver the signal. If the delivery failed, we need to * Whee! Actually deliver the signal. If the delivery failed, we need to
* continue to iterate in this loop so we can deliver the SIGSEGV... * continue to iterate in this loop so we can deliver the SIGSEGV...
*/ */
if (handle_signal(signr, &ka, &info, scr)) if (handle_signal(&ksig, scr))
return; return;
} }
......
...@@ -162,28 +162,22 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -162,28 +162,22 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
* Determine which stack to use.. * Determine which stack to use..
*/ */
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)
{ {
/* This is the X/Open sanctioned signal stack switching. */ return (void __user *)((sigsp(sp, ksig) - frame_size) & -8ul);
if (ka->sa.sa_flags & SA_ONSTACK) {
if (sas_ss_flags(sp) == 0)
sp = current->sas_ss_sp + current->sas_ss_size;
}
return (void __user *)((sp - frame_size) & -8ul);
} }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0;
int signal; int signal, sig = ksig->sig;
frame = get_sigframe(ka, regs->spu, sizeof(*frame)); frame = get_sigframe(ksig, regs->spu, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
signal = current_thread_info()->exec_domain signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -193,13 +187,13 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -193,13 +187,13 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(signal, &frame->sig); err |= __put_user(signal, &frame->sig);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_flags);
...@@ -208,17 +202,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -208,17 +202,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Set up to return from userspace. */ /* Set up to return from userspace. */
regs->lr = (unsigned long)ka->sa.sa_restorer; regs->lr = (unsigned long)ksig->ka.sa.sa_restorer;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->spu = (unsigned long)frame; regs->spu = (unsigned long)frame;
regs->r0 = signal; /* Arg for signal handler */ regs->r0 = signal; /* Arg for signal handler */
regs->r1 = (unsigned long)&frame->info; regs->r1 = (unsigned long)&frame->info;
regs->r2 = (unsigned long)&frame->uc; regs->r2 = (unsigned long)&frame->uc;
regs->bpc = (unsigned long)ka->sa.sa_handler; regs->bpc = (unsigned long)ksig->ka.sa.sa_handler;
set_fs(USER_DS); set_fs(USER_DS);
...@@ -228,10 +222,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -228,10 +222,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static int prev_insn(struct pt_regs *regs) static int prev_insn(struct pt_regs *regs)
...@@ -252,9 +242,10 @@ static int prev_insn(struct pt_regs *regs) ...@@ -252,9 +242,10 @@ static int prev_insn(struct pt_regs *regs)
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct pt_regs *regs)
{ {
int ret;
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->syscall_nr >= 0) { if (regs->syscall_nr >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
...@@ -265,7 +256,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -265,7 +256,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->r0 = -EINTR; regs->r0 = -EINTR;
break; break;
} }
...@@ -278,10 +269,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -278,10 +269,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
} }
/* Set up the stack frame */ /* Set up the stack frame */
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs)) ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
return;
signal_delivered(sig, info, ka, regs, 0); signal_setup_done(ret, ksig, 0);
} }
/* /*
...@@ -291,9 +281,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -291,9 +281,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -304,8 +292,7 @@ static void do_signal(struct pt_regs *regs) ...@@ -304,8 +292,7 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Re-enable any watchpoints before delivering the /* Re-enable any watchpoints before delivering the
* signal to user space. The processor register will * signal to user space. The processor register will
* have been cleared if the watchpoint triggered * have been cleared if the watchpoint triggered
...@@ -313,7 +300,7 @@ static void do_signal(struct pt_regs *regs) ...@@ -313,7 +300,7 @@ static void do_signal(struct pt_regs *regs)
*/ */
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, regs); handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -835,38 +835,30 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs * ...@@ -835,38 +835,30 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *
} }
static inline void __user * static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) get_sigframe(struct ksignal *ksig, size_t frame_size)
{ {
unsigned long usp; unsigned long usp = sigsp(rdusp(), ksig);
/* Default to using normal stack. */
usp = rdusp();
/* This is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (!sas_ss_flags(usp))
usp = current->sas_ss_sp + current->sas_ss_size;
}
return (void __user *)((usp - frame_size) & -8UL); return (void __user *)((usp - frame_size) & -8UL);
} }
static int setup_frame (int sig, struct k_sigaction *ka, static int setup_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
int fsize = frame_extra_sizes(regs->format); int fsize = frame_extra_sizes(regs->format);
struct sigcontext context; struct sigcontext context;
int err = 0; int err = 0, sig = ksig->sig;
if (fsize < 0) { if (fsize < 0) {
#ifdef DEBUG #ifdef DEBUG
printk ("setup_frame: Unknown frame format %#x\n", printk ("setup_frame: Unknown frame format %#x\n",
regs->format); regs->format);
#endif #endif
goto give_sigsegv; return -EFAULT;
} }
frame = get_sigframe(ka, regs, sizeof(*frame) + fsize); frame = get_sigframe(ksig, sizeof(*frame) + fsize);
if (fsize) if (fsize)
err |= copy_to_user (frame + 1, regs + 1, fsize); err |= copy_to_user (frame + 1, regs + 1, fsize);
...@@ -899,7 +891,7 @@ static int setup_frame (int sig, struct k_sigaction *ka, ...@@ -899,7 +891,7 @@ static int setup_frame (int sig, struct k_sigaction *ka,
#endif #endif
if (err) if (err)
goto give_sigsegv; return -EFAULT;
push_cache ((unsigned long) &frame->retcode); push_cache ((unsigned long) &frame->retcode);
...@@ -908,7 +900,7 @@ static int setup_frame (int sig, struct k_sigaction *ka, ...@@ -908,7 +900,7 @@ static int setup_frame (int sig, struct k_sigaction *ka,
* to destroy is successfully copied to sigframe. * to destroy is successfully copied to sigframe.
*/ */
wrusp ((unsigned long) frame); wrusp ((unsigned long) frame);
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
adjustformat(regs); adjustformat(regs);
/* /*
...@@ -934,28 +926,24 @@ static int setup_frame (int sig, struct k_sigaction *ka, ...@@ -934,28 +926,24 @@ static int setup_frame (int sig, struct k_sigaction *ka,
tregs->sr = regs->sr; tregs->sr = regs->sr;
} }
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return err;
} }
static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int fsize = frame_extra_sizes(regs->format); int fsize = frame_extra_sizes(regs->format);
int err = 0; int err = 0, sig = ksig->sig;
if (fsize < 0) { if (fsize < 0) {
#ifdef DEBUG #ifdef DEBUG
printk ("setup_frame: Unknown frame format %#x\n", printk ("setup_frame: Unknown frame format %#x\n",
regs->format); regs->format);
#endif #endif
goto give_sigsegv; return -EFAULT;
} }
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, sizeof(*frame));
if (fsize) if (fsize)
err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
...@@ -968,7 +956,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -968,7 +956,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
&frame->sig); &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
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);
...@@ -996,7 +984,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -996,7 +984,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
#endif /* CONFIG_MMU */ #endif /* CONFIG_MMU */
if (err) if (err)
goto give_sigsegv; return -EFAULT;
push_cache ((unsigned long) &frame->retcode); push_cache ((unsigned long) &frame->retcode);
...@@ -1005,7 +993,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -1005,7 +993,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
* to destroy is successfully copied to sigframe. * to destroy is successfully copied to sigframe.
*/ */
wrusp ((unsigned long) frame); wrusp ((unsigned long) frame);
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
adjustformat(regs); adjustformat(regs);
/* /*
...@@ -1031,10 +1019,6 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -1031,10 +1019,6 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
tregs->sr = regs->sr; tregs->sr = regs->sr;
} }
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return err;
} }
static inline void static inline void
...@@ -1074,26 +1058,22 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) ...@@ -1074,26 +1058,22 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static 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 err; int err;
/* are we from a system call? */ /* are we from a system call? */
if (regs->orig_d0 >= 0) if (regs->orig_d0 >= 0)
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
handle_restart(regs, ka, 1); handle_restart(regs, &ksig->ka, 1);
/* 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)
err = setup_rt_frame(sig, ka, info, oldset, regs); err = setup_rt_frame(ksig, oldset, regs);
else else
err = setup_frame(sig, ka, oldset, regs); err = setup_frame(ksig, oldset, regs);
if (err)
return;
signal_delivered(sig, info, ka, regs, 0); signal_setup_done(err, ksig, 0);
if (test_thread_flag(TIF_DELAYED_TRACE)) { if (test_thread_flag(TIF_DELAYED_TRACE)) {
regs->sr &= ~0x8000; regs->sr &= ~0x8000;
...@@ -1108,16 +1088,13 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -1108,16 +1088,13 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
siginfo_t info; struct ksignal ksig;
struct k_sigaction ka;
int signr;
current->thread.esp0 = (unsigned long) regs; current->thread.esp0 = (unsigned long) regs;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, regs); handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -140,13 +140,9 @@ static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -140,13 +140,9 @@ static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
/* /*
* Determine which stack to use.. * Determine which stack to use..
*/ */
static void __user *get_sigframe(struct k_sigaction *ka, unsigned long sp, static void __user *get_sigframe(struct ksignal *ksig, unsigned long sp)
size_t frame_size)
{ {
/* Meta stacks grows upwards */ sp = sigsp(sp, ksig);
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp;
sp = (sp + 7) & ~7; /* 8byte align stack */ sp = (sp + 7) & ~7; /* 8byte align stack */
return (void __user *)sp; return (void __user *)sp;
...@@ -159,7 +155,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, ...@@ -159,7 +155,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
int err; int err;
unsigned long code; unsigned long code;
frame = get_sigframe(&ksig->ka, regs->REG_SP, sizeof(*frame)); frame = get_sigframe(ksig, regs->REG_SP);
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return -EFAULT; return -EFAULT;
......
...@@ -145,22 +145,19 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, ...@@ -145,22 +145,19 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
* Determine which stack to use.. * Determine which stack to use..
*/ */
static inline void __user * static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size) get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size)
{ {
/* Default to using normal stack */ /* Default to using normal stack */
unsigned long sp = regs->r1; unsigned long sp = sigsp(regs->r1, ksig);
if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
return (void __user *)((sp - frame_size) & -8UL); return (void __user *)((sp - frame_size) & -8UL);
} }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0, sig = ksig->sig;
int signal; int signal;
unsigned long address = 0; unsigned long address = 0;
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
...@@ -168,10 +165,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -168,10 +165,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
pte_t *ptep; pte_t *ptep;
#endif #endif
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
signal = current_thread_info()->exec_domain signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -179,8 +176,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -179,8 +176,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
? current_thread_info()->exec_domain->signal_invmap[sig] ? current_thread_info()->exec_domain->signal_invmap[sig]
: sig; : sig;
if (info) if (ksig->ka.sa.sa_flags & SA_SIGINFO)
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);
...@@ -227,7 +224,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -227,7 +224,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
flush_dcache_range(address, address + 8); flush_dcache_range(address, address + 8);
#endif #endif
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->r1 = (unsigned long) frame; regs->r1 = (unsigned long) frame;
...@@ -237,7 +234,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -237,7 +234,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */ regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */ regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */
/* Offset to handle microblaze rtid r14, 0 */ /* Offset to handle microblaze rtid r14, 0 */
regs->pc = (unsigned long)ka->sa.sa_handler; regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
set_fs(USER_DS); set_fs(USER_DS);
...@@ -247,10 +244,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -247,10 +244,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
/* Handle restarting system calls */ /* Handle restarting system calls */
...@@ -283,23 +276,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler) ...@@ -283,23 +276,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(struct ksignal *ksig, struct pt_regs *regs)
siginfo_t *info, struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Set up the stack frame */ /* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO) ret = setup_rt_frame(ksig, oldset, regs);
ret = setup_rt_frame(sig, ka, info, oldset, regs);
else
ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
if (ret) signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
return;
signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
...@@ -313,21 +298,19 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -313,21 +298,19 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
*/ */
static void do_signal(struct pt_regs *regs, int in_syscall) static void do_signal(struct pt_regs *regs, int in_syscall)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
#ifdef DEBUG_SIG #ifdef DEBUG_SIG
pr_info("do signal: %p %d\n", regs, in_syscall); pr_info("do signal: %p %d\n", regs, in_syscall);
pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1, pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
regs->r12, current_thread_info()->flags); regs->r12, current_thread_info()->flags);
#endif #endif
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (in_syscall) if (in_syscall)
handle_restart(regs, &ka, 1); handle_restart(regs, &ksig.ka, 1);
handle_signal(signr, &ka, &info, regs); handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -13,13 +13,11 @@ ...@@ -13,13 +13,11 @@
#include <asm/siginfo.h> #include <asm/siginfo.h>
struct mips_abi { struct mips_abi {
int (* const setup_frame)(void *sig_return, struct k_sigaction *ka, int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, int signr, struct pt_regs *regs, sigset_t *set);
sigset_t *set);
const unsigned long signal_return_offset; const unsigned long signal_return_offset;
int (* const setup_rt_frame)(void *sig_return, struct k_sigaction *ka, int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, int signr, struct pt_regs *regs, sigset_t *set);
sigset_t *set, siginfo_t *info);
const unsigned long rt_signal_return_offset; const unsigned long rt_signal_return_offset;
const unsigned long restart; const unsigned long restart;
}; };
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
/* /*
* Determine which stack to use.. * Determine which stack to use..
*/ */
extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, extern void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
size_t frame_size); size_t frame_size);
/* Check and clear pending FPU exceptions in saved CSR */ /* Check and clear pending FPU exceptions in saved CSR */
extern int fpcsr_pending(unsigned int __user *fpcsr); extern int fpcsr_pending(unsigned int __user *fpcsr);
......
...@@ -280,7 +280,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) ...@@ -280,7 +280,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
return err; return err;
} }
void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
size_t frame_size) size_t frame_size)
{ {
unsigned long sp; unsigned long sp;
...@@ -295,9 +295,7 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -295,9 +295,7 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
*/ */
sp -= 32; sp -= 32;
/* This is the X/Open sanctioned signal stack switching. */ sp = sigsp(sp, ksig);
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size;
return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK)); return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
} }
...@@ -428,20 +426,20 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) ...@@ -428,20 +426,20 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
} }
#ifdef CONFIG_TRAD_SIGNALS #ifdef CONFIG_TRAD_SIGNALS
static int setup_frame(void *sig_return, struct k_sigaction *ka, static int setup_frame(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, int signr, sigset_t *set) struct pt_regs *regs, sigset_t *set)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; return -EFAULT;
err |= setup_sigcontext(regs, &frame->sf_sc); err |= setup_sigcontext(regs, &frame->sf_sc);
err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set)); err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Arguments to signal handler: * Arguments to signal handler:
...@@ -453,37 +451,32 @@ static int setup_frame(void *sig_return, struct k_sigaction *ka, ...@@ -453,37 +451,32 @@ static int setup_frame(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to the * $25 and c0_epc point to the signal handler, $29 points to the
* struct sigframe. * struct sigframe.
*/ */
regs->regs[ 4] = signr; regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = 0; regs->regs[ 5] = 0;
regs->regs[ 6] = (unsigned long) &frame->sf_sc; regs->regs[ 6] = (unsigned long) &frame->sf_sc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]); frame, regs->cp0_epc, regs->regs[31]);
return 0; return 0;
give_sigsegv:
force_sigsegv(signr, current);
return -EFAULT;
} }
#endif #endif
static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, int signr, sigset_t *set, struct pt_regs *regs, sigset_t *set)
siginfo_t *info)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; return -EFAULT;
/* Create siginfo. */ /* Create siginfo. */
err |= copy_siginfo_to_user(&frame->rs_info, info); err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_flags);
...@@ -493,7 +486,7 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, ...@@ -493,7 +486,7 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Arguments to signal handler: * Arguments to signal handler:
...@@ -505,22 +498,18 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka, ...@@ -505,22 +498,18 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to * $25 and c0_epc point to the signal handler, $29 points to
* the struct rt_sigframe. * the struct rt_sigframe.
*/ */
regs->regs[ 4] = signr; regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]); frame, regs->cp0_epc, regs->regs[31]);
return 0; return 0;
give_sigsegv:
force_sigsegv(signr, current);
return -EFAULT;
} }
struct mips_abi mips_abi = { struct mips_abi mips_abi = {
...@@ -534,8 +523,7 @@ struct mips_abi mips_abi = { ...@@ -534,8 +523,7 @@ struct mips_abi mips_abi = {
.restart = __NR_restart_syscall .restart = __NR_restart_syscall
}; };
static void handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct k_sigaction *ka, struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
...@@ -557,7 +545,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -557,7 +545,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[2] = EINTR; regs->regs[2] = EINTR;
break; break;
case ERESTARTSYS: case ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->regs[2] = EINTR; regs->regs[2] = EINTR;
break; break;
} }
...@@ -571,29 +559,23 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -571,29 +559,23 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[0] = 0; /* Don't deal with this again. */ regs->regs[0] = 0; /* Don't deal with this again. */
} }
if (sig_uses_siginfo(ka)) if (sig_uses_siginfo(&ksig->ka))
ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
ka, regs, sig, oldset, info); ksig, regs, oldset);
else else
ret = abi->setup_frame(vdso + abi->signal_return_offset, ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
ka, regs, sig, oldset); regs, oldset);
if (ret)
return;
signal_delivered(sig, info, ka, regs, 0); signal_setup_done(ret, ksig, 0);
} }
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct ksignal ksig;
siginfo_t info;
int signr;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, regs); handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -490,21 +490,21 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) ...@@ -490,21 +490,21 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
static int setup_frame_32(void *sig_return, struct k_sigaction *ka, static int setup_frame_32(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, int signr, sigset_t *set) struct pt_regs *regs, sigset_t *set)
{ {
struct sigframe32 __user *frame; struct sigframe32 __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; return -EFAULT;
err |= setup_sigcontext32(regs, &frame->sf_sc); err |= setup_sigcontext32(regs, &frame->sf_sc);
err |= __copy_conv_sigset_to_user(&frame->sf_mask, set); err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Arguments to signal handler: * Arguments to signal handler:
...@@ -516,37 +516,32 @@ static int setup_frame_32(void *sig_return, struct k_sigaction *ka, ...@@ -516,37 +516,32 @@ static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to the * $25 and c0_epc point to the signal handler, $29 points to the
* struct sigframe. * struct sigframe.
*/ */
regs->regs[ 4] = signr; regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = 0; regs->regs[ 5] = 0;
regs->regs[ 6] = (unsigned long) &frame->sf_sc; regs->regs[ 6] = (unsigned long) &frame->sf_sc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]); frame, regs->cp0_epc, regs->regs[31]);
return 0; return 0;
give_sigsegv:
force_sigsegv(signr, current);
return -EFAULT;
} }
static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka, static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, int signr, sigset_t *set, struct pt_regs *regs, sigset_t *set)
siginfo_t *info)
{ {
struct rt_sigframe32 __user *frame; struct rt_sigframe32 __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; return -EFAULT;
/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */ /* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
err |= copy_siginfo_to_user32(&frame->rs_info, info); err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_flags);
...@@ -556,7 +551,7 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka, ...@@ -556,7 +551,7 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Arguments to signal handler: * Arguments to signal handler:
...@@ -568,22 +563,18 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka, ...@@ -568,22 +563,18 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to * $25 and c0_epc point to the signal handler, $29 points to
* the struct rt_sigframe32. * the struct rt_sigframe32.
*/ */
regs->regs[ 4] = signr; regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]); frame, regs->cp0_epc, regs->regs[31]);
return 0; return 0;
give_sigsegv:
force_sigsegv(signr, current);
return -EFAULT;
} }
/* /*
......
...@@ -102,18 +102,18 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs) ...@@ -102,18 +102,18 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
force_sig(SIGSEGV, current); force_sig(SIGSEGV, current);
} }
static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka, static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info) struct pt_regs *regs, sigset_t *set)
{ {
struct rt_sigframe_n32 __user *frame; struct rt_sigframe_n32 __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
goto give_sigsegv; return -EFAULT;
/* Create siginfo. */ /* Create siginfo. */
err |= copy_siginfo_to_user32(&frame->rs_info, info); err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_flags);
...@@ -123,7 +123,7 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka, ...@@ -123,7 +123,7 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set); err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* /*
* Arguments to signal handler: * Arguments to signal handler:
...@@ -135,22 +135,18 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka, ...@@ -135,22 +135,18 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
* $25 and c0_epc point to the signal handler, $29 points to * $25 and c0_epc point to the signal handler, $29 points to
* the struct rt_sigframe. * the struct rt_sigframe.
*/ */
regs->regs[ 4] = signr; regs->regs[ 4] = ksig->sig;
regs->regs[ 5] = (unsigned long) &frame->rs_info; regs->regs[ 5] = (unsigned long) &frame->rs_info;
regs->regs[ 6] = (unsigned long) &frame->rs_uc; regs->regs[ 6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) frame; regs->regs[29] = (unsigned long) frame;
regs->regs[31] = (unsigned long) sig_return; regs->regs[31] = (unsigned long) sig_return;
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n", DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
current->comm, current->pid, current->comm, current->pid,
frame, regs->cp0_epc, regs->regs[31]); frame, regs->cp0_epc, regs->regs[31]);
return 0; return 0;
give_sigsegv:
force_sigsegv(signr, current);
return -EFAULT;
} }
struct mips_abi mips_abi_n32 = { struct mips_abi mips_abi_n32 = {
......
...@@ -186,20 +186,11 @@ static int setup_sigcontext(struct sigcontext __user *sc, ...@@ -186,20 +186,11 @@ static int setup_sigcontext(struct sigcontext __user *sc,
/* /*
* determine which stack to use.. * determine which stack to use..
*/ */
static inline void __user *get_sigframe(struct k_sigaction *ka, static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs, struct pt_regs *regs,
size_t frame_size) size_t frame_size)
{ {
unsigned long sp; unsigned long sp = sigsp(regs->sp, ksig);
/* default to using normal stack */
sp = regs->sp;
/* this is the X/Open sanctioned signal stack switching. */
if (ka->sa.sa_flags & SA_ONSTACK) {
if (sas_ss_flags(sp) == 0)
sp = current->sas_ss_sp + current->sas_ss_size;
}
return (void __user *) ((sp - frame_size) & ~7UL); return (void __user *) ((sp - frame_size) & ~7UL);
} }
...@@ -207,16 +198,16 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, ...@@ -207,16 +198,16 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
/* /*
* set up a normal signal frame * set up a normal signal frame
*/ */
static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, static int setup_frame(struct ksignal *ksig, sigset_t *set,
struct pt_regs *regs) struct pt_regs *regs)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
int rsig; int rsig, sig = ksig->sig;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
rsig = sig; rsig = sig;
if (sig < 32 && if (sig < 32 &&
...@@ -226,40 +217,40 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -226,40 +217,40 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
if (__put_user(rsig, &frame->sig) < 0 || if (__put_user(rsig, &frame->sig) < 0 ||
__put_user(&frame->sc, &frame->psc) < 0) __put_user(&frame->sc, &frame->psc) < 0)
goto give_sigsegv; return -EFAULT;
if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0])) if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
goto give_sigsegv; return -EFAULT;
if (_NSIG_WORDS > 1) { if (_NSIG_WORDS > 1) {
if (__copy_to_user(frame->extramask, &set->sig[1], if (__copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask))) sizeof(frame->extramask)))
goto give_sigsegv; return -EFAULT;
} }
/* set up to return from userspace. If provided, use a stub already in /* set up to return from userspace. If provided, use a stub already in
* userspace */ * userspace */
if (ka->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
if (__put_user(ka->sa.sa_restorer, &frame->pretcode)) if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
goto give_sigsegv; return -EFAULT;
} else { } else {
if (__put_user((void (*)(void))frame->retcode, if (__put_user((void (*)(void))frame->retcode,
&frame->pretcode)) &frame->pretcode))
goto give_sigsegv; return -EFAULT;
/* this is mov $,d0; syscall 0 */ /* this is mov $,d0; syscall 0 */
if (__put_user(0x2c, (char *)(frame->retcode + 0)) || if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
__put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) || __put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
__put_user(0x00, (char *)(frame->retcode + 2)) || __put_user(0x00, (char *)(frame->retcode + 2)) ||
__put_user(0xf0, (char *)(frame->retcode + 3)) || __put_user(0xf0, (char *)(frame->retcode + 3)) ||
__put_user(0xe0, (char *)(frame->retcode + 4))) __put_user(0xe0, (char *)(frame->retcode + 4)))
goto give_sigsegv; return -EFAULT;
flush_icache_range((unsigned long) frame->retcode, flush_icache_range((unsigned long) frame->retcode,
(unsigned long) frame->retcode + 5); (unsigned long) frame->retcode + 5);
} }
/* set up registers for signal handler */ /* set up registers for signal handler */
regs->sp = (unsigned long) frame; regs->sp = (unsigned long) frame;
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
regs->d0 = sig; regs->d0 = sig;
regs->d1 = (unsigned long) &frame->sc; regs->d1 = (unsigned long) &frame->sc;
...@@ -270,25 +261,21 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, ...@@ -270,25 +261,21 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
/* /*
* set up a realtime signal frame * set up a realtime signal frame
*/ */
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int rsig; int rsig, sig = ksig->sig;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
rsig = sig; rsig = sig;
if (sig < 32 && if (sig < 32 &&
...@@ -299,8 +286,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -299,8 +286,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__put_user(rsig, &frame->sig) || if (__put_user(rsig, &frame->sig) ||
__put_user(&frame->info, &frame->pinfo) || __put_user(&frame->info, &frame->pinfo) ||
__put_user(&frame->uc, &frame->puc) || __put_user(&frame->uc, &frame->puc) ||
copy_siginfo_to_user(&frame->info, info)) copy_siginfo_to_user(&frame->info, &ksig->info))
goto give_sigsegv; return -EFAULT;
/* create the ucontext. */ /* create the ucontext. */
if (__put_user(0, &frame->uc.uc_flags) || if (__put_user(0, &frame->uc.uc_flags) ||
...@@ -309,13 +296,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -309,13 +296,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
setup_sigcontext(&frame->uc.uc_mcontext, setup_sigcontext(&frame->uc.uc_mcontext,
&frame->fpuctx, regs, set->sig[0]) || &frame->fpuctx, regs, set->sig[0]) ||
__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set))) __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
goto give_sigsegv; return -EFAULT;
/* set up to return from userspace. If provided, use a stub already in /* set up to return from userspace. If provided, use a stub already in
* userspace */ * userspace */
if (ka->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
if (__put_user(ka->sa.sa_restorer, &frame->pretcode)) if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
goto give_sigsegv; return -EFAULT;
} else { } else {
if (__put_user((void(*)(void))frame->retcode, if (__put_user((void(*)(void))frame->retcode,
&frame->pretcode) || &frame->pretcode) ||
...@@ -326,7 +314,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -326,7 +314,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
__put_user(0x00, (char *)(frame->retcode + 2)) || __put_user(0x00, (char *)(frame->retcode + 2)) ||
__put_user(0xf0, (char *)(frame->retcode + 3)) || __put_user(0xf0, (char *)(frame->retcode + 3)) ||
__put_user(0xe0, (char *)(frame->retcode + 4))) __put_user(0xe0, (char *)(frame->retcode + 4)))
goto give_sigsegv; return -EFAULT;
flush_icache_range((u_long) frame->retcode, flush_icache_range((u_long) frame->retcode,
(u_long) frame->retcode + 5); (u_long) frame->retcode + 5);
...@@ -334,7 +322,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -334,7 +322,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->sp = (unsigned long) frame; regs->sp = (unsigned long) frame;
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
regs->d0 = sig; regs->d0 = sig;
regs->d1 = (long) &frame->info; regs->d1 = (long) &frame->info;
...@@ -345,10 +333,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -345,10 +333,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static inline void stepback(struct pt_regs *regs) static inline void stepback(struct pt_regs *regs)
...@@ -360,9 +344,7 @@ static inline void stepback(struct pt_regs *regs) ...@@ -360,9 +344,7 @@ static inline void stepback(struct pt_regs *regs)
/* /*
* handle the actual delivery of a signal to userspace * handle the actual delivery of a signal to userspace
*/ */
static int handle_signal(int sig, static int handle_signal(struct ksignal *ksig, struct pt_regs *regs)
siginfo_t *info, struct k_sigaction *ka,
struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
...@@ -377,7 +359,7 @@ static int handle_signal(int sig, ...@@ -377,7 +359,7 @@ static int handle_signal(int sig,
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->d0 = -EINTR; regs->d0 = -EINTR;
break; break;
} }
...@@ -390,15 +372,12 @@ static int handle_signal(int sig, ...@@ -390,15 +372,12 @@ static int handle_signal(int sig,
} }
/* 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(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)
return ret;
signal_delivered(sig, info, ka, regs, signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
test_thread_flag(TIF_SINGLESTEP));
return 0; return 0;
} }
...@@ -407,15 +386,10 @@ static int handle_signal(int sig, ...@@ -407,15 +386,10 @@ static int handle_signal(int sig,
*/ */
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct ksignal ksig;
siginfo_t info;
int signr;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
if (handle_signal(signr, &info, &ka, regs) == 0) {
}
if (get_signal(&ksig)) {
handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -132,30 +132,16 @@ static inline unsigned long align_sigframe(unsigned long sp) ...@@ -132,30 +132,16 @@ static inline unsigned long align_sigframe(unsigned long sp)
* or the alternate stack. * or the alternate stack.
*/ */
static inline void __user *get_sigframe(struct k_sigaction *ka, static inline void __user *get_sigframe(struct ksignal *ksig,
struct pt_regs *regs, size_t frame_size) struct pt_regs *regs, size_t frame_size)
{ {
unsigned long sp = regs->sp; unsigned long sp = regs->sp;
int onsigstack = on_sig_stack(sp);
/* redzone */ /* redzone */
sp -= STACK_FRAME_OVERHEAD; sp -= STACK_FRAME_OVERHEAD;
sp = sigsp(sp, ksig);
/* This is the X/Open sanctioned signal stack switching. */
if ((ka->sa.sa_flags & SA_ONSTACK) && !onsigstack) {
if (current->sas_ss_size)
sp = current->sas_ss_sp + current->sas_ss_size;
}
sp = align_sigframe(sp - frame_size); sp = align_sigframe(sp - frame_size);
/*
* If we are on the alternate signal stack and would overflow it, don't.
* Return an always-bogus address instead so we will die with SIGSEGV.
*/
if (onsigstack && !likely(on_sig_stack(sp)))
return (void __user *)-1L;
return (void __user *)sp; return (void __user *)sp;
} }
...@@ -173,7 +159,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, ...@@ -173,7 +159,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
unsigned long return_ip; unsigned long return_ip;
int err = 0; int err = 0;
frame = get_sigframe(&ksig->ka, regs, sizeof(*frame)); frame = get_sigframe(ksig, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return -EFAULT; return -EFAULT;
......
...@@ -227,8 +227,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_sysc ...@@ -227,8 +227,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_sysc
} }
static long static long
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, int in_syscall) int in_syscall)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
unsigned long rp, usp; unsigned long rp, usp;
...@@ -241,10 +241,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -241,10 +241,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
usp = (regs->gr[30] & ~(0x01UL)); usp = (regs->gr[30] & ~(0x01UL));
/*FIXME: frame_size parameter is unused, remove it. */ /*FIXME: frame_size parameter is unused, remove it. */
frame = get_sigframe(ka, usp, sizeof(*frame)); frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
DBG(1,"SETUP_RT_FRAME: START\n"); DBG(1,"SETUP_RT_FRAME: START\n");
DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info); DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
...@@ -253,7 +253,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -253,7 +253,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (is_compat_task()) { if (is_compat_task()) {
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info); DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
err |= copy_siginfo_to_user32(&compat_frame->info, info); err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]); err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc); DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext); DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
...@@ -265,7 +265,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -265,7 +265,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif #endif
{ {
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info); DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]); err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc); DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext); DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
...@@ -275,7 +275,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -275,7 +275,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* 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. The first words of tramp are used to already in userspace. The first words of tramp are used to
...@@ -312,9 +312,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -312,9 +312,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP]; rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
if (err) if (err)
goto give_sigsegv; return -EFAULT;
haddr = A(ka->sa.sa_handler); haddr = A(ksig->ka.sa.sa_handler);
/* The sa_handler may be a pointer to a function descriptor */ /* The sa_handler may be a pointer to a function descriptor */
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
if (is_compat_task()) { if (is_compat_task()) {
...@@ -326,7 +326,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -326,7 +326,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc)); err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
haddr = fdesc.addr; haddr = fdesc.addr;
regs->gr[19] = fdesc.gp; regs->gr[19] = fdesc.gp;
...@@ -339,7 +339,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -339,7 +339,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc)); err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
haddr = fdesc.addr; haddr = fdesc.addr;
regs->gr[19] = fdesc.gp; regs->gr[19] = fdesc.gp;
...@@ -386,7 +386,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -386,7 +386,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
regs->gr[2] = rp; /* userland return pointer */ regs->gr[2] = rp; /* userland return pointer */
regs->gr[26] = sig; /* signal number */ regs->gr[26] = ksig->sig; /* signal number */
#ifdef CONFIG_64BIT #ifdef CONFIG_64BIT
if (is_compat_task()) { if (is_compat_task()) {
...@@ -410,11 +410,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -410,11 +410,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, frame, regs->gr[30], current->comm, current->pid, frame, regs->gr[30],
regs->iaoq[0], regs->iaoq[1], rp); regs->iaoq[0], regs->iaoq[1], rp);
return 1;
give_sigsegv:
DBG(1,"setup_rt_frame: sending SIGSEGV\n");
force_sigsegv(sig, current);
return 0; return 0;
} }
...@@ -423,20 +418,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -423,20 +418,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void static void
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
struct pt_regs *regs, int in_syscall)
{ {
int ret;
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n", DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
sig, ka, info, oldset, regs); ksig->sig, ksig->ka, ksig->info, oldset, regs);
/* Set up the stack frame */ /* Set up the stack frame */
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall)) ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
return;
signal_delivered(sig, info, ka, regs, signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
test_thread_flag(TIF_SINGLESTEP) || test_thread_flag(TIF_BLOCKSTEP));
test_thread_flag(TIF_BLOCKSTEP));
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n", DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
regs->gr[28]); regs->gr[28]);
...@@ -544,22 +538,18 @@ insert_restart_trampoline(struct pt_regs *regs) ...@@ -544,22 +538,18 @@ insert_restart_trampoline(struct pt_regs *regs)
asmlinkage void asmlinkage void
do_signal(struct pt_regs *regs, long in_syscall) do_signal(struct pt_regs *regs, long in_syscall)
{ {
siginfo_t info; struct ksignal ksig;
struct k_sigaction ka;
int signr;
DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n", DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
regs, regs->sr[7], in_syscall); regs, regs->sr[7], in_syscall);
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
if (signr > 0) {
/* Restart a system call if necessary. */ /* Restart a system call if necessary. */
if (in_syscall) if (in_syscall)
syscall_restart(regs, &ka); syscall_restart(regs, &ksig.ka);
handle_signal(signr, &info, &ka, regs, in_syscall); handle_signal(&ksig, regs, in_syscall);
return; return;
} }
......
...@@ -31,20 +31,14 @@ int show_unhandled_signals = 1; ...@@ -31,20 +31,14 @@ int show_unhandled_signals = 1;
/* /*
* Allocate space for the signal frame * Allocate space for the signal frame
*/ */
void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp, void __user *get_sigframe(struct ksignal *ksig, unsigned long sp,
size_t frame_size, int is_32) size_t frame_size, int is_32)
{ {
unsigned long oldsp, newsp; unsigned long oldsp, newsp;
/* Default to using normal stack */ /* Default to using normal stack */
oldsp = get_clean_sp(sp, is_32); oldsp = get_clean_sp(sp, is_32);
oldsp = sigsp(oldsp, ksig);
/* Check for alt stack */
if ((ka->sa.sa_flags & SA_ONSTACK) &&
current->sas_ss_size && !on_sig_stack(oldsp))
oldsp = (current->sas_ss_sp + current->sas_ss_size);
/* Get aligned frame */
newsp = (oldsp - frame_size) & ~0xFUL; newsp = (oldsp - frame_size) & ~0xFUL;
/* Check access */ /* Check access */
...@@ -105,25 +99,23 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, ...@@ -105,25 +99,23 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
} }
} }
static int do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
int ret; int ret;
int is32 = is_32bit_task(); int is32 = is_32bit_task();
signr = get_signal_to_deliver(&info, &ka, regs, NULL); get_signal(&ksig);
/* Is there any syscall restart business here ? */ /* Is there any syscall restart business here ? */
check_syscall_restart(regs, &ka, signr > 0); check_syscall_restart(regs, &ksig.ka, ksig.sig > 0);
if (signr <= 0) { if (ksig.sig <= 0) {
/* No signal to deliver -- put the saved sigmask back */ /* No signal to deliver -- put the saved sigmask back */
restore_saved_sigmask(); restore_saved_sigmask();
regs->trap = 0; regs->trap = 0;
return 0; /* no signals delivered */ return; /* no signals delivered */
} }
#ifndef CONFIG_PPC_ADV_DEBUG_REGS #ifndef CONFIG_PPC_ADV_DEBUG_REGS
...@@ -140,23 +132,16 @@ static int do_signal(struct pt_regs *regs) ...@@ -140,23 +132,16 @@ static int do_signal(struct pt_regs *regs)
thread_change_pc(current, regs); thread_change_pc(current, regs);
if (is32) { if (is32) {
if (ka.sa.sa_flags & SA_SIGINFO) if (ksig.ka.sa.sa_flags & SA_SIGINFO)
ret = handle_rt_signal32(signr, &ka, &info, oldset, ret = handle_rt_signal32(&ksig, oldset, regs);
regs);
else else
ret = handle_signal32(signr, &ka, &info, oldset, ret = handle_signal32(&ksig, oldset, regs);
regs);
} else { } else {
ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); ret = handle_rt_signal64(&ksig, oldset, regs);
} }
regs->trap = 0; regs->trap = 0;
if (ret) { signal_setup_done(ret, &ksig, test_thread_flag(TIF_SINGLESTEP));
signal_delivered(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return ret;
} }
void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
......
...@@ -12,15 +12,13 @@ ...@@ -12,15 +12,13 @@
extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags); extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp, extern void __user *get_sigframe(struct ksignal *ksig, unsigned long sp,
size_t frame_size, int is_32); size_t frame_size, int is_32);
extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, extern int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs); struct pt_regs *regs);
extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, extern int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs); struct pt_regs *regs);
extern unsigned long copy_fpr_to_user(void __user *to, extern unsigned long copy_fpr_to_user(void __user *to,
...@@ -44,14 +42,12 @@ extern unsigned long copy_transact_vsx_from_user(struct task_struct *task, ...@@ -44,14 +42,12 @@ extern unsigned long copy_transact_vsx_from_user(struct task_struct *task,
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
extern int handle_rt_signal64(int signr, struct k_sigaction *ka, extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
siginfo_t *info, sigset_t *set,
struct pt_regs *regs); struct pt_regs *regs);
#else /* CONFIG_PPC64 */ #else /* CONFIG_PPC64 */
static inline int handle_rt_signal64(int signr, struct k_sigaction *ka, static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
siginfo_t *info, sigset_t *set,
struct pt_regs *regs) struct pt_regs *regs)
{ {
return -EFAULT; return -EFAULT;
......
...@@ -981,9 +981,8 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) ...@@ -981,9 +981,8 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
* Set up a signal frame for a "real-time" signal handler * Set up a signal frame for a "real-time" signal handler
* (one which gets siginfo). * (one which gets siginfo).
*/ */
int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
struct pt_regs *regs)
{ {
struct rt_sigframe __user *rt_sf; struct rt_sigframe __user *rt_sf;
struct mcontext __user *frame; struct mcontext __user *frame;
...@@ -995,13 +994,13 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -995,13 +994,13 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
/* Set up Signal Frame */ /* Set up Signal Frame */
/* Put a Real Time Context onto stack */ /* Put a Real Time Context onto stack */
rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1); rt_sf = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
addr = rt_sf; addr = rt_sf;
if (unlikely(rt_sf == NULL)) if (unlikely(rt_sf == NULL))
goto badframe; goto badframe;
/* Put the siginfo & fill in most of the ucontext */ /* Put the siginfo & fill in most of the ucontext */
if (copy_siginfo_to_user(&rt_sf->info, info) if (copy_siginfo_to_user(&rt_sf->info, &ksig->info)
|| __put_user(0, &rt_sf->uc.uc_flags) || __put_user(0, &rt_sf->uc.uc_flags)
|| __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1]) || __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1])
|| __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext), || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext),
...@@ -1051,15 +1050,15 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1051,15 +1050,15 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
/* Fill registers for signal handler */ /* Fill registers for signal handler */
regs->gpr[1] = newsp; regs->gpr[1] = newsp;
regs->gpr[3] = sig; regs->gpr[3] = ksig->sig;
regs->gpr[4] = (unsigned long) &rt_sf->info; regs->gpr[4] = (unsigned long) &rt_sf->info;
regs->gpr[5] = (unsigned long) &rt_sf->uc; regs->gpr[5] = (unsigned long) &rt_sf->uc;
regs->gpr[6] = (unsigned long) rt_sf; regs->gpr[6] = (unsigned long) rt_sf;
regs->nip = (unsigned long) ka->sa.sa_handler; regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
/* enter the signal handler in native-endian mode */ /* enter the signal handler in native-endian mode */
regs->msr &= ~MSR_LE; regs->msr &= ~MSR_LE;
regs->msr |= (MSR_KERNEL & MSR_LE); regs->msr |= (MSR_KERNEL & MSR_LE);
return 1; return 0;
badframe: badframe:
if (show_unhandled_signals) if (show_unhandled_signals)
...@@ -1069,8 +1068,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1069,8 +1068,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
current->comm, current->pid, current->comm, current->pid,
addr, regs->nip, regs->link); addr, regs->nip, regs->link);
force_sigsegv(sig, current); return 1;
return 0;
} }
static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig) static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
...@@ -1409,8 +1407,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, ...@@ -1409,8 +1407,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
int handle_signal32(unsigned long sig, struct k_sigaction *ka, int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs)
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{ {
struct sigcontext __user *sc; struct sigcontext __user *sc;
struct sigframe __user *frame; struct sigframe __user *frame;
...@@ -1420,7 +1417,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1420,7 +1417,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
unsigned long tramp; unsigned long tramp;
/* Set up Signal Frame */ /* Set up Signal Frame */
frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1); frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 1);
if (unlikely(frame == NULL)) if (unlikely(frame == NULL))
goto badframe; goto badframe;
sc = (struct sigcontext __user *) &frame->sctx; sc = (struct sigcontext __user *) &frame->sctx;
...@@ -1428,7 +1425,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1428,7 +1425,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
#if _NSIG != 64 #if _NSIG != 64
#error "Please adjust handle_signal()" #error "Please adjust handle_signal()"
#endif #endif
if (__put_user(to_user_ptr(ka->sa.sa_handler), &sc->handler) if (__put_user(to_user_ptr(ksig->ka.sa.sa_handler), &sc->handler)
|| __put_user(oldset->sig[0], &sc->oldmask) || __put_user(oldset->sig[0], &sc->oldmask)
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
|| __put_user((oldset->sig[0] >> 32), &sc->_unused[3]) || __put_user((oldset->sig[0] >> 32), &sc->_unused[3])
...@@ -1436,7 +1433,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1436,7 +1433,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|| __put_user(oldset->sig[1], &sc->_unused[3]) || __put_user(oldset->sig[1], &sc->_unused[3])
#endif #endif
|| __put_user(to_user_ptr(&frame->mctx), &sc->regs) || __put_user(to_user_ptr(&frame->mctx), &sc->regs)
|| __put_user(sig, &sc->signal)) || __put_user(ksig->sig, &sc->signal))
goto badframe; goto badframe;
if (vdso32_sigtramp && current->mm->context.vdso_base) { if (vdso32_sigtramp && current->mm->context.vdso_base) {
...@@ -1471,12 +1468,12 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1471,12 +1468,12 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
goto badframe; goto badframe;
regs->gpr[1] = newsp; regs->gpr[1] = newsp;
regs->gpr[3] = sig; regs->gpr[3] = ksig->sig;
regs->gpr[4] = (unsigned long) sc; regs->gpr[4] = (unsigned long) sc;
regs->nip = (unsigned long) ka->sa.sa_handler; regs->nip = (unsigned long) (unsigned long)ksig->ka.sa.sa_handler;
/* enter the signal handler in big-endian mode */ /* enter the signal handler in big-endian mode */
regs->msr &= ~MSR_LE; regs->msr &= ~MSR_LE;
return 1; return 0;
badframe: badframe:
if (show_unhandled_signals) if (show_unhandled_signals)
...@@ -1486,8 +1483,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1486,8 +1483,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
current->comm, current->pid, current->comm, current->pid,
frame, regs->nip, regs->link); frame, regs->nip, regs->link);
force_sigsegv(sig, current); return 1;
return 0;
} }
/* /*
......
...@@ -708,20 +708,19 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -708,20 +708,19 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
return 0; return 0;
} }
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
sigset_t *set, struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
unsigned long newsp = 0; unsigned long newsp = 0;
long err = 0; long err = 0;
frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0); frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 0);
if (unlikely(frame == NULL)) if (unlikely(frame == NULL))
goto badframe; goto badframe;
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err) if (err)
goto badframe; goto badframe;
...@@ -736,15 +735,15 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -736,15 +735,15 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); err |= __put_user(&frame->uc_transact, &frame->uc.uc_link);
err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
&frame->uc_transact.uc_mcontext, &frame->uc_transact.uc_mcontext,
regs, signr, regs, ksig->sig,
NULL, NULL,
(unsigned long)ka->sa.sa_handler); (unsigned long)ksig->ka.sa.sa_handler);
} else } else
#endif #endif
{ {
err |= __put_user(0, &frame->uc.uc_link); err |= __put_user(0, &frame->uc.uc_link);
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, ksig->sig,
NULL, (unsigned long)ka->sa.sa_handler, NULL, (unsigned long)ksig->ka.sa.sa_handler,
1); 1);
} }
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
...@@ -770,7 +769,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -770,7 +769,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
/* Set up "regs" so we "return" to the signal handler. */ /* Set up "regs" so we "return" to the signal handler. */
if (is_elf2_task()) { if (is_elf2_task()) {
regs->nip = (unsigned long) ka->sa.sa_handler; regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
regs->gpr[12] = regs->nip; regs->gpr[12] = regs->nip;
} else { } else {
/* Handler is *really* a pointer to the function descriptor for /* Handler is *really* a pointer to the function descriptor for
...@@ -779,7 +778,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -779,7 +778,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
* entry is the TOC value we need to use. * entry is the TOC value we need to use.
*/ */
func_descr_t __user *funct_desc_ptr = func_descr_t __user *funct_desc_ptr =
(func_descr_t __user *) ka->sa.sa_handler; (func_descr_t __user *) ksig->ka.sa.sa_handler;
err |= get_user(regs->nip, &funct_desc_ptr->entry); err |= get_user(regs->nip, &funct_desc_ptr->entry);
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
...@@ -789,9 +788,9 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -789,9 +788,9 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
regs->msr &= ~MSR_LE; regs->msr &= ~MSR_LE;
regs->msr |= (MSR_KERNEL & MSR_LE); regs->msr |= (MSR_KERNEL & MSR_LE);
regs->gpr[1] = newsp; regs->gpr[1] = newsp;
regs->gpr[3] = signr; regs->gpr[3] = ksig->sig;
regs->result = 0; regs->result = 0;
if (ka->sa.sa_flags & SA_SIGINFO) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo);
err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc);
regs->gpr[6] = (unsigned long) frame; regs->gpr[6] = (unsigned long) frame;
...@@ -801,7 +800,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -801,7 +800,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
if (err) if (err)
goto badframe; goto badframe;
return 1; return 0;
badframe: badframe:
if (show_unhandled_signals) if (show_unhandled_signals)
...@@ -809,6 +808,5 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, ...@@ -809,6 +808,5 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
current->comm, current->pid, "setup_rt_frame", current->comm, current->pid, "setup_rt_frame",
(long)frame, regs->nip, regs->link); (long)frame, regs->nip, regs->link);
force_sigsegv(signr, current); return 1;
return 0;
} }
...@@ -320,38 +320,39 @@ static inline int map_signal(int sig) ...@@ -320,38 +320,39 @@ static inline int map_signal(int sig)
return sig; return sig;
} }
static int setup_frame32(int sig, struct k_sigaction *ka, static int setup_frame32(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs * regs) struct pt_regs *regs)
{ {
sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32)); int sig = ksig->sig;
sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(sigframe32));
if (frame == (void __user *) -1UL) if (frame == (void __user *) -1UL)
goto give_sigsegv; return -EFAULT;
if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32)) if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
goto give_sigsegv; return -EFAULT;
if (save_sigregs32(regs, &frame->sregs)) if (save_sigregs32(regs, &frame->sregs))
goto give_sigsegv; return -EFAULT;
if (save_sigregs_gprs_high(regs, frame->gprs_high)) if (save_sigregs_gprs_high(regs, frame->gprs_high))
goto give_sigsegv; return -EFAULT;
if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs)) if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
goto give_sigsegv; return -EFAULT;
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE; regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
} else { } else {
regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE; regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
(u16 __force __user *)(frame->retcode))) (u16 __force __user *)(frame->retcode)))
goto give_sigsegv; return -EFAULT;
} }
/* Set up backchain. */ /* Set up backchain. */
if (__put_user(regs->gprs[15], (unsigned int __user *) frame)) if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->gprs[15] = (__force __u64) frame; regs->gprs[15] = (__force __u64) frame;
...@@ -359,7 +360,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka, ...@@ -359,7 +360,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
regs->psw.mask = PSW_MASK_BA | regs->psw.mask = PSW_MASK_BA |
(PSW_USER_BITS & PSW_MASK_ASC) | (PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC); (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__force __u64) ka->sa.sa_handler; regs->psw.addr = (__force __u64) ksig->ka.sa.sa_handler;
regs->gprs[2] = map_signal(sig); regs->gprs[2] = map_signal(sig);
regs->gprs[3] = (__force __u64) &frame->sc; regs->gprs[3] = (__force __u64) &frame->sc;
...@@ -376,25 +377,21 @@ static int setup_frame32(int sig, struct k_sigaction *ka, ...@@ -376,25 +377,21 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
/* Place signal number on stack to allow backtrace from handler. */ /* Place signal number on stack to allow backtrace from handler. */
if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo)) if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
goto give_sigsegv; return -EFAULT;
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs * regs) struct pt_regs *regs)
{ {
int err = 0; int err = 0;
rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32)); rt_sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe32));
if (frame == (void __user *) -1UL) if (frame == (void __user *) -1UL)
goto give_sigsegv; return -EFAULT;
if (copy_siginfo_to_user32(&frame->info, info)) if (copy_siginfo_to_user32(&frame->info, &ksig->info))
goto give_sigsegv; return -EFAULT;
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags); err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
...@@ -404,22 +401,22 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -404,22 +401,22 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= save_sigregs_gprs_high(regs, frame->gprs_high); err |= save_sigregs_gprs_high(regs, frame->gprs_high);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE; regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
} else { } else {
regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE; regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
(u16 __force __user *)(frame->retcode))) (u16 __force __user *)(frame->retcode)))
goto give_sigsegv; return -EFAULT;
} }
/* Set up backchain. */ /* Set up backchain. */
if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame)) if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->gprs[15] = (__force __u64) frame; regs->gprs[15] = (__force __u64) frame;
...@@ -427,36 +424,30 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -427,36 +424,30 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->psw.mask = PSW_MASK_BA | regs->psw.mask = PSW_MASK_BA |
(PSW_USER_BITS & PSW_MASK_ASC) | (PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC); (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (__u64 __force) ka->sa.sa_handler; regs->psw.addr = (__u64 __force) ksig->ka.sa.sa_handler;
regs->gprs[2] = map_signal(sig); regs->gprs[2] = map_signal(ksig->sig);
regs->gprs[3] = (__force __u64) &frame->info; regs->gprs[3] = (__force __u64) &frame->info;
regs->gprs[4] = (__force __u64) &frame->uc; regs->gprs[4] = (__force __u64) &frame->uc;
regs->gprs[5] = task_thread_info(current)->last_break; regs->gprs[5] = task_thread_info(current)->last_break;
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
void handle_signal32(unsigned long sig, struct k_sigaction *ka, void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
int ret; int ret;
/* 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_frame32(sig, ka, info, oldset, regs); ret = setup_rt_frame32(ksig, oldset, regs);
else else
ret = setup_frame32(sig, ka, oldset, regs); ret = setup_frame32(ksig, oldset, regs);
if (ret)
return; signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLE_STEP));
} }
...@@ -48,8 +48,8 @@ void do_per_trap(struct pt_regs *regs); ...@@ -48,8 +48,8 @@ void do_per_trap(struct pt_regs *regs);
void syscall_trace(struct pt_regs *regs, int entryexit); void syscall_trace(struct pt_regs *regs, int entryexit);
void kernel_stack_overflow(struct pt_regs * regs); void kernel_stack_overflow(struct pt_regs * regs);
void do_signal(struct pt_regs *regs); void do_signal(struct pt_regs *regs);
void handle_signal32(unsigned long sig, struct k_sigaction *ka, void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); struct pt_regs *regs);
void do_notify_resume(struct pt_regs *regs); void do_notify_resume(struct pt_regs *regs);
void __init init_IRQ(void); void __init init_IRQ(void);
......
...@@ -200,15 +200,15 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -200,15 +200,15 @@ static int setup_frame(int sig, struct k_sigaction *ka,
frame = get_sigframe(ka, regs, sizeof(sigframe)); frame = get_sigframe(ka, regs, sizeof(sigframe));
if (frame == (void __user *) -1UL) if (frame == (void __user *) -1UL)
goto give_sigsegv; return -EFAULT;
if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE)) if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
goto give_sigsegv; return -EFAULT;
if (save_sigregs(regs, &frame->sregs)) if (save_sigregs(regs, &frame->sregs))
goto give_sigsegv; return -EFAULT;
if (__put_user(&frame->sregs, &frame->sc.sregs)) if (__put_user(&frame->sregs, &frame->sc.sregs))
goto give_sigsegv; return -EFAULT;
/* 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. */
...@@ -220,12 +220,12 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -220,12 +220,12 @@ static int setup_frame(int sig, struct k_sigaction *ka,
frame->retcode | PSW_ADDR_AMODE; frame->retcode | PSW_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
(u16 __user *)(frame->retcode))) (u16 __user *)(frame->retcode)))
goto give_sigsegv; return -EFAULT;
} }
/* Set up backchain. */ /* Set up backchain. */
if (__put_user(regs->gprs[15], (addr_t __user *) frame)) if (__put_user(regs->gprs[15], (addr_t __user *) frame))
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame; regs->gprs[15] = (unsigned long) frame;
...@@ -250,27 +250,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -250,27 +250,23 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Place signal number on stack to allow backtrace from handler. */ /* Place signal number on stack to allow backtrace from handler. */
if (__put_user(regs->gprs[2], (int __user *) &frame->signo)) if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
goto give_sigsegv; return -EFAULT;
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs * regs) struct pt_regs *regs)
{ {
int err = 0; int err = 0;
rt_sigframe __user *frame; rt_sigframe __user *frame;
frame = get_sigframe(ka, regs, sizeof(rt_sigframe)); frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe));
if (frame == (void __user *) -1UL) if (frame == (void __user *) -1UL)
goto give_sigsegv; return -EFAULT;
if (copy_siginfo_to_user(&frame->info, info)) if (copy_siginfo_to_user(&frame->info, &ksig->info))
goto give_sigsegv; return -EFAULT;
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_flags);
...@@ -279,24 +275,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -279,24 +275,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= save_sigregs(regs, &frame->uc.uc_mcontext); err |= save_sigregs(regs, &frame->uc.uc_mcontext);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
regs->gprs[14] = (unsigned long) regs->gprs[14] = (unsigned long)
ka->sa.sa_restorer | PSW_ADDR_AMODE; ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE;
} else { } else {
regs->gprs[14] = (unsigned long) regs->gprs[14] = (unsigned long)
frame->retcode | PSW_ADDR_AMODE; frame->retcode | PSW_ADDR_AMODE;
if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
(u16 __user *)(frame->retcode))) (u16 __user *)(frame->retcode)))
goto give_sigsegv; return -EFAULT;
} }
/* Set up backchain. */ /* Set up backchain. */
if (__put_user(regs->gprs[15], (addr_t __user *) frame)) if (__put_user(regs->gprs[15], (addr_t __user *) frame))
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->gprs[15] = (unsigned long) frame; regs->gprs[15] = (unsigned long) frame;
...@@ -304,34 +300,27 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -304,34 +300,27 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
(PSW_USER_BITS & PSW_MASK_ASC) | (PSW_USER_BITS & PSW_MASK_ASC) |
(regs->psw.mask & ~PSW_MASK_ASC); (regs->psw.mask & ~PSW_MASK_ASC);
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->psw.addr = (unsigned long) ksig->ka.sa.sa_handler | PSW_ADDR_AMODE;
regs->gprs[2] = map_signal(sig); regs->gprs[2] = map_signal(ksig->sig);
regs->gprs[3] = (unsigned long) &frame->info; regs->gprs[3] = (unsigned long) &frame->info;
regs->gprs[4] = (unsigned long) &frame->uc; regs->gprs[4] = (unsigned long) &frame->uc;
regs->gprs[5] = task_thread_info(current)->last_break; regs->gprs[5] = task_thread_info(current)->last_break;
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static void handle_signal(unsigned long sig, struct k_sigaction *ka, static void handle_signal(struct ksignal *ksig, sigset_t *oldset,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
struct pt_regs *regs)
{ {
int ret; int ret;
/* 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(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->sig, &ksig->ka, oldset, regs);
if (ret)
return; signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLE_STEP));
} }
/* /*
...@@ -345,9 +334,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -345,9 +334,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
*/ */
void do_signal(struct pt_regs *regs) void do_signal(struct pt_regs *regs)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
/* /*
...@@ -357,9 +344,8 @@ void do_signal(struct pt_regs *regs) ...@@ -357,9 +344,8 @@ void do_signal(struct pt_regs *regs)
*/ */
current_thread_info()->system_call = current_thread_info()->system_call =
test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0; test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0;
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (get_signal(&ksig)) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (current_thread_info()->system_call) { if (current_thread_info()->system_call) {
regs->int_code = current_thread_info()->system_call; regs->int_code = current_thread_info()->system_call;
...@@ -370,7 +356,7 @@ void do_signal(struct pt_regs *regs) ...@@ -370,7 +356,7 @@ void do_signal(struct pt_regs *regs)
regs->gprs[2] = -EINTR; regs->gprs[2] = -EINTR;
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka.sa.sa_flags & SA_RESTART)) { if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
regs->gprs[2] = -EINTR; regs->gprs[2] = -EINTR;
break; break;
} }
...@@ -387,9 +373,9 @@ void do_signal(struct pt_regs *regs) ...@@ -387,9 +373,9 @@ void do_signal(struct pt_regs *regs)
clear_pt_regs_flag(regs, PIF_SYSCALL); clear_pt_regs_flag(regs, PIF_SYSCALL);
if (is_compat_task()) if (is_compat_task())
handle_signal32(signr, &ka, &info, oldset, regs); handle_signal32(&ksig, oldset, regs);
else else
handle_signal(signr, &ka, &info, oldset, regs); handle_signal(&ksig, oldset, regs);
return; return;
} }
......
...@@ -173,15 +173,15 @@ score_rt_sigreturn(struct pt_regs *regs) ...@@ -173,15 +173,15 @@ score_rt_sigreturn(struct pt_regs *regs)
return 0; return 0;
} }
static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
int signr, sigset_t *set, siginfo_t *info) sigset_t *set)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
/* /*
* Set up the return code ... * Set up the return code ...
...@@ -194,7 +194,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -194,7 +194,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __put_user(0x80008002, frame->rs_code + 1); err |= __put_user(0x80008002, frame->rs_code + 1);
flush_cache_sigtramp((unsigned long) frame->rs_code); flush_cache_sigtramp((unsigned long) frame->rs_code);
err |= copy_siginfo_to_user(&frame->rs_info, info); err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
err |= __put_user(0, &frame->rs_uc.uc_flags); err |= __put_user(0, &frame->rs_uc.uc_flags);
err |= __put_user(NULL, &frame->rs_uc.uc_link); err |= __put_user(NULL, &frame->rs_uc.uc_link);
err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[0]); err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[0]);
...@@ -202,26 +202,23 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, ...@@ -202,26 +202,23 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; return -EFAULT;
regs->regs[0] = (unsigned long) frame; regs->regs[0] = (unsigned long) frame;
regs->regs[3] = (unsigned long) frame->rs_code; regs->regs[3] = (unsigned long) frame->rs_code;
regs->regs[4] = signr; regs->regs[4] = ksig->sig;
regs->regs[5] = (unsigned long) &frame->rs_info; regs->regs[5] = (unsigned long) &frame->rs_info;
regs->regs[6] = (unsigned long) &frame->rs_uc; regs->regs[6] = (unsigned long) &frame->rs_uc;
regs->regs[29] = (unsigned long) ka->sa.sa_handler; regs->regs[29] = (unsigned long) ksig->ka.sa.sa_handler;
regs->cp0_epc = (unsigned long) ka->sa.sa_handler; regs->cp0_epc = (unsigned long) ksig->ka.sa.sa_handler;
return 0; return 0;
give_sigsegv:
force_sigsegv(signr, current);
return -EFAULT;
} }
static void handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct k_sigaction *ka, struct pt_regs *regs)
{ {
int ret;
if (regs->is_syscall) { if (regs->is_syscall) {
switch (regs->regs[4]) { switch (regs->regs[4]) {
case ERESTART_RESTARTBLOCK: case ERESTART_RESTARTBLOCK:
...@@ -229,7 +226,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -229,7 +226,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
regs->regs[4] = EINTR; regs->regs[4] = EINTR;
break; break;
case ERESTARTSYS: case ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->regs[4] = EINTR; regs->regs[4] = EINTR;
break; break;
} }
...@@ -245,17 +242,14 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -245,17 +242,14 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
/* /*
* Set up the stack frame * Set up the stack frame
*/ */
if (setup_rt_frame(ka, regs, sig, sigmask_to_save(), info) < 0) ret = setup_rt_frame(ksig, regs, sigmask_to_save());
return;
signal_delivered(sig, info, ka, regs, 0); signal_setup_done(ret, ksig, 0);
} }
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct ksignal ksig;
siginfo_t info;
int signr;
/* /*
* We want the common case to go fast, which is why we may in certain * We want the common case to go fast, which is why we may in certain
...@@ -265,10 +259,9 @@ static void do_signal(struct pt_regs *regs) ...@@ -265,10 +259,9 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Actually deliver the signal. */ /* Actually deliver the signal. */
handle_signal(signr, &info, &ka, regs); handle_signal(&ksig, regs);
return; return;
} }
......
...@@ -262,17 +262,17 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) ...@@ -262,17 +262,17 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
extern void __kernel_sigreturn(void); extern void __kernel_sigreturn(void);
extern void __kernel_rt_sigreturn(void); extern void __kernel_rt_sigreturn(void);
static int setup_frame(int sig, struct k_sigaction *ka, static int setup_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
int err = 0; int err = 0, sig = ksig->sig;
int signal; int signal;
frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
signal = current_thread_info()->exec_domain signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -288,8 +288,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -288,8 +288,8 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
regs->pr = (unsigned long) ka->sa.sa_restorer; regs->pr = (unsigned long) ksig->ka.sa.sa_restorer;
#ifdef CONFIG_VSYSCALL #ifdef CONFIG_VSYSCALL
} else if (likely(current->mm->context.vdso)) { } else if (likely(current->mm->context.vdso)) {
regs->pr = VDSO_SYM(&__kernel_sigreturn); regs->pr = VDSO_SYM(&__kernel_sigreturn);
...@@ -309,7 +309,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -309,7 +309,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->regs[15] = (unsigned long) frame; regs->regs[15] = (unsigned long) frame;
...@@ -319,15 +319,15 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -319,15 +319,15 @@ static int setup_frame(int sig, struct k_sigaction *ka,
if (current->personality & FDPIC_FUNCPTRS) { if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr = struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor __user *)ka->sa.sa_handler; (struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler;
err |= __get_user(regs->pc, &funcptr->text); err |= __get_user(regs->pc, &funcptr->text);
err |= __get_user(regs->regs[12], &funcptr->GOT); err |= __get_user(regs->regs[12], &funcptr->GOT);
} else } else
regs->pc = (unsigned long)ka->sa.sa_handler; regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
if (err) if (err)
goto give_sigsegv; return -EFAULT;
set_fs(USER_DS); set_fs(USER_DS);
...@@ -335,23 +335,19 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -335,23 +335,19 @@ static int setup_frame(int sig, struct k_sigaction *ka,
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0, sig = ksig->sig;
int signal; int signal;
frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
signal = current_thread_info()->exec_domain signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -359,7 +355,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -359,7 +355,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
? current_thread_info()->exec_domain->signal_invmap[sig] ? current_thread_info()->exec_domain->signal_invmap[sig]
: sig; : sig;
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);
...@@ -371,8 +367,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -371,8 +367,8 @@ static int 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
regs->pr = (unsigned long) ka->sa.sa_restorer; regs->pr = (unsigned long) ksig->ka.sa.sa_restorer;
#ifdef CONFIG_VSYSCALL #ifdef CONFIG_VSYSCALL
} else if (likely(current->mm->context.vdso)) { } else if (likely(current->mm->context.vdso)) {
regs->pr = VDSO_SYM(&__kernel_rt_sigreturn); regs->pr = VDSO_SYM(&__kernel_rt_sigreturn);
...@@ -392,7 +388,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -392,7 +388,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
} }
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->regs[15] = (unsigned long) frame; regs->regs[15] = (unsigned long) frame;
...@@ -402,15 +398,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -402,15 +398,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (current->personality & FDPIC_FUNCPTRS) { if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr = struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor __user *)ka->sa.sa_handler; (struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler;
err |= __get_user(regs->pc, &funcptr->text); err |= __get_user(regs->pc, &funcptr->text);
err |= __get_user(regs->regs[12], &funcptr->GOT); err |= __get_user(regs->regs[12], &funcptr->GOT);
} else } else
regs->pc = (unsigned long)ka->sa.sa_handler; regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
if (err) if (err)
goto give_sigsegv; return -EFAULT;
set_fs(USER_DS); set_fs(USER_DS);
...@@ -418,10 +414,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -418,10 +414,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static inline void static inline void
...@@ -455,22 +447,18 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs, ...@@ -455,22 +447,18 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(struct ksignal *ksig, struct pt_regs *regs, unsigned int save_r0)
struct pt_regs *regs, unsigned int save_r0)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* 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(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, test_thread_flag(TIF_SINGLESTEP));
return;
signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
...@@ -484,9 +472,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -484,9 +472,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void do_signal(struct pt_regs *regs, unsigned int save_r0) static void do_signal(struct pt_regs *regs, unsigned int save_r0)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -497,12 +483,11 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) ...@@ -497,12 +483,11 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) { handle_syscall_restart(save_r0, regs, &ksig.ka.sa);
handle_syscall_restart(save_r0, regs, &ka.sa);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &ka, &info, regs, save_r0); handle_signal(&ksig, regs, save_r0);
return; return;
} }
......
...@@ -41,8 +41,7 @@ ...@@ -41,8 +41,7 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
static void static void
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(struct ksignal *ksig, struct pt_regs *regs);
struct pt_regs * regs);
static inline void static inline void
handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
...@@ -82,9 +81,7 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) ...@@ -82,9 +81,7 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
*/ */
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -95,12 +92,11 @@ static void do_signal(struct pt_regs *regs) ...@@ -95,12 +92,11 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, 0); if (get_signal(&ksig)) {
if (signr > 0) { handle_syscall_restart(regs, &ksig.ka.sa);
handle_syscall_restart(regs, &ka.sa);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, regs); handle_signal(&ksig, regs);
return; return;
} }
...@@ -378,17 +374,16 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) ...@@ -378,17 +374,16 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
void sa_default_restorer(void); /* See comments below */ void sa_default_restorer(void); /* See comments below */
void sa_default_rt_restorer(void); /* See comments below */ void sa_default_rt_restorer(void); /* See comments below */
static int setup_frame(int sig, struct k_sigaction *ka, static int setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
sigset_t *set, struct pt_regs *regs)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
int err = 0; int err = 0, sig = ksig->sig;
int signal; int signal;
frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
signal = current_thread_info()->exec_domain signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -400,7 +395,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -400,7 +395,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Give up earlier as i386, in case */ /* Give up earlier as i386, in case */
if (err) if (err)
goto give_sigsegv; return -EFAULT;
if (_NSIG_WORDS > 1) { if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1], err |= __copy_to_user(frame->extramask, &set->sig[1],
...@@ -408,16 +403,16 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -408,16 +403,16 @@ static int setup_frame(int sig, struct k_sigaction *ka,
/* Give up earlier as i386, in case */ /* Give up earlier as i386, in case */
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
/* /*
* On SH5 all edited pointers are subject to NEFF * On SH5 all edited pointers are subject to NEFF
*/ */
DEREF_REG_PR = neff_sign_extend((unsigned long) DEREF_REG_PR = neff_sign_extend((unsigned long)
ka->sa.sa_restorer | 0x1); ksig->ka->sa.sa_restorer | 0x1);
} else { } else {
/* /*
* Different approach on SH5. * Different approach on SH5.
...@@ -435,7 +430,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -435,7 +430,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
if (__copy_to_user(frame->retcode, if (__copy_to_user(frame->retcode,
(void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0) (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
goto give_sigsegv; return -EFAULT;
/* Cohere the trampoline with the I-cache. */ /* Cohere the trampoline with the I-cache. */
flush_cache_sigtramp(DEREF_REG_PR-1); flush_cache_sigtramp(DEREF_REG_PR-1);
...@@ -460,7 +455,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -460,7 +455,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc; regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc; regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler); regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
set_fs(USER_DS); set_fs(USER_DS);
...@@ -471,23 +466,19 @@ static int setup_frame(int sig, struct k_sigaction *ka, ...@@ -471,23 +466,19 @@ static int setup_frame(int sig, struct k_sigaction *ka,
DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *kig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0, sig = ksig->sig;
int signal; int signal;
frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; return -EFAULT;
signal = current_thread_info()->exec_domain signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -497,11 +488,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -497,11 +488,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
/* Give up earlier as i386, in case */ /* Give up earlier as i386, in case */
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* Create the ucontext. */ /* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags); err |= __put_user(0, &frame->uc.uc_flags);
...@@ -513,16 +504,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -513,16 +504,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Give up earlier as i386, in case */ /* Give up earlier as i386, in case */
if (err) if (err)
goto give_sigsegv; return -EFAULT;
/* 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->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
/* /*
* On SH5 all edited pointers are subject to NEFF * On SH5 all edited pointers are subject to NEFF
*/ */
DEREF_REG_PR = neff_sign_extend((unsigned long) DEREF_REG_PR = neff_sign_extend((unsigned long)
ka->sa.sa_restorer | 0x1); ksig->ka.sa.sa_restorer | 0x1);
} else { } else {
/* /*
* Different approach on SH5. * Different approach on SH5.
...@@ -540,7 +531,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -540,7 +531,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (__copy_to_user(frame->retcode, if (__copy_to_user(frame->retcode,
(void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0) (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
goto give_sigsegv; return -EFAULT;
/* Cohere the trampoline with the I-cache. */ /* Cohere the trampoline with the I-cache. */
flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
...@@ -554,7 +545,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -554,7 +545,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler); regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
set_fs(USER_DS); set_fs(USER_DS);
...@@ -564,33 +555,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -564,33 +555,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, 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;
/* 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(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)
return;
signal_delivered(sig, info, ka, regs, signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
test_thread_flag(TIF_SINGLESTEP));
} }
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
......
...@@ -267,8 +267,7 @@ static inline int is_compat_task(void) ...@@ -267,8 +267,7 @@ static inline int is_compat_task(void)
return current_thread_info()->status & TS_COMPAT; return current_thread_info()->status & TS_COMPAT;
} }
extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka, extern int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
siginfo_t *info, sigset_t *set,
struct pt_regs *regs); struct pt_regs *regs);
/* Compat syscalls. */ /* Compat syscalls. */
......
...@@ -190,18 +190,18 @@ static inline void __user *compat_get_sigframe(struct k_sigaction *ka, ...@@ -190,18 +190,18 @@ static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
return (void __user *) sp; return (void __user *) sp;
} }
int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
unsigned long restorer; unsigned long restorer;
struct compat_rt_sigframe __user *frame; struct compat_rt_sigframe __user *frame;
int err = 0; int err = 0, sig = ksig->sig;
int usig; int usig;
frame = compat_get_sigframe(ka, regs, sizeof(*frame)); frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; goto err;
usig = current_thread_info()->exec_domain usig = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -210,12 +210,12 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -210,12 +210,12 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
: sig; : sig;
/* Always write at least the signal number for the stack backtracer. */ /* Always write at least the signal number for the stack backtracer. */
if (ka->sa.sa_flags & SA_SIGINFO) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
/* At sigreturn time, restore the callee-save registers too. */ /* At sigreturn time, restore the callee-save registers too. */
err |= copy_siginfo_to_user32(&frame->info, info); err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
regs->flags |= PT_FLAGS_RESTORE_REGS; regs->flags |= PT_FLAGS_RESTORE_REGS;
} else { } else {
err |= __put_user(info->si_signo, &frame->info.si_signo); err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
} }
/* Create the ucontext. */ /* Create the ucontext. */
...@@ -226,11 +226,11 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -226,11 +226,11 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; goto err;
restorer = VDSO_SYM(&__vdso_rt_sigreturn); restorer = VDSO_SYM(&__vdso_rt_sigreturn);
if (ka->sa.sa_flags & SA_RESTORER) if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ptr_to_compat_reg(ka->sa.sa_restorer); restorer = ptr_to_compat_reg(ksig->ka.sa.sa_restorer);
/* /*
* Set up registers for signal handler. * Set up registers for signal handler.
...@@ -239,7 +239,7 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -239,7 +239,7 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* We always pass siginfo and mcontext, regardless of SA_SIGINFO, * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
* since some things rely on this (e.g. glibc's debug/segfault.c). * since some things rely on this (e.g. glibc's debug/segfault.c).
*/ */
regs->pc = ptr_to_compat_reg(ka->sa.sa_handler); regs->pc = ptr_to_compat_reg(ksig->ka.sa.sa_handler);
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = ptr_to_compat_reg(frame); regs->sp = ptr_to_compat_reg(frame);
regs->lr = restorer; regs->lr = restorer;
...@@ -249,7 +249,8 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -249,7 +249,8 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->flags |= PT_FLAGS_CALLER_SAVES; regs->flags |= PT_FLAGS_CALLER_SAVES;
return 0; return 0;
give_sigsegv: err:
signal_fault("bad setup frame", regs, frame, sig); trace_unhandled_signal("bad sigreturn frame", regs,
(unsigned long)frame, SIGSEGV);
return -EFAULT; return -EFAULT;
} }
...@@ -153,18 +153,18 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, ...@@ -153,18 +153,18 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
return (void __user *) sp; return (void __user *) sp;
} }
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
unsigned long restorer; unsigned long restorer;
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0, sig = ksig->sig;
int usig; int usig;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; goto err;
usig = current_thread_info()->exec_domain usig = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
...@@ -173,12 +173,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -173,12 +173,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
: sig; : sig;
/* Always write at least the signal number for the stack backtracer. */ /* Always write at least the signal number for the stack backtracer. */
if (ka->sa.sa_flags & SA_SIGINFO) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
/* At sigreturn time, restore the callee-save registers too. */ /* At sigreturn time, restore the callee-save registers too. */
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
regs->flags |= PT_FLAGS_RESTORE_REGS; regs->flags |= PT_FLAGS_RESTORE_REGS;
} else { } else {
err |= __put_user(info->si_signo, &frame->info.si_signo); err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
} }
/* Create the ucontext. */ /* Create the ucontext. */
...@@ -189,11 +189,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -189,11 +189,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (err) if (err)
goto give_sigsegv; goto err;
restorer = VDSO_SYM(&__vdso_rt_sigreturn); restorer = VDSO_SYM(&__vdso_rt_sigreturn);
if (ka->sa.sa_flags & SA_RESTORER) if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = (unsigned long) ka->sa.sa_restorer; restorer = (unsigned long) ksig->ka.sa.sa_restorer;
/* /*
* Set up registers for signal handler. * Set up registers for signal handler.
...@@ -202,7 +202,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -202,7 +202,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
* We always pass siginfo and mcontext, regardless of SA_SIGINFO, * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
* since some things rely on this (e.g. glibc's debug/segfault.c). * since some things rely on this (e.g. glibc's debug/segfault.c).
*/ */
regs->pc = (unsigned long) ka->sa.sa_handler; regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */ regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
regs->sp = (unsigned long) frame; regs->sp = (unsigned long) frame;
regs->lr = restorer; regs->lr = restorer;
...@@ -212,8 +212,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -212,8 +212,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->flags |= PT_FLAGS_CALLER_SAVES; regs->flags |= PT_FLAGS_CALLER_SAVES;
return 0; return 0;
give_sigsegv: err:
signal_fault("bad setup frame", regs, frame, sig); trace_unhandled_signal("bad sigreturn frame", regs,
(unsigned long)frame, SIGSEGV);
return -EFAULT; return -EFAULT;
} }
...@@ -221,9 +222,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -221,9 +222,7 @@ static int 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 void handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct k_sigaction *ka,
struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int ret; int ret;
...@@ -238,7 +237,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -238,7 +237,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->regs[0] = -EINTR; regs->regs[0] = -EINTR;
break; break;
} }
...@@ -254,14 +253,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -254,14 +253,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
/* Set up the stack frame */ /* Set up the stack frame */
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
if (is_compat_task()) if (is_compat_task())
ret = compat_setup_rt_frame(sig, ka, info, oldset, regs); ret = compat_setup_rt_frame(ksig, oldset, regs);
else else
#endif #endif
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(ksig, oldset, regs);
if (ret)
return; signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
...@@ -271,9 +268,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info, ...@@ -271,9 +268,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
*/ */
void do_signal(struct pt_regs *regs) void do_signal(struct pt_regs *regs)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
/* /*
* i386 will check if we're coming from kernel mode and bail out * i386 will check if we're coming from kernel mode and bail out
...@@ -282,10 +277,9 @@ void do_signal(struct pt_regs *regs) ...@@ -282,10 +277,9 @@ void do_signal(struct pt_regs *regs)
* helpful, we can reinstate the check on "!user_mode(regs)". * helpful, we can reinstate the check on "!user_mode(regs)".
*/ */
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(signr, &info, &ka, regs); handle_signal(&ksig, regs);
goto done; goto done;
} }
......
...@@ -6,14 +6,10 @@ ...@@ -6,14 +6,10 @@
#ifndef __FRAME_KERN_H_ #ifndef __FRAME_KERN_H_
#define __FRAME_KERN_H_ #define __FRAME_KERN_H_
extern int setup_signal_stack_sc(unsigned long stack_top, int sig, extern int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
struct k_sigaction *ka, struct pt_regs *regs, sigset_t *mask);
struct pt_regs *regs, extern int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
sigset_t *mask); struct pt_regs *regs, sigset_t *mask);
extern int setup_signal_stack_si(unsigned long stack_top, int sig,
struct k_sigaction *ka,
struct pt_regs *regs, struct siginfo *info,
sigset_t *mask);
#endif #endif
...@@ -18,8 +18,7 @@ EXPORT_SYMBOL(unblock_signals); ...@@ -18,8 +18,7 @@ EXPORT_SYMBOL(unblock_signals);
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void handle_signal(struct pt_regs *regs, unsigned long signr, static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
struct k_sigaction *ka, struct siginfo *info)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int singlestep = 0; int singlestep = 0;
...@@ -39,7 +38,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, ...@@ -39,7 +38,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
PT_REGS_SYSCALL_RET(regs) = -EINTR; PT_REGS_SYSCALL_RET(regs) = -EINTR;
break; break;
} }
...@@ -52,32 +51,28 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr, ...@@ -52,32 +51,28 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
} }
sp = PT_REGS_SP(regs); sp = PT_REGS_SP(regs);
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0)) if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
sp = current->sas_ss_sp + current->sas_ss_size; sp = current->sas_ss_sp + current->sas_ss_size;
#ifdef CONFIG_ARCH_HAS_SC_SIGNALS #ifdef CONFIG_ARCH_HAS_SC_SIGNALS
if (!(ka->sa.sa_flags & SA_SIGINFO)) if (!(ksig->ka.sa.sa_flags & SA_SIGINFO))
err = setup_signal_stack_sc(sp, signr, ka, regs, oldset); err = setup_signal_stack_sc(sp, ksig, regs, oldset);
else else
#endif #endif
err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset); err = setup_signal_stack_si(sp, ksig, regs, oldset);
if (err) signal_setup_done(err, ksig, singlestep);
force_sigsegv(signr, current);
else
signal_delivered(signr, info, ka, regs, singlestep);
} }
static int kern_do_signal(struct pt_regs *regs) static int kern_do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka_copy; struct ksignal ksig;
struct siginfo info; int handled_sig = 0;
int sig, handled_sig = 0;
while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { while (get_signal(&ksig)) {
handled_sig = 1; handled_sig = 1;
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
handle_signal(regs, sig, &ka_copy, &info); handle_signal(&ksig, regs);
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
......
...@@ -238,10 +238,10 @@ static int setup_return(struct pt_regs *regs, struct k_sigaction *ka, ...@@ -238,10 +238,10 @@ static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
return 0; return 0;
} }
static int setup_frame(int usig, struct k_sigaction *ka, static int setup_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); struct sigframe __user *frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
int err = 0; int err = 0;
if (!frame) if (!frame)
...@@ -254,29 +254,29 @@ static int setup_frame(int usig, struct k_sigaction *ka, ...@@ -254,29 +254,29 @@ static int setup_frame(int usig, struct k_sigaction *ka,
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->ka, frame->retcode, frame, usig);
return err; return err;
} }
static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe __user *frame = struct rt_sigframe __user *frame =
get_sigframe(ka, regs, sizeof(*frame)); get_sigframe(&ksig->ka, 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);
err |= __put_user(0, &frame->sig.uc.uc_flags); err |= __put_user(0, &frame->sig.uc.uc_flags);
err |= __put_user(NULL, &frame->sig.uc.uc_link); err |= __put_user(NULL, &frame->sig.uc.uc_link);
err |= __save_altstack(&frame->sig.uc.uc_stack, regs->UCreg_sp); err |= __save_altstack(&frame->sig.uc.uc_stack, regs->UCreg_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->ka, frame->sig.retcode, frame, usig);
if (err == 0) { if (err == 0) {
/* /*
...@@ -299,13 +299,13 @@ static inline void setup_syscall_restart(struct pt_regs *regs) ...@@ -299,13 +299,13 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void handle_signal(unsigned long sig, struct k_sigaction *ka, static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
siginfo_t *info, struct pt_regs *regs, int syscall) int syscall)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current; struct task_struct *tsk = current;
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
int usig = sig; int usig = ksig->sig;
int ret; int ret;
/* /*
...@@ -318,7 +318,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -318,7 +318,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
regs->UCreg_00 = -EINTR; regs->UCreg_00 = -EINTR;
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka->sa.sa_flags & SA_RESTART)) { if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
regs->UCreg_00 = -EINTR; regs->UCreg_00 = -EINTR;
break; break;
} }
...@@ -338,22 +338,17 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -338,22 +338,17 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
/* /*
* 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);
} }
/* /*
...@@ -367,9 +362,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -367,9 +362,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
*/ */
static void do_signal(struct pt_regs *regs, int syscall) static void do_signal(struct pt_regs *regs, int syscall)
{ {
struct k_sigaction ka; struct ksignal ksig;
siginfo_t info;
int signr;
/* /*
* We want the common case to go fast, which * We want the common case to go fast, which
...@@ -380,9 +373,8 @@ static void do_signal(struct pt_regs *regs, int syscall) ...@@ -380,9 +373,8 @@ static void do_signal(struct pt_regs *regs, int syscall)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signsl(&ksig)) {
if (signr > 0) { handle_signal(&ksig, regs, syscall);
handle_signal(signr, &ka, &info, regs, syscall);
return; return;
} }
......
...@@ -370,13 +370,12 @@ struct rt_sigframe ...@@ -370,13 +370,12 @@ struct rt_sigframe
char retcode[8]; char retcode[8];
}; };
int setup_signal_stack_sc(unsigned long stack_top, int sig, int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
struct k_sigaction *ka, struct pt_regs *regs, struct pt_regs *regs, sigset_t *mask)
sigset_t *mask)
{ {
struct sigframe __user *frame; struct sigframe __user *frame;
void __user *restorer; void __user *restorer;
int err = 0; int err = 0, sig = ksig->sig;
/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */ /* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
stack_top = ((stack_top + 4) & -16UL) - 4; stack_top = ((stack_top + 4) & -16UL) - 4;
...@@ -385,8 +384,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, ...@@ -385,8 +384,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
return 1; return 1;
restorer = frame->retcode; restorer = frame->retcode;
if (ka->sa.sa_flags & SA_RESTORER) if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer; restorer = ksig->ka.sa.sa_restorer;
err |= __put_user(restorer, &frame->pretcode); err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig); err |= __put_user(sig, &frame->sig);
...@@ -410,20 +409,19 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig, ...@@ -410,20 +409,19 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
return err; return err;
PT_REGS_SP(regs) = (unsigned long) frame; PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
PT_REGS_AX(regs) = (unsigned long) sig; PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) 0; PT_REGS_DX(regs) = (unsigned long) 0;
PT_REGS_CX(regs) = (unsigned long) 0; PT_REGS_CX(regs) = (unsigned long) 0;
return 0; return 0;
} }
int setup_signal_stack_si(unsigned long stack_top, int sig, int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
struct k_sigaction *ka, struct pt_regs *regs, struct pt_regs *regs, sigset_t *mask)
siginfo_t *info, sigset_t *mask)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
void __user *restorer; void __user *restorer;
int err = 0; int err = 0, sig = ksig->sig;
stack_top &= -8UL; stack_top &= -8UL;
frame = (struct rt_sigframe __user *) stack_top - 1; frame = (struct rt_sigframe __user *) stack_top - 1;
...@@ -431,14 +429,14 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ...@@ -431,14 +429,14 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
return 1; return 1;
restorer = frame->retcode; restorer = frame->retcode;
if (ka->sa.sa_flags & SA_RESTORER) if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer; restorer = ksig->ka.sa.sa_restorer;
err |= __put_user(restorer, &frame->pretcode); err |= __put_user(restorer, &frame->pretcode);
err |= __put_user(sig, &frame->sig); err |= __put_user(sig, &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask, err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
PT_REGS_SP(regs)); PT_REGS_SP(regs));
...@@ -457,7 +455,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ...@@ -457,7 +455,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
return err; return err;
PT_REGS_SP(regs) = (unsigned long) frame; PT_REGS_SP(regs) = (unsigned long) frame;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
PT_REGS_AX(regs) = (unsigned long) sig; PT_REGS_AX(regs) = (unsigned long) sig;
PT_REGS_DX(regs) = (unsigned long) &frame->info; PT_REGS_DX(regs) = (unsigned long) &frame->info;
PT_REGS_CX(regs) = (unsigned long) &frame->uc; PT_REGS_CX(regs) = (unsigned long) &frame->uc;
...@@ -502,12 +500,11 @@ struct rt_sigframe ...@@ -502,12 +500,11 @@ struct rt_sigframe
struct _fpstate fpstate; struct _fpstate fpstate;
}; };
int setup_signal_stack_si(unsigned long stack_top, int sig, int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
struct k_sigaction *ka, struct pt_regs * regs, struct pt_regs *regs, sigset_t *set)
siginfo_t *info, sigset_t *set)
{ {
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0, sig = ksig->sig;
frame = (struct rt_sigframe __user *) frame = (struct rt_sigframe __user *)
round_down(stack_top - sizeof(struct rt_sigframe), 16); round_down(stack_top - sizeof(struct rt_sigframe), 16);
...@@ -517,8 +514,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ...@@ -517,8 +514,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto out; goto out;
if (ka->sa.sa_flags & SA_SIGINFO) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
if (err) if (err)
goto out; goto out;
} }
...@@ -543,8 +540,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ...@@ -543,8 +540,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
* already in userspace. * already in userspace.
*/ */
/* x86-64 should always use SA_RESTORER. */ /* x86-64 should always use SA_RESTORER. */
if (ka->sa.sa_flags & SA_RESTORER) if (ksig->ka.sa.sa_flags & SA_RESTORER)
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); err |= __put_user(ksig->ka.sa.sa_restorer, &frame->pretcode);
else else
/* could use a vstub here */ /* could use a vstub here */
return err; return err;
...@@ -570,7 +567,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig, ...@@ -570,7 +567,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
*/ */
PT_REGS_SI(regs) = (unsigned long) &frame->info; PT_REGS_SI(regs) = (unsigned long) &frame->info;
PT_REGS_DX(regs) = (unsigned long) &frame->uc; PT_REGS_DX(regs) = (unsigned long) &frame->uc;
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler; PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
out: out:
return err; return err;
} }
......
...@@ -331,17 +331,17 @@ gen_return_code(unsigned char *codemem) ...@@ -331,17 +331,17 @@ gen_return_code(unsigned char *codemem)
} }
static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, static int setup_frame(struct ksignal *ksig, sigset_t *set,
sigset_t *set, struct pt_regs *regs) struct pt_regs *regs)
{ {
struct rt_sigframe *frame; struct rt_sigframe *frame;
int err = 0; int err = 0, sig = ksig->sig;
int signal; int signal;
unsigned long sp, ra, tp; unsigned long sp, ra, tp;
sp = regs->areg[1]; sp = regs->areg[1];
if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) { if ((ksig->ka.sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) {
sp = current->sas_ss_sp + current->sas_ss_size; sp = current->sas_ss_sp + current->sas_ss_size;
} }
...@@ -351,7 +351,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -351,7 +351,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
panic ("Double exception sys_sigreturn\n"); panic ("Double exception sys_sigreturn\n");
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) { if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
goto give_sigsegv; return -EFAULT;
} }
signal = current_thread_info()->exec_domain signal = current_thread_info()->exec_domain
...@@ -360,8 +360,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -360,8 +360,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
? current_thread_info()->exec_domain->signal_invmap[sig] ? current_thread_info()->exec_domain->signal_invmap[sig]
: sig; : sig;
if (ka->sa.sa_flags & SA_SIGINFO) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, &ksig->info);
} }
/* Create the user context. */ /* Create the user context. */
...@@ -372,8 +372,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -372,8 +372,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= setup_sigcontext(frame, regs); err |= setup_sigcontext(frame, regs);
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
if (ka->sa.sa_flags & SA_RESTORER) { if (ksig->ka.sa.sa_flags & SA_RESTORER) {
ra = (unsigned long)ka->sa.sa_restorer; ra = (unsigned long)ksig->ka.sa.sa_restorer;
} else { } else {
/* Create sys_rt_sigreturn syscall in stack frame */ /* Create sys_rt_sigreturn syscall in stack frame */
...@@ -381,7 +381,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -381,7 +381,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
err |= gen_return_code(frame->retcode); err |= gen_return_code(frame->retcode);
if (err) { if (err) {
goto give_sigsegv; return -EFAULT;
} }
ra = (unsigned long) frame->retcode; ra = (unsigned long) frame->retcode;
} }
...@@ -393,7 +393,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -393,7 +393,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler; preserve the threadptr */ /* Set up registers for signal handler; preserve the threadptr */
tp = regs->threadptr; tp = regs->threadptr;
start_thread(regs, (unsigned long) ka->sa.sa_handler, start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
(unsigned long) frame); (unsigned long) frame);
/* Set up a stack frame for a call4 /* Set up a stack frame for a call4
...@@ -416,10 +416,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -416,10 +416,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
#endif #endif
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
/* /*
...@@ -433,15 +429,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -433,15 +429,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
siginfo_t info; struct ksignal ksig;
int signr;
struct k_sigaction ka;
task_pt_regs(current)->icountlevel = 0; task_pt_regs(current)->icountlevel = 0;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); if (get_signal(&ksig)) {
if (signr > 0) {
int ret; int ret;
/* Are we from a system call? */ /* Are we from a system call? */
...@@ -457,7 +449,7 @@ static void do_signal(struct pt_regs *regs) ...@@ -457,7 +449,7 @@ static void do_signal(struct pt_regs *regs)
break; break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (!(ka.sa.sa_flags & SA_RESTART)) { if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
regs->areg[2] = -EINTR; regs->areg[2] = -EINTR;
break; break;
} }
...@@ -476,11 +468,8 @@ static void do_signal(struct pt_regs *regs) ...@@ -476,11 +468,8 @@ static void do_signal(struct pt_regs *regs)
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
/* Set up the stack frame */ /* Set up the stack frame */
ret = setup_frame(signr, &ka, &info, sigmask_to_save(), regs); ret = setup_frame(&ksig, sigmask_to_save(), regs);
if (ret) signal_setup_done(ret, &ksig, 0);
return;
signal_delivered(signr, &info, &ka, regs, 0);
if (current->ptrace & PT_SINGLESTEP) if (current->ptrace & PT_SINGLESTEP)
task_pt_regs(current)->icountlevel = 1; task_pt_regs(current)->icountlevel = 1;
......
...@@ -2360,8 +2360,10 @@ static inline int on_sig_stack(unsigned long sp) ...@@ -2360,8 +2360,10 @@ static inline int on_sig_stack(unsigned long sp)
static inline int sas_ss_flags(unsigned long sp) static inline int sas_ss_flags(unsigned long sp)
{ {
return (current->sas_ss_size == 0 ? SS_DISABLE if (!current->sas_ss_size)
: on_sig_stack(sp) ? SS_ONSTACK : 0); return SS_DISABLE;
return on_sig_stack(sp) ? SS_ONSTACK : 0;
} }
static inline unsigned long sigsp(unsigned long sp, struct ksignal *ksig) static inline unsigned long sigsp(unsigned long sp, struct ksignal *ksig)
......
...@@ -280,9 +280,8 @@ struct ksignal { ...@@ -280,9 +280,8 @@ struct ksignal {
int sig; int sig;
}; };
extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); extern int get_signal(struct ksignal *ksig);
extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping); extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping);
extern void exit_signals(struct task_struct *tsk); extern void exit_signals(struct task_struct *tsk);
extern void kernel_sigaction(int, __sighandler_t); extern void kernel_sigaction(int, __sighandler_t);
...@@ -301,18 +300,6 @@ static inline void disallow_signal(int sig) ...@@ -301,18 +300,6 @@ static inline void disallow_signal(int sig)
kernel_sigaction(sig, SIG_IGN); kernel_sigaction(sig, SIG_IGN);
} }
/*
* Eventually that'll replace get_signal_to_deliver(); macro for now,
* to avoid nastiness with include order.
*/
#define get_signal(ksig) \
({ \
struct ksignal *p = (ksig); \
p->sig = get_signal_to_deliver(&p->info, &p->ka, \
signal_pt_regs(), NULL);\
p->sig > 0; \
})
extern struct kmem_cache *sighand_cachep; extern struct kmem_cache *sighand_cachep;
int unhandled_signal(struct task_struct *tsk, int sig); int unhandled_signal(struct task_struct *tsk, int sig);
......
...@@ -133,10 +133,6 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) ...@@ -133,10 +133,6 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
/** /**
* tracehook_signal_handler - signal handler setup is complete * tracehook_signal_handler - signal handler setup is complete
* @sig: number of signal being delivered
* @info: siginfo_t of signal being delivered
* @ka: sigaction setting that chose the handler
* @regs: user register state
* @stepping: nonzero if debugger single-step or block-step in use * @stepping: nonzero if debugger single-step or block-step in use
* *
* Called by the arch code after a signal handler has been set up. * Called by the arch code after a signal handler has been set up.
...@@ -146,9 +142,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) ...@@ -146,9 +142,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
* Called without locks, shortly before returning to user mode * Called without locks, shortly before returning to user mode
* (or handling more signals). * (or handling more signals).
*/ */
static inline void tracehook_signal_handler(int sig, siginfo_t *info, static inline void tracehook_signal_handler(int stepping)
const struct k_sigaction *ka,
struct pt_regs *regs, int stepping)
{ {
if (stepping) if (stepping)
ptrace_notify(SIGTRAP); ptrace_notify(SIGTRAP);
......
...@@ -2170,8 +2170,7 @@ static int ptrace_signal(int signr, siginfo_t *info) ...@@ -2170,8 +2170,7 @@ static int ptrace_signal(int signr, siginfo_t *info)
return signr; return signr;
} }
int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, int get_signal(struct ksignal *ksig)
struct pt_regs *regs, void *cookie)
{ {
struct sighand_struct *sighand = current->sighand; struct sighand_struct *sighand = current->sighand;
struct signal_struct *signal = current->signal; struct signal_struct *signal = current->signal;
...@@ -2241,13 +2240,13 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, ...@@ -2241,13 +2240,13 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
goto relock; goto relock;
} }
signr = dequeue_signal(current, &current->blocked, info); signr = dequeue_signal(current, &current->blocked, &ksig->info);
if (!signr) if (!signr)
break; /* will return 0 */ break; /* will return 0 */
if (unlikely(current->ptrace) && signr != SIGKILL) { if (unlikely(current->ptrace) && signr != SIGKILL) {
signr = ptrace_signal(signr, info); signr = ptrace_signal(signr, &ksig->info);
if (!signr) if (!signr)
continue; continue;
} }
...@@ -2255,13 +2254,13 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, ...@@ -2255,13 +2254,13 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
ka = &sighand->action[signr-1]; ka = &sighand->action[signr-1];
/* Trace actually delivered signals. */ /* Trace actually delivered signals. */
trace_signal_deliver(signr, info, ka); trace_signal_deliver(signr, &ksig->info, ka);
if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */ if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */
continue; continue;
if (ka->sa.sa_handler != SIG_DFL) { if (ka->sa.sa_handler != SIG_DFL) {
/* Run the handler. */ /* Run the handler. */
*return_ka = *ka; ksig->ka = *ka;
if (ka->sa.sa_flags & SA_ONESHOT) if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL; ka->sa.sa_handler = SIG_DFL;
...@@ -2311,7 +2310,7 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, ...@@ -2311,7 +2310,7 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
spin_lock_irq(&sighand->siglock); spin_lock_irq(&sighand->siglock);
} }
if (likely(do_signal_stop(info->si_signo))) { if (likely(do_signal_stop(ksig->info.si_signo))) {
/* It released the siglock. */ /* It released the siglock. */
goto relock; goto relock;
} }
...@@ -2332,7 +2331,7 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, ...@@ -2332,7 +2331,7 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
if (sig_kernel_coredump(signr)) { if (sig_kernel_coredump(signr)) {
if (print_fatal_signals) if (print_fatal_signals)
print_fatal_signal(info->si_signo); print_fatal_signal(ksig->info.si_signo);
proc_coredump_connector(current); proc_coredump_connector(current);
/* /*
* If it was able to dump core, this kills all * If it was able to dump core, this kills all
...@@ -2342,34 +2341,32 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, ...@@ -2342,34 +2341,32 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
* first and our do_group_exit call below will use * first and our do_group_exit call below will use
* that value and ignore the one we pass it. * that value and ignore the one we pass it.
*/ */
do_coredump(info); do_coredump(&ksig->info);
} }
/* /*
* Death signals, no core dump. * Death signals, no core dump.
*/ */
do_group_exit(info->si_signo); do_group_exit(ksig->info.si_signo);
/* NOTREACHED */ /* NOTREACHED */
} }
spin_unlock_irq(&sighand->siglock); spin_unlock_irq(&sighand->siglock);
return signr;
ksig->sig = signr;
return ksig->sig > 0;
} }
/** /**
* signal_delivered - * signal_delivered -
* @sig: number of signal being delivered * @ksig: kernel signal struct
* @info: siginfo_t of signal being delivered
* @ka: sigaction setting that chose the handler
* @regs: user register state
* @stepping: nonzero if debugger single-step or block-step in use * @stepping: nonzero if debugger single-step or block-step in use
* *
* This function should be called when a signal has successfully been * This function should be called when a signal has successfully been
* delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask * delivered. It updates the blocked signals accordingly (@ksig->ka.sa.sa_mask
* is always blocked, and the signal itself is blocked unless %SA_NODEFER * is always blocked, and the signal itself is blocked unless %SA_NODEFER
* is set in @ka->sa.sa_flags. Tracing is notified. * is set in @ksig->ka.sa.sa_flags. Tracing is notified.
*/ */
void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, static void signal_delivered(struct ksignal *ksig, int stepping)
struct pt_regs *regs, int stepping)
{ {
sigset_t blocked; sigset_t blocked;
...@@ -2379,11 +2376,11 @@ void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -2379,11 +2376,11 @@ void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka,
simply clear the restore sigmask flag. */ simply clear the restore sigmask flag. */
clear_restore_sigmask(); clear_restore_sigmask();
sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask); sigorsets(&blocked, &current->blocked, &ksig->ka.sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER)) if (!(ksig->ka.sa.sa_flags & SA_NODEFER))
sigaddset(&blocked, sig); sigaddset(&blocked, ksig->sig);
set_current_blocked(&blocked); set_current_blocked(&blocked);
tracehook_signal_handler(sig, info, ka, regs, stepping); tracehook_signal_handler(stepping);
} }
void signal_setup_done(int failed, struct ksignal *ksig, int stepping) void signal_setup_done(int failed, struct ksignal *ksig, int stepping)
...@@ -2391,8 +2388,7 @@ void signal_setup_done(int failed, struct ksignal *ksig, int stepping) ...@@ -2391,8 +2388,7 @@ void signal_setup_done(int failed, struct ksignal *ksig, int stepping)
if (failed) if (failed)
force_sigsegv(ksig->sig, current); force_sigsegv(ksig->sig, current);
else else
signal_delivered(ksig->sig, &ksig->info, &ksig->ka, signal_delivered(ksig, stepping);
signal_pt_regs(), stepping);
} }
/* /*
......
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