/*
* linux/arch/m68k/kernel/traps.c
*
* Copyright (C) 1993, 1994 by Hamish Macdonald
*
* 68040 fixes by Michael Rausch
* 68040 fixes by Martin Apel
* 68040 fixes and writeback by Richard Zidlicky
* 68060 fixes by Roman Hodek
* 68060 fixes by Jesper Skov
*
* 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.
*/
/*
* Sets up all exception vectors
*/
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/user.h>
#include <linux/string.h>
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/ptrace.h>
#include <linux/kallsyms.h>
#include <asm/setup.h>
#include <asm/fpu.h>
#include <asm/uaccess.h>
#include <asm/traps.h>
#include <asm/pgalloc.h>
#include <asm/machdep.h>
#include <asm/siginfo.h>
static const char *vec_names[] = {
[VEC_RESETSP] = "RESET SP",
[VEC_RESETPC] = "RESET PC",
[VEC_BUSERR] = "BUS ERROR",
[VEC_ADDRERR] = "ADDRESS ERROR",
[VEC_ILLEGAL] = "ILLEGAL INSTRUCTION",
[VEC_ZERODIV] = "ZERO DIVIDE",
[VEC_CHK] = "CHK",
[VEC_TRAP] = "TRAPcc",
[VEC_PRIV] = "PRIVILEGE VIOLATION",
[VEC_TRACE] = "TRACE",
[VEC_LINE10] = "LINE 1010",
[VEC_LINE11] = "LINE 1111",
[VEC_RESV12] = "UNASSIGNED RESERVED 12",
[VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION",
[VEC_FORMAT] = "FORMAT ERROR",
[VEC_UNINT] = "UNINITIALIZED INTERRUPT",
[VEC_RESV16] = "UNASSIGNED RESERVED 16",
[VEC_RESV17] = "UNASSIGNED RESERVED 17",
[VEC_RESV18] = "UNASSIGNED RESERVED 18",
[VEC_RESV19] = "UNASSIGNED RESERVED 19",
[VEC_RESV20] = "UNASSIGNED RESERVED 20",
[VEC_RESV21] = "UNASSIGNED RESERVED 21",
[VEC_RESV22] = "UNASSIGNED RESERVED 22",
[VEC_RESV23] = "UNASSIGNED RESERVED 23",
[VEC_SPUR] = "SPURIOUS INTERRUPT",
[VEC_INT1] = "LEVEL 1 INT",
[VEC_INT2] = "LEVEL 2 INT",
[VEC_INT3] = "LEVEL 3 INT",
[VEC_INT4] = "LEVEL 4 INT",
[VEC_INT5] = "LEVEL 5 INT",
[VEC_INT6] = "LEVEL 6 INT",
[VEC_INT7] = "LEVEL 7 INT",
[VEC_SYS] = "SYSCALL",
[VEC_TRAP1] = "TRAP #1",
[VEC_TRAP2] = "TRAP #2",
[VEC_TRAP3] = "TRAP #3",
[VEC_TRAP4] = "TRAP #4",
[VEC_TRAP5] = "TRAP #5",
[VEC_TRAP6] = "TRAP #6",
[VEC_TRAP7] = "TRAP #7",
[VEC_TRAP8] = "TRAP #8",
[VEC_TRAP9] = "TRAP #9",
[VEC_TRAP10] = "TRAP #10",
[VEC_TRAP11] = "TRAP #11",
[VEC_TRAP12] = "TRAP #12",
[VEC_TRAP13] = "TRAP #13",
[VEC_TRAP14] = "TRAP #14",
[VEC_TRAP15] = "TRAP #15",
[VEC_FPBRUC] = "FPCP BSUN",
[VEC_FPIR] = "FPCP INEXACT",
[VEC_FPDIVZ] = "FPCP DIV BY 0",
[VEC_FPUNDER] = "FPCP UNDERFLOW",
[VEC_FPOE] = "FPCP OPERAND ERROR",
[VEC_FPOVER] = "FPCP OVERFLOW",
[VEC_FPNAN] = "FPCP SNAN",
[VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION",
[VEC_MMUCFG] = "MMU CONFIGURATION ERROR",
[VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR",
[VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR",
[VEC_RESV59] = "UNASSIGNED RESERVED 59",
[VEC_UNIMPEA] = "UNASSIGNED RESERVED 60",
[VEC_UNIMPII] = "UNASSIGNED RESERVED 61",
[VEC_RESV62] = "UNASSIGNED RESERVED 62",
[VEC_RESV63] = "UNASSIGNED RESERVED 63",
};
static const char *space_names[] = {
[0] = "Space 0",
[USER_DATA] = "User Data",
[USER_PROGRAM] = "User Program",
#ifndef CONFIG_SUN3
[3] = "Space 3",
#else
[FC_CONTROL] = "Control",
#endif
[4] = "Space 4",
[SUPER_DATA] = "Super Data",
[SUPER_PROGRAM] = "Super Program",
[CPU_SPACE] = "CPU"
};
void die_if_kernel(char *,struct pt_regs *,int);
asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
unsigned long error_code);
int send_fault_sig(struct pt_regs *regs);
asmlinkage void trap_c(struct frame *fp);
#if defined (CONFIG_M68060)
static inline void access_error060 (struct frame *fp)
{
unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
#ifdef DEBUG
printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
#endif
if (fslw & MMU060_BPE) {
/* branch prediction error -> clear branch cache */
__asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
"orl #0x00400000,%/d0\n\t"
"movec %/d0,%/cacr"
: : : "d0" );
/* return if there's no other error */
if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
return;
}
if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
unsigned long errorcode;
unsigned long addr = fp->un.fmt4.effaddr;
if (fslw & MMU060_MA)
addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
errorcode = 1;
if (fslw & MMU060_DESC_ERR) {
__flush_tlb040_one(addr);
errorcode = 0;
}
if (fslw & MMU060_W)
errorcode |= 2;
#ifdef DEBUG
printk("errorcode = %d\n", errorcode );
#endif
do_page_fault(&fp->ptregs, addr, errorcode);
} else if (fslw
|