/*
* linux/arch/m68k/kernel/signal.c
*
* Copyright (C) 1991, 1992 Linus Torvalds
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
/*
* Linux/m68k support by Hamish Macdonald
*
* 68060 fixes by Jesper Skov
*
* 1997-12-01 Modified for POSIX.1b signals by Andreas Schwab
*
* mathemu support by Roman Zippel
* (Note: fpstate in the signal context is completely ignored for the emulator
* and the internal floating point format is put on stack)
*/
/*
* ++roman (07/09/96): implemented signal stacks (specially for tosemu on
* Atari :-) Current limitation: Only one sigstack can be active at one time.
* If a second signal with SA_ONSTACK set arrives while working on a sigstack,
* SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
* signal handlers!
*/
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/syscalls.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
#include <linux/highuid.h>
#include <linux/personality.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
#include <linux/module.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/traps.h>
#include <asm/ucontext.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
static const int frame_extra_sizes[16] = {
[1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
[2] = sizeof(((struct frame *)0)->un.fmt2),
[3] = sizeof(((struct frame *)0)->un.fmt3),
#ifdef CONFIG_COLDFIRE
[4] = 0,
#else
[4] = sizeof(((struct frame *)0)->un.fmt4),
#endif
[5] = -1, /* sizeof(((struct frame *)0)->un.fmt5), */
[6] = -1, /* sizeof(((struct frame *)0)->un.fmt6), */
[7] = sizeof(((struct frame *)0)->un.fmt7),
[8] = -1, /* sizeof(((struct frame *)0)->un.fmt8), */
[9] = sizeof(((struct frame *)0)->un.fmt9),
[10] = sizeof(((struct frame *)0)->un.fmta),
[11] = sizeof(((struct frame *)0)->un.fmtb),
[12] = -1, /* sizeof(((struct frame *)0)->un.fmtc), */
[13] = -1, /* sizeof(((struct frame *)0)->un.fmtd), */
[14] = -1, /* sizeof(((struct frame *)0)->un.fmte), */
[15] = -1, /* sizeof(((struct frame *)0)->un.fmtf), */
};
int handle_kernel_fault(struct pt_regs *regs)
{
const struct exception_table_entry *fixup;
struct pt_regs *tregs;
/* Are we prepared to handle this kernel fault? */
fixup = search_exception_tables(regs->pc);
if (!fixup)
return 0;
/* Create a new four word stack frame, discarding the old one. */
regs->stkadj = frame_extra_sizes[regs->format];
tregs = (struct pt_regs *)((long)regs + regs->stkadj);
tregs->vector = regs->vector;
#ifdef CONFIG_COLDFIRE
tregs->format = 4;
#else
tregs->format = 0;
#endif
tregs->pc = fixup->fixup;
tregs->sr = regs->sr;
return 1;
}
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int
sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
{
mask &= _BLOCKABLE;
spin_lock_irq(¤t->sighand->siglock);
current->saved_sigmask = current->blocked;
siginitset(¤t->blocked, mask);
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
current->state = TASK_INTERRUPTIBLE;
schedule();
set_restore_sigmask();
return -ERESTARTNOHAND;
}
asmlinkage int
sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;