/*
* 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 <linux/tracehook.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/traps.h>
#include <asm/ucontext.h>
#ifdef CONFIG_MMU
/*
* Handle the slight differences in classic 68k and ColdFire trap frames.
*/
#ifdef CONFIG_COLDFIRE
#define FORMAT 4
#define FMT4SIZE 0
#else
#define FORMAT 0
#define FMT4SIZE sizeof(((struct frame *)0)->un.fmt4)
#endif
static const int frame_size_change[16] = {
[1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */
[2] = sizeof(((struct frame *)0)->un.fmt2),
[3] = sizeof(((struct frame *)0)->un.fmt3),
[4] = FMT4SIZE,
[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), */
};
static inline int frame_extra_sizes(int f)
{
return frame_size_change[f];
}
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;
tregs->format = FORMAT;
tregs->pc = fixup->fixup;
tregs->sr = regs->sr;
return 1;
}
void ptrace_signal_deliver(void)
{
struct pt_regs *regs = signal_pt_regs();
if (regs->orig_d0 < 0)
return;
switch (regs->d0) {