📄 traps.c
字号:
/* * 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/config.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/a.out.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/system.h>#include <asm/uaccess.h>#include <asm/traps.h>#include <asm/pgalloc.h>#include <asm/machdep.h>#include <asm/siginfo.h>/* assembler routines */asmlinkage void system_call(void);asmlinkage void buserr(void);asmlinkage void trap(void);asmlinkage void inthandler(void);asmlinkage void nmihandler(void);#ifdef CONFIG_M68KFPU_EMUasmlinkage void fpu_emu(void);#endife_vector vectors[256] = { [VEC_BUSERR] = buserr, [VEC_ADDRERR] = trap, [VEC_ILLEGAL] = trap, [VEC_ZERODIV] = trap, [VEC_CHK] = trap, [VEC_TRAP] = trap, [VEC_PRIV] = trap, [VEC_TRACE] = trap, [VEC_LINE10] = trap, [VEC_LINE11] = trap, [VEC_RESV12] = trap, [VEC_COPROC] = trap, [VEC_FORMAT] = trap, [VEC_UNINT] = trap, [VEC_RESV16] = trap, [VEC_RESV17] = trap, [VEC_RESV18] = trap, [VEC_RESV19] = trap, [VEC_RESV20] = trap, [VEC_RESV21] = trap, [VEC_RESV22] = trap, [VEC_RESV23] = trap, [VEC_SPUR] = inthandler, [VEC_INT1] = inthandler, [VEC_INT2] = inthandler, [VEC_INT3] = inthandler, [VEC_INT4] = inthandler, [VEC_INT5] = inthandler, [VEC_INT6] = inthandler, [VEC_INT7] = inthandler, [VEC_SYS] = system_call, [VEC_TRAP1] = trap, [VEC_TRAP2] = trap, [VEC_TRAP3] = trap, [VEC_TRAP4] = trap, [VEC_TRAP5] = trap, [VEC_TRAP6] = trap, [VEC_TRAP7] = trap, [VEC_TRAP8] = trap, [VEC_TRAP9] = trap, [VEC_TRAP10] = trap, [VEC_TRAP11] = trap, [VEC_TRAP12] = trap, [VEC_TRAP13] = trap, [VEC_TRAP14] = trap, [VEC_TRAP15] = trap,};/* nmi handler for the Amiga */asm(".text\n" __ALIGN_STR "\n" "nmihandler: rte");/* * this must be called very early as the kernel might * use some instruction that are emulated on the 060 */void __init base_trap_init(void){ if(MACH_IS_SUN3X) { extern e_vector *sun3x_prom_vbr; __asm__ volatile ("movec %%vbr, %0" : "=r" ((void*)sun3x_prom_vbr)); } /* setup the exception vector table */ __asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors)); if (CPU_IS_060) { /* set up ISP entry points */ asmlinkage void unimp_vec(void) asm ("_060_isp_unimp"); vectors[VEC_UNIMPII] = unimp_vec; }}void __init trap_init (void){ int i; for (i = 48; i < 64; i++) if (!vectors[i]) vectors[i] = trap; for (i = 64; i < 256; i++) vectors[i] = inthandler;#ifdef CONFIG_M68KFPU_EMU if (FPU_IS_EMU) vectors[VEC_LINE11] = fpu_emu;#endif if (CPU_IS_040 && !FPU_IS_EMU) { /* set up FPSP entry points */ asmlinkage void dz_vec(void) asm ("dz"); asmlinkage void inex_vec(void) asm ("inex"); asmlinkage void ovfl_vec(void) asm ("ovfl"); asmlinkage void unfl_vec(void) asm ("unfl"); asmlinkage void snan_vec(void) asm ("snan"); asmlinkage void operr_vec(void) asm ("operr"); asmlinkage void bsun_vec(void) asm ("bsun"); asmlinkage void fline_vec(void) asm ("fline"); asmlinkage void unsupp_vec(void) asm ("unsupp"); vectors[VEC_FPDIVZ] = dz_vec; vectors[VEC_FPIR] = inex_vec; vectors[VEC_FPOVER] = ovfl_vec; vectors[VEC_FPUNDER] = unfl_vec; vectors[VEC_FPNAN] = snan_vec; vectors[VEC_FPOE] = operr_vec; vectors[VEC_FPBRUC] = bsun_vec; vectors[VEC_LINE11] = fline_vec; vectors[VEC_FPUNSUP] = unsupp_vec; } if (CPU_IS_060 && !FPU_IS_EMU) { /* set up IFPSP entry points */ asmlinkage void snan_vec(void) asm ("_060_fpsp_snan"); asmlinkage void operr_vec(void) asm ("_060_fpsp_operr"); asmlinkage void ovfl_vec(void) asm ("_060_fpsp_ovfl"); asmlinkage void unfl_vec(void) asm ("_060_fpsp_unfl"); asmlinkage void dz_vec(void) asm ("_060_fpsp_dz"); asmlinkage void inex_vec(void) asm ("_060_fpsp_inex"); asmlinkage void fline_vec(void) asm ("_060_fpsp_fline"); asmlinkage void unsupp_vec(void) asm ("_060_fpsp_unsupp"); asmlinkage void effadd_vec(void) asm ("_060_fpsp_effadd"); vectors[VEC_FPNAN] = snan_vec; vectors[VEC_FPOE] = operr_vec; vectors[VEC_FPOVER] = ovfl_vec; vectors[VEC_FPUNDER] = unfl_vec; vectors[VEC_FPDIVZ] = dz_vec; vectors[VEC_FPIR] = inex_vec; vectors[VEC_LINE11] = fline_vec; vectors[VEC_FPUNSUP] = unsupp_vec; vectors[VEC_UNIMPEA] = effadd_vec; } /* if running on an amiga, make the NMI interrupt do nothing */ if (MACH_IS_AMIGA) { vectors[VEC_INT7] = nmihandler; }}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 & (MMU060_SEE)){ /* Software Emulation Error. * fault during mem_read/mem_write in ifpsp060/os.S */ send_fault_sig(&fp->ptregs); } else if (!(fslw & (MMU060_RE|MMU060_WE)) || send_fault_sig(&fp->ptregs) > 0) { printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); printk( "68060 access error, fslw=%lx\n", fslw ); trap_c( fp ); }}#endif /* CONFIG_M68060 */#if defined (CONFIG_M68040)static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs){ unsigned long mmusr; mm_segment_t old_fs = get_fs(); set_fs(MAKE_MM_SEG(wbs)); if (iswrite) asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); else asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr)); asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); set_fs(old_fs); return mmusr;}static inline int do_040writeback1(unsigned short wbs, unsigned long wba, unsigned long wbd){ int res = 0; mm_segment_t old_fs = get_fs(); /* set_fs can not be moved, otherwise put_user() may oops */ set_fs(MAKE_MM_SEG(wbs)); switch (wbs & WBSIZ_040) { case BA_SIZE_BYTE: res = put_user(wbd & 0xff, (char *)wba); break; case BA_SIZE_WORD: res = put_user(wbd & 0xffff, (short *)wba); break; case BA_SIZE_LONG: res = put_user(wbd, (int *)wba); break; } /* set_fs can not be moved, otherwise put_user() may oops */ set_fs(old_fs);#ifdef DEBUG printk("do_040writeback1, res=%d\n",res);#endif return res;}/* after an exception in a writeback the stack frame corresponding * to that exception is discarded, set a few bits in the old frame * to simulate what it should look like */static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs){ fp->un.fmt7.faddr = wba; fp->un.fmt7.ssw = wbs & 0xff; if (wba != current->thread.faddr) fp->un.fmt7.ssw |= MA_040;}static inline void do_040writebacks(struct frame *fp){ int res = 0;#if 0 if (fp->un.fmt7.wb1s & WBV_040) printk("access_error040: cannot handle 1st writeback. oops.\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -