1*144077eaSGreg Ungerer /* 2*144077eaSGreg Ungerer * linux/arch/m68k/kernel/traps.c 3*144077eaSGreg Ungerer * 4*144077eaSGreg Ungerer * Copyright (C) 1993, 1994 by Hamish Macdonald 5*144077eaSGreg Ungerer * 6*144077eaSGreg Ungerer * 68040 fixes by Michael Rausch 7*144077eaSGreg Ungerer * 68040 fixes by Martin Apel 8*144077eaSGreg Ungerer * 68040 fixes and writeback by Richard Zidlicky 9*144077eaSGreg Ungerer * 68060 fixes by Roman Hodek 10*144077eaSGreg Ungerer * 68060 fixes by Jesper Skov 11*144077eaSGreg Ungerer * 12*144077eaSGreg Ungerer * This file is subject to the terms and conditions of the GNU General Public 13*144077eaSGreg Ungerer * License. See the file COPYING in the main directory of this archive 14*144077eaSGreg Ungerer * for more details. 15*144077eaSGreg Ungerer */ 16*144077eaSGreg Ungerer 17*144077eaSGreg Ungerer /* 18*144077eaSGreg Ungerer * Sets up all exception vectors 19*144077eaSGreg Ungerer */ 20*144077eaSGreg Ungerer 21*144077eaSGreg Ungerer #include <linux/sched.h> 22*144077eaSGreg Ungerer #include <linux/signal.h> 23*144077eaSGreg Ungerer #include <linux/kernel.h> 24*144077eaSGreg Ungerer #include <linux/mm.h> 25*144077eaSGreg Ungerer #include <linux/module.h> 26*144077eaSGreg Ungerer #include <linux/user.h> 27*144077eaSGreg Ungerer #include <linux/string.h> 28*144077eaSGreg Ungerer #include <linux/linkage.h> 29*144077eaSGreg Ungerer #include <linux/init.h> 30*144077eaSGreg Ungerer #include <linux/ptrace.h> 31*144077eaSGreg Ungerer #include <linux/kallsyms.h> 32*144077eaSGreg Ungerer 33*144077eaSGreg Ungerer #include <asm/setup.h> 34*144077eaSGreg Ungerer #include <asm/fpu.h> 35*144077eaSGreg Ungerer #include <asm/system.h> 36*144077eaSGreg Ungerer #include <asm/uaccess.h> 37*144077eaSGreg Ungerer #include <asm/traps.h> 38*144077eaSGreg Ungerer #include <asm/pgalloc.h> 39*144077eaSGreg Ungerer #include <asm/machdep.h> 40*144077eaSGreg Ungerer #include <asm/siginfo.h> 41*144077eaSGreg Ungerer 42*144077eaSGreg Ungerer 43*144077eaSGreg Ungerer static const char *vec_names[] = { 44*144077eaSGreg Ungerer [VEC_RESETSP] = "RESET SP", 45*144077eaSGreg Ungerer [VEC_RESETPC] = "RESET PC", 46*144077eaSGreg Ungerer [VEC_BUSERR] = "BUS ERROR", 47*144077eaSGreg Ungerer [VEC_ADDRERR] = "ADDRESS ERROR", 48*144077eaSGreg Ungerer [VEC_ILLEGAL] = "ILLEGAL INSTRUCTION", 49*144077eaSGreg Ungerer [VEC_ZERODIV] = "ZERO DIVIDE", 50*144077eaSGreg Ungerer [VEC_CHK] = "CHK", 51*144077eaSGreg Ungerer [VEC_TRAP] = "TRAPcc", 52*144077eaSGreg Ungerer [VEC_PRIV] = "PRIVILEGE VIOLATION", 53*144077eaSGreg Ungerer [VEC_TRACE] = "TRACE", 54*144077eaSGreg Ungerer [VEC_LINE10] = "LINE 1010", 55*144077eaSGreg Ungerer [VEC_LINE11] = "LINE 1111", 56*144077eaSGreg Ungerer [VEC_RESV12] = "UNASSIGNED RESERVED 12", 57*144077eaSGreg Ungerer [VEC_COPROC] = "COPROCESSOR PROTOCOL VIOLATION", 58*144077eaSGreg Ungerer [VEC_FORMAT] = "FORMAT ERROR", 59*144077eaSGreg Ungerer [VEC_UNINT] = "UNINITIALIZED INTERRUPT", 60*144077eaSGreg Ungerer [VEC_RESV16] = "UNASSIGNED RESERVED 16", 61*144077eaSGreg Ungerer [VEC_RESV17] = "UNASSIGNED RESERVED 17", 62*144077eaSGreg Ungerer [VEC_RESV18] = "UNASSIGNED RESERVED 18", 63*144077eaSGreg Ungerer [VEC_RESV19] = "UNASSIGNED RESERVED 19", 64*144077eaSGreg Ungerer [VEC_RESV20] = "UNASSIGNED RESERVED 20", 65*144077eaSGreg Ungerer [VEC_RESV21] = "UNASSIGNED RESERVED 21", 66*144077eaSGreg Ungerer [VEC_RESV22] = "UNASSIGNED RESERVED 22", 67*144077eaSGreg Ungerer [VEC_RESV23] = "UNASSIGNED RESERVED 23", 68*144077eaSGreg Ungerer [VEC_SPUR] = "SPURIOUS INTERRUPT", 69*144077eaSGreg Ungerer [VEC_INT1] = "LEVEL 1 INT", 70*144077eaSGreg Ungerer [VEC_INT2] = "LEVEL 2 INT", 71*144077eaSGreg Ungerer [VEC_INT3] = "LEVEL 3 INT", 72*144077eaSGreg Ungerer [VEC_INT4] = "LEVEL 4 INT", 73*144077eaSGreg Ungerer [VEC_INT5] = "LEVEL 5 INT", 74*144077eaSGreg Ungerer [VEC_INT6] = "LEVEL 6 INT", 75*144077eaSGreg Ungerer [VEC_INT7] = "LEVEL 7 INT", 76*144077eaSGreg Ungerer [VEC_SYS] = "SYSCALL", 77*144077eaSGreg Ungerer [VEC_TRAP1] = "TRAP #1", 78*144077eaSGreg Ungerer [VEC_TRAP2] = "TRAP #2", 79*144077eaSGreg Ungerer [VEC_TRAP3] = "TRAP #3", 80*144077eaSGreg Ungerer [VEC_TRAP4] = "TRAP #4", 81*144077eaSGreg Ungerer [VEC_TRAP5] = "TRAP #5", 82*144077eaSGreg Ungerer [VEC_TRAP6] = "TRAP #6", 83*144077eaSGreg Ungerer [VEC_TRAP7] = "TRAP #7", 84*144077eaSGreg Ungerer [VEC_TRAP8] = "TRAP #8", 85*144077eaSGreg Ungerer [VEC_TRAP9] = "TRAP #9", 86*144077eaSGreg Ungerer [VEC_TRAP10] = "TRAP #10", 87*144077eaSGreg Ungerer [VEC_TRAP11] = "TRAP #11", 88*144077eaSGreg Ungerer [VEC_TRAP12] = "TRAP #12", 89*144077eaSGreg Ungerer [VEC_TRAP13] = "TRAP #13", 90*144077eaSGreg Ungerer [VEC_TRAP14] = "TRAP #14", 91*144077eaSGreg Ungerer [VEC_TRAP15] = "TRAP #15", 92*144077eaSGreg Ungerer [VEC_FPBRUC] = "FPCP BSUN", 93*144077eaSGreg Ungerer [VEC_FPIR] = "FPCP INEXACT", 94*144077eaSGreg Ungerer [VEC_FPDIVZ] = "FPCP DIV BY 0", 95*144077eaSGreg Ungerer [VEC_FPUNDER] = "FPCP UNDERFLOW", 96*144077eaSGreg Ungerer [VEC_FPOE] = "FPCP OPERAND ERROR", 97*144077eaSGreg Ungerer [VEC_FPOVER] = "FPCP OVERFLOW", 98*144077eaSGreg Ungerer [VEC_FPNAN] = "FPCP SNAN", 99*144077eaSGreg Ungerer [VEC_FPUNSUP] = "FPCP UNSUPPORTED OPERATION", 100*144077eaSGreg Ungerer [VEC_MMUCFG] = "MMU CONFIGURATION ERROR", 101*144077eaSGreg Ungerer [VEC_MMUILL] = "MMU ILLEGAL OPERATION ERROR", 102*144077eaSGreg Ungerer [VEC_MMUACC] = "MMU ACCESS LEVEL VIOLATION ERROR", 103*144077eaSGreg Ungerer [VEC_RESV59] = "UNASSIGNED RESERVED 59", 104*144077eaSGreg Ungerer [VEC_UNIMPEA] = "UNASSIGNED RESERVED 60", 105*144077eaSGreg Ungerer [VEC_UNIMPII] = "UNASSIGNED RESERVED 61", 106*144077eaSGreg Ungerer [VEC_RESV62] = "UNASSIGNED RESERVED 62", 107*144077eaSGreg Ungerer [VEC_RESV63] = "UNASSIGNED RESERVED 63", 108*144077eaSGreg Ungerer }; 109*144077eaSGreg Ungerer 110*144077eaSGreg Ungerer static const char *space_names[] = { 111*144077eaSGreg Ungerer [0] = "Space 0", 112*144077eaSGreg Ungerer [USER_DATA] = "User Data", 113*144077eaSGreg Ungerer [USER_PROGRAM] = "User Program", 114*144077eaSGreg Ungerer #ifndef CONFIG_SUN3 115*144077eaSGreg Ungerer [3] = "Space 3", 1161da177e4SLinus Torvalds #else 117*144077eaSGreg Ungerer [FC_CONTROL] = "Control", 118*144077eaSGreg Ungerer #endif 119*144077eaSGreg Ungerer [4] = "Space 4", 120*144077eaSGreg Ungerer [SUPER_DATA] = "Super Data", 121*144077eaSGreg Ungerer [SUPER_PROGRAM] = "Super Program", 122*144077eaSGreg Ungerer [CPU_SPACE] = "CPU" 123*144077eaSGreg Ungerer }; 124*144077eaSGreg Ungerer 125*144077eaSGreg Ungerer void die_if_kernel(char *,struct pt_regs *,int); 126*144077eaSGreg Ungerer asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, 127*144077eaSGreg Ungerer unsigned long error_code); 128*144077eaSGreg Ungerer int send_fault_sig(struct pt_regs *regs); 129*144077eaSGreg Ungerer 130*144077eaSGreg Ungerer asmlinkage void trap_c(struct frame *fp); 131*144077eaSGreg Ungerer 132*144077eaSGreg Ungerer #if defined (CONFIG_M68060) 133*144077eaSGreg Ungerer static inline void access_error060 (struct frame *fp) 134*144077eaSGreg Ungerer { 135*144077eaSGreg Ungerer unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */ 136*144077eaSGreg Ungerer 137*144077eaSGreg Ungerer #ifdef DEBUG 138*144077eaSGreg Ungerer printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr); 139*144077eaSGreg Ungerer #endif 140*144077eaSGreg Ungerer 141*144077eaSGreg Ungerer if (fslw & MMU060_BPE) { 142*144077eaSGreg Ungerer /* branch prediction error -> clear branch cache */ 143*144077eaSGreg Ungerer __asm__ __volatile__ ("movec %/cacr,%/d0\n\t" 144*144077eaSGreg Ungerer "orl #0x00400000,%/d0\n\t" 145*144077eaSGreg Ungerer "movec %/d0,%/cacr" 146*144077eaSGreg Ungerer : : : "d0" ); 147*144077eaSGreg Ungerer /* return if there's no other error */ 148*144077eaSGreg Ungerer if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE)) 149*144077eaSGreg Ungerer return; 150*144077eaSGreg Ungerer } 151*144077eaSGreg Ungerer 152*144077eaSGreg Ungerer if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) { 153*144077eaSGreg Ungerer unsigned long errorcode; 154*144077eaSGreg Ungerer unsigned long addr = fp->un.fmt4.effaddr; 155*144077eaSGreg Ungerer 156*144077eaSGreg Ungerer if (fslw & MMU060_MA) 157*144077eaSGreg Ungerer addr = (addr + PAGE_SIZE - 1) & PAGE_MASK; 158*144077eaSGreg Ungerer 159*144077eaSGreg Ungerer errorcode = 1; 160*144077eaSGreg Ungerer if (fslw & MMU060_DESC_ERR) { 161*144077eaSGreg Ungerer __flush_tlb040_one(addr); 162*144077eaSGreg Ungerer errorcode = 0; 163*144077eaSGreg Ungerer } 164*144077eaSGreg Ungerer if (fslw & MMU060_W) 165*144077eaSGreg Ungerer errorcode |= 2; 166*144077eaSGreg Ungerer #ifdef DEBUG 167*144077eaSGreg Ungerer printk("errorcode = %d\n", errorcode ); 168*144077eaSGreg Ungerer #endif 169*144077eaSGreg Ungerer do_page_fault(&fp->ptregs, addr, errorcode); 170*144077eaSGreg Ungerer } else if (fslw & (MMU060_SEE)){ 171*144077eaSGreg Ungerer /* Software Emulation Error. 172*144077eaSGreg Ungerer * fault during mem_read/mem_write in ifpsp060/os.S 173*144077eaSGreg Ungerer */ 174*144077eaSGreg Ungerer send_fault_sig(&fp->ptregs); 175*144077eaSGreg Ungerer } else if (!(fslw & (MMU060_RE|MMU060_WE)) || 176*144077eaSGreg Ungerer send_fault_sig(&fp->ptregs) > 0) { 177*144077eaSGreg Ungerer printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr); 178*144077eaSGreg Ungerer printk( "68060 access error, fslw=%lx\n", fslw ); 179*144077eaSGreg Ungerer trap_c( fp ); 180*144077eaSGreg Ungerer } 181*144077eaSGreg Ungerer } 182*144077eaSGreg Ungerer #endif /* CONFIG_M68060 */ 183*144077eaSGreg Ungerer 184*144077eaSGreg Ungerer #if defined (CONFIG_M68040) 185*144077eaSGreg Ungerer static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs) 186*144077eaSGreg Ungerer { 187*144077eaSGreg Ungerer unsigned long mmusr; 188*144077eaSGreg Ungerer mm_segment_t old_fs = get_fs(); 189*144077eaSGreg Ungerer 190*144077eaSGreg Ungerer set_fs(MAKE_MM_SEG(wbs)); 191*144077eaSGreg Ungerer 192*144077eaSGreg Ungerer if (iswrite) 193*144077eaSGreg Ungerer asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr)); 194*144077eaSGreg Ungerer else 195*144077eaSGreg Ungerer asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr)); 196*144077eaSGreg Ungerer 197*144077eaSGreg Ungerer asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr)); 198*144077eaSGreg Ungerer 199*144077eaSGreg Ungerer set_fs(old_fs); 200*144077eaSGreg Ungerer 201*144077eaSGreg Ungerer return mmusr; 202*144077eaSGreg Ungerer } 203*144077eaSGreg Ungerer 204*144077eaSGreg Ungerer static inline int do_040writeback1(unsigned short wbs, unsigned long wba, 205*144077eaSGreg Ungerer unsigned long wbd) 206*144077eaSGreg Ungerer { 207*144077eaSGreg Ungerer int res = 0; 208*144077eaSGreg Ungerer mm_segment_t old_fs = get_fs(); 209*144077eaSGreg Ungerer 210*144077eaSGreg Ungerer /* set_fs can not be moved, otherwise put_user() may oops */ 211*144077eaSGreg Ungerer set_fs(MAKE_MM_SEG(wbs)); 212*144077eaSGreg Ungerer 213*144077eaSGreg Ungerer switch (wbs & WBSIZ_040) { 214*144077eaSGreg Ungerer case BA_SIZE_BYTE: 215*144077eaSGreg Ungerer res = put_user(wbd & 0xff, (char __user *)wba); 216*144077eaSGreg Ungerer break; 217*144077eaSGreg Ungerer case BA_SIZE_WORD: 218*144077eaSGreg Ungerer res = put_user(wbd & 0xffff, (short __user *)wba); 219*144077eaSGreg Ungerer break; 220*144077eaSGreg Ungerer case BA_SIZE_LONG: 221*144077eaSGreg Ungerer res = put_user(wbd, (int __user *)wba); 222*144077eaSGreg Ungerer break; 223*144077eaSGreg Ungerer } 224*144077eaSGreg Ungerer 225*144077eaSGreg Ungerer /* set_fs can not be moved, otherwise put_user() may oops */ 226*144077eaSGreg Ungerer set_fs(old_fs); 227*144077eaSGreg Ungerer 228*144077eaSGreg Ungerer 229*144077eaSGreg Ungerer #ifdef DEBUG 230*144077eaSGreg Ungerer printk("do_040writeback1, res=%d\n",res); 231*144077eaSGreg Ungerer #endif 232*144077eaSGreg Ungerer 233*144077eaSGreg Ungerer return res; 234*144077eaSGreg Ungerer } 235*144077eaSGreg Ungerer 236*144077eaSGreg Ungerer /* after an exception in a writeback the stack frame corresponding 237*144077eaSGreg Ungerer * to that exception is discarded, set a few bits in the old frame 238*144077eaSGreg Ungerer * to simulate what it should look like 239*144077eaSGreg Ungerer */ 240*144077eaSGreg Ungerer static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs) 241*144077eaSGreg Ungerer { 242*144077eaSGreg Ungerer fp->un.fmt7.faddr = wba; 243*144077eaSGreg Ungerer fp->un.fmt7.ssw = wbs & 0xff; 244*144077eaSGreg Ungerer if (wba != current->thread.faddr) 245*144077eaSGreg Ungerer fp->un.fmt7.ssw |= MA_040; 246*144077eaSGreg Ungerer } 247*144077eaSGreg Ungerer 248*144077eaSGreg Ungerer static inline void do_040writebacks(struct frame *fp) 249*144077eaSGreg Ungerer { 250*144077eaSGreg Ungerer int res = 0; 251*144077eaSGreg Ungerer #if 0 252*144077eaSGreg Ungerer if (fp->un.fmt7.wb1s & WBV_040) 253*144077eaSGreg Ungerer printk("access_error040: cannot handle 1st writeback. oops.\n"); 254*144077eaSGreg Ungerer #endif 255*144077eaSGreg Ungerer 256*144077eaSGreg Ungerer if ((fp->un.fmt7.wb2s & WBV_040) && 257*144077eaSGreg Ungerer !(fp->un.fmt7.wb2s & WBTT_040)) { 258*144077eaSGreg Ungerer res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, 259*144077eaSGreg Ungerer fp->un.fmt7.wb2d); 260*144077eaSGreg Ungerer if (res) 261*144077eaSGreg Ungerer fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s); 262*144077eaSGreg Ungerer else 263*144077eaSGreg Ungerer fp->un.fmt7.wb2s = 0; 264*144077eaSGreg Ungerer } 265*144077eaSGreg Ungerer 266*144077eaSGreg Ungerer /* do the 2nd wb only if the first one was successful (except for a kernel wb) */ 267*144077eaSGreg Ungerer if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) { 268*144077eaSGreg Ungerer res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, 269*144077eaSGreg Ungerer fp->un.fmt7.wb3d); 270*144077eaSGreg Ungerer if (res) 271*144077eaSGreg Ungerer { 272*144077eaSGreg Ungerer fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s); 273*144077eaSGreg Ungerer 274*144077eaSGreg Ungerer fp->un.fmt7.wb2s = fp->un.fmt7.wb3s; 275*144077eaSGreg Ungerer fp->un.fmt7.wb3s &= (~WBV_040); 276*144077eaSGreg Ungerer fp->un.fmt7.wb2a = fp->un.fmt7.wb3a; 277*144077eaSGreg Ungerer fp->un.fmt7.wb2d = fp->un.fmt7.wb3d; 278*144077eaSGreg Ungerer } 279*144077eaSGreg Ungerer else 280*144077eaSGreg Ungerer fp->un.fmt7.wb3s = 0; 281*144077eaSGreg Ungerer } 282*144077eaSGreg Ungerer 283*144077eaSGreg Ungerer if (res) 284*144077eaSGreg Ungerer send_fault_sig(&fp->ptregs); 285*144077eaSGreg Ungerer } 286*144077eaSGreg Ungerer 287*144077eaSGreg Ungerer /* 288*144077eaSGreg Ungerer * called from sigreturn(), must ensure userspace code didn't 289*144077eaSGreg Ungerer * manipulate exception frame to circumvent protection, then complete 290*144077eaSGreg Ungerer * pending writebacks 291*144077eaSGreg Ungerer * we just clear TM2 to turn it into a userspace access 292*144077eaSGreg Ungerer */ 293*144077eaSGreg Ungerer asmlinkage void berr_040cleanup(struct frame *fp) 294*144077eaSGreg Ungerer { 295*144077eaSGreg Ungerer fp->un.fmt7.wb2s &= ~4; 296*144077eaSGreg Ungerer fp->un.fmt7.wb3s &= ~4; 297*144077eaSGreg Ungerer 298*144077eaSGreg Ungerer do_040writebacks(fp); 299*144077eaSGreg Ungerer } 300*144077eaSGreg Ungerer 301*144077eaSGreg Ungerer static inline void access_error040(struct frame *fp) 302*144077eaSGreg Ungerer { 303*144077eaSGreg Ungerer unsigned short ssw = fp->un.fmt7.ssw; 304*144077eaSGreg Ungerer unsigned long mmusr; 305*144077eaSGreg Ungerer 306*144077eaSGreg Ungerer #ifdef DEBUG 307*144077eaSGreg Ungerer printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr); 308*144077eaSGreg Ungerer printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s, 309*144077eaSGreg Ungerer fp->un.fmt7.wb2s, fp->un.fmt7.wb3s); 310*144077eaSGreg Ungerer printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n", 311*144077eaSGreg Ungerer fp->un.fmt7.wb2a, fp->un.fmt7.wb3a, 312*144077eaSGreg Ungerer fp->un.fmt7.wb2d, fp->un.fmt7.wb3d); 313*144077eaSGreg Ungerer #endif 314*144077eaSGreg Ungerer 315*144077eaSGreg Ungerer if (ssw & ATC_040) { 316*144077eaSGreg Ungerer unsigned long addr = fp->un.fmt7.faddr; 317*144077eaSGreg Ungerer unsigned long errorcode; 318*144077eaSGreg Ungerer 319*144077eaSGreg Ungerer /* 320*144077eaSGreg Ungerer * The MMU status has to be determined AFTER the address 321*144077eaSGreg Ungerer * has been corrected if there was a misaligned access (MA). 322*144077eaSGreg Ungerer */ 323*144077eaSGreg Ungerer if (ssw & MA_040) 324*144077eaSGreg Ungerer addr = (addr + 7) & -8; 325*144077eaSGreg Ungerer 326*144077eaSGreg Ungerer /* MMU error, get the MMUSR info for this access */ 327*144077eaSGreg Ungerer mmusr = probe040(!(ssw & RW_040), addr, ssw); 328*144077eaSGreg Ungerer #ifdef DEBUG 329*144077eaSGreg Ungerer printk("mmusr = %lx\n", mmusr); 330*144077eaSGreg Ungerer #endif 331*144077eaSGreg Ungerer errorcode = 1; 332*144077eaSGreg Ungerer if (!(mmusr & MMU_R_040)) { 333*144077eaSGreg Ungerer /* clear the invalid atc entry */ 334*144077eaSGreg Ungerer __flush_tlb040_one(addr); 335*144077eaSGreg Ungerer errorcode = 0; 336*144077eaSGreg Ungerer } 337*144077eaSGreg Ungerer 338*144077eaSGreg Ungerer /* despite what documentation seems to say, RMW 339*144077eaSGreg Ungerer * accesses have always both the LK and RW bits set */ 340*144077eaSGreg Ungerer if (!(ssw & RW_040) || (ssw & LK_040)) 341*144077eaSGreg Ungerer errorcode |= 2; 342*144077eaSGreg Ungerer 343*144077eaSGreg Ungerer if (do_page_fault(&fp->ptregs, addr, errorcode)) { 344*144077eaSGreg Ungerer #ifdef DEBUG 345*144077eaSGreg Ungerer printk("do_page_fault() !=0\n"); 346*144077eaSGreg Ungerer #endif 347*144077eaSGreg Ungerer if (user_mode(&fp->ptregs)){ 348*144077eaSGreg Ungerer /* delay writebacks after signal delivery */ 349*144077eaSGreg Ungerer #ifdef DEBUG 350*144077eaSGreg Ungerer printk(".. was usermode - return\n"); 351*144077eaSGreg Ungerer #endif 352*144077eaSGreg Ungerer return; 353*144077eaSGreg Ungerer } 354*144077eaSGreg Ungerer /* disable writeback into user space from kernel 355*144077eaSGreg Ungerer * (if do_page_fault didn't fix the mapping, 356*144077eaSGreg Ungerer * the writeback won't do good) 357*144077eaSGreg Ungerer */ 358*144077eaSGreg Ungerer disable_wb: 359*144077eaSGreg Ungerer #ifdef DEBUG 360*144077eaSGreg Ungerer printk(".. disabling wb2\n"); 361*144077eaSGreg Ungerer #endif 362*144077eaSGreg Ungerer if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr) 363*144077eaSGreg Ungerer fp->un.fmt7.wb2s &= ~WBV_040; 364*144077eaSGreg Ungerer if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr) 365*144077eaSGreg Ungerer fp->un.fmt7.wb3s &= ~WBV_040; 366*144077eaSGreg Ungerer } 367*144077eaSGreg Ungerer } else { 368*144077eaSGreg Ungerer /* In case of a bus error we either kill the process or expect 369*144077eaSGreg Ungerer * the kernel to catch the fault, which then is also responsible 370*144077eaSGreg Ungerer * for cleaning up the mess. 371*144077eaSGreg Ungerer */ 372*144077eaSGreg Ungerer current->thread.signo = SIGBUS; 373*144077eaSGreg Ungerer current->thread.faddr = fp->un.fmt7.faddr; 374*144077eaSGreg Ungerer if (send_fault_sig(&fp->ptregs) >= 0) 375*144077eaSGreg Ungerer printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw, 376*144077eaSGreg Ungerer fp->un.fmt7.faddr); 377*144077eaSGreg Ungerer goto disable_wb; 378*144077eaSGreg Ungerer } 379*144077eaSGreg Ungerer 380*144077eaSGreg Ungerer do_040writebacks(fp); 381*144077eaSGreg Ungerer } 382*144077eaSGreg Ungerer #endif /* CONFIG_M68040 */ 383*144077eaSGreg Ungerer 384*144077eaSGreg Ungerer #if defined(CONFIG_SUN3) 385*144077eaSGreg Ungerer #include <asm/sun3mmu.h> 386*144077eaSGreg Ungerer 387*144077eaSGreg Ungerer extern int mmu_emu_handle_fault (unsigned long, int, int); 388*144077eaSGreg Ungerer 389*144077eaSGreg Ungerer /* sun3 version of bus_error030 */ 390*144077eaSGreg Ungerer 391*144077eaSGreg Ungerer static inline void bus_error030 (struct frame *fp) 392*144077eaSGreg Ungerer { 393*144077eaSGreg Ungerer unsigned char buserr_type = sun3_get_buserr (); 394*144077eaSGreg Ungerer unsigned long addr, errorcode; 395*144077eaSGreg Ungerer unsigned short ssw = fp->un.fmtb.ssw; 396*144077eaSGreg Ungerer extern unsigned long _sun3_map_test_start, _sun3_map_test_end; 397*144077eaSGreg Ungerer 398*144077eaSGreg Ungerer #ifdef DEBUG 399*144077eaSGreg Ungerer if (ssw & (FC | FB)) 400*144077eaSGreg Ungerer printk ("Instruction fault at %#010lx\n", 401*144077eaSGreg Ungerer ssw & FC ? 402*144077eaSGreg Ungerer fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 403*144077eaSGreg Ungerer : 404*144077eaSGreg Ungerer fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); 405*144077eaSGreg Ungerer if (ssw & DF) 406*144077eaSGreg Ungerer printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", 407*144077eaSGreg Ungerer ssw & RW ? "read" : "write", 408*144077eaSGreg Ungerer fp->un.fmtb.daddr, 409*144077eaSGreg Ungerer space_names[ssw & DFC], fp->ptregs.pc); 410*144077eaSGreg Ungerer #endif 411*144077eaSGreg Ungerer 412*144077eaSGreg Ungerer /* 413*144077eaSGreg Ungerer * Check if this page should be demand-mapped. This needs to go before 414*144077eaSGreg Ungerer * the testing for a bad kernel-space access (demand-mapping applies 415*144077eaSGreg Ungerer * to kernel accesses too). 416*144077eaSGreg Ungerer */ 417*144077eaSGreg Ungerer 418*144077eaSGreg Ungerer if ((ssw & DF) 419*144077eaSGreg Ungerer && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) { 420*144077eaSGreg Ungerer if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0)) 421*144077eaSGreg Ungerer return; 422*144077eaSGreg Ungerer } 423*144077eaSGreg Ungerer 424*144077eaSGreg Ungerer /* Check for kernel-space pagefault (BAD). */ 425*144077eaSGreg Ungerer if (fp->ptregs.sr & PS_S) { 426*144077eaSGreg Ungerer /* kernel fault must be a data fault to user space */ 427*144077eaSGreg Ungerer if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) { 428*144077eaSGreg Ungerer // try checking the kernel mappings before surrender 429*144077eaSGreg Ungerer if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1)) 430*144077eaSGreg Ungerer return; 431*144077eaSGreg Ungerer /* instruction fault or kernel data fault! */ 432*144077eaSGreg Ungerer if (ssw & (FC | FB)) 433*144077eaSGreg Ungerer printk ("Instruction fault at %#010lx\n", 434*144077eaSGreg Ungerer fp->ptregs.pc); 435*144077eaSGreg Ungerer if (ssw & DF) { 436*144077eaSGreg Ungerer /* was this fault incurred testing bus mappings? */ 437*144077eaSGreg Ungerer if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) && 438*144077eaSGreg Ungerer (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) { 439*144077eaSGreg Ungerer send_fault_sig(&fp->ptregs); 440*144077eaSGreg Ungerer return; 441*144077eaSGreg Ungerer } 442*144077eaSGreg Ungerer 443*144077eaSGreg Ungerer printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", 444*144077eaSGreg Ungerer ssw & RW ? "read" : "write", 445*144077eaSGreg Ungerer fp->un.fmtb.daddr, 446*144077eaSGreg Ungerer space_names[ssw & DFC], fp->ptregs.pc); 447*144077eaSGreg Ungerer } 448*144077eaSGreg Ungerer printk ("BAD KERNEL BUSERR\n"); 449*144077eaSGreg Ungerer 450*144077eaSGreg Ungerer die_if_kernel("Oops", &fp->ptregs,0); 451*144077eaSGreg Ungerer force_sig(SIGKILL, current); 452*144077eaSGreg Ungerer return; 453*144077eaSGreg Ungerer } 454*144077eaSGreg Ungerer } else { 455*144077eaSGreg Ungerer /* user fault */ 456*144077eaSGreg Ungerer if (!(ssw & (FC | FB)) && !(ssw & DF)) 457*144077eaSGreg Ungerer /* not an instruction fault or data fault! BAD */ 458*144077eaSGreg Ungerer panic ("USER BUSERR w/o instruction or data fault"); 459*144077eaSGreg Ungerer } 460*144077eaSGreg Ungerer 461*144077eaSGreg Ungerer 462*144077eaSGreg Ungerer /* First handle the data fault, if any. */ 463*144077eaSGreg Ungerer if (ssw & DF) { 464*144077eaSGreg Ungerer addr = fp->un.fmtb.daddr; 465*144077eaSGreg Ungerer 466*144077eaSGreg Ungerer // errorcode bit 0: 0 -> no page 1 -> protection fault 467*144077eaSGreg Ungerer // errorcode bit 1: 0 -> read fault 1 -> write fault 468*144077eaSGreg Ungerer 469*144077eaSGreg Ungerer // (buserr_type & SUN3_BUSERR_PROTERR) -> protection fault 470*144077eaSGreg Ungerer // (buserr_type & SUN3_BUSERR_INVALID) -> invalid page fault 471*144077eaSGreg Ungerer 472*144077eaSGreg Ungerer if (buserr_type & SUN3_BUSERR_PROTERR) 473*144077eaSGreg Ungerer errorcode = 0x01; 474*144077eaSGreg Ungerer else if (buserr_type & SUN3_BUSERR_INVALID) 475*144077eaSGreg Ungerer errorcode = 0x00; 476*144077eaSGreg Ungerer else { 477*144077eaSGreg Ungerer #ifdef DEBUG 478*144077eaSGreg Ungerer printk ("*** unexpected busfault type=%#04x\n", buserr_type); 479*144077eaSGreg Ungerer printk ("invalid %s access at %#lx from pc %#lx\n", 480*144077eaSGreg Ungerer !(ssw & RW) ? "write" : "read", addr, 481*144077eaSGreg Ungerer fp->ptregs.pc); 482*144077eaSGreg Ungerer #endif 483*144077eaSGreg Ungerer die_if_kernel ("Oops", &fp->ptregs, buserr_type); 484*144077eaSGreg Ungerer force_sig (SIGBUS, current); 485*144077eaSGreg Ungerer return; 486*144077eaSGreg Ungerer } 487*144077eaSGreg Ungerer 488*144077eaSGreg Ungerer //todo: wtf is RM bit? --m 489*144077eaSGreg Ungerer if (!(ssw & RW) || ssw & RM) 490*144077eaSGreg Ungerer errorcode |= 0x02; 491*144077eaSGreg Ungerer 492*144077eaSGreg Ungerer /* Handle page fault. */ 493*144077eaSGreg Ungerer do_page_fault (&fp->ptregs, addr, errorcode); 494*144077eaSGreg Ungerer 495*144077eaSGreg Ungerer /* Retry the data fault now. */ 496*144077eaSGreg Ungerer return; 497*144077eaSGreg Ungerer } 498*144077eaSGreg Ungerer 499*144077eaSGreg Ungerer /* Now handle the instruction fault. */ 500*144077eaSGreg Ungerer 501*144077eaSGreg Ungerer /* Get the fault address. */ 502*144077eaSGreg Ungerer if (fp->ptregs.format == 0xA) 503*144077eaSGreg Ungerer addr = fp->ptregs.pc + 4; 504*144077eaSGreg Ungerer else 505*144077eaSGreg Ungerer addr = fp->un.fmtb.baddr; 506*144077eaSGreg Ungerer if (ssw & FC) 507*144077eaSGreg Ungerer addr -= 2; 508*144077eaSGreg Ungerer 509*144077eaSGreg Ungerer if (buserr_type & SUN3_BUSERR_INVALID) { 510*144077eaSGreg Ungerer if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0)) 511*144077eaSGreg Ungerer do_page_fault (&fp->ptregs, addr, 0); 512*144077eaSGreg Ungerer } else { 513*144077eaSGreg Ungerer #ifdef DEBUG 514*144077eaSGreg Ungerer printk ("protection fault on insn access (segv).\n"); 515*144077eaSGreg Ungerer #endif 516*144077eaSGreg Ungerer force_sig (SIGSEGV, current); 517*144077eaSGreg Ungerer } 518*144077eaSGreg Ungerer } 519*144077eaSGreg Ungerer #else 520*144077eaSGreg Ungerer #if defined(CPU_M68020_OR_M68030) 521*144077eaSGreg Ungerer static inline void bus_error030 (struct frame *fp) 522*144077eaSGreg Ungerer { 523*144077eaSGreg Ungerer volatile unsigned short temp; 524*144077eaSGreg Ungerer unsigned short mmusr; 525*144077eaSGreg Ungerer unsigned long addr, errorcode; 526*144077eaSGreg Ungerer unsigned short ssw = fp->un.fmtb.ssw; 527*144077eaSGreg Ungerer #ifdef DEBUG 528*144077eaSGreg Ungerer unsigned long desc; 529*144077eaSGreg Ungerer 530*144077eaSGreg Ungerer printk ("pid = %x ", current->pid); 531*144077eaSGreg Ungerer printk ("SSW=%#06x ", ssw); 532*144077eaSGreg Ungerer 533*144077eaSGreg Ungerer if (ssw & (FC | FB)) 534*144077eaSGreg Ungerer printk ("Instruction fault at %#010lx\n", 535*144077eaSGreg Ungerer ssw & FC ? 536*144077eaSGreg Ungerer fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2 537*144077eaSGreg Ungerer : 538*144077eaSGreg Ungerer fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr); 539*144077eaSGreg Ungerer if (ssw & DF) 540*144077eaSGreg Ungerer printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", 541*144077eaSGreg Ungerer ssw & RW ? "read" : "write", 542*144077eaSGreg Ungerer fp->un.fmtb.daddr, 543*144077eaSGreg Ungerer space_names[ssw & DFC], fp->ptregs.pc); 544*144077eaSGreg Ungerer #endif 545*144077eaSGreg Ungerer 546*144077eaSGreg Ungerer /* ++andreas: If a data fault and an instruction fault happen 547*144077eaSGreg Ungerer at the same time map in both pages. */ 548*144077eaSGreg Ungerer 549*144077eaSGreg Ungerer /* First handle the data fault, if any. */ 550*144077eaSGreg Ungerer if (ssw & DF) { 551*144077eaSGreg Ungerer addr = fp->un.fmtb.daddr; 552*144077eaSGreg Ungerer 553*144077eaSGreg Ungerer #ifdef DEBUG 554*144077eaSGreg Ungerer asm volatile ("ptestr %3,%2@,#7,%0\n\t" 555*144077eaSGreg Ungerer "pmove %%psr,%1@" 556*144077eaSGreg Ungerer : "=a&" (desc) 557*144077eaSGreg Ungerer : "a" (&temp), "a" (addr), "d" (ssw)); 558*144077eaSGreg Ungerer #else 559*144077eaSGreg Ungerer asm volatile ("ptestr %2,%1@,#7\n\t" 560*144077eaSGreg Ungerer "pmove %%psr,%0@" 561*144077eaSGreg Ungerer : : "a" (&temp), "a" (addr), "d" (ssw)); 562*144077eaSGreg Ungerer #endif 563*144077eaSGreg Ungerer mmusr = temp; 564*144077eaSGreg Ungerer 565*144077eaSGreg Ungerer #ifdef DEBUG 566*144077eaSGreg Ungerer printk("mmusr is %#x for addr %#lx in task %p\n", 567*144077eaSGreg Ungerer mmusr, addr, current); 568*144077eaSGreg Ungerer printk("descriptor address is %#lx, contents %#lx\n", 569*144077eaSGreg Ungerer __va(desc), *(unsigned long *)__va(desc)); 570*144077eaSGreg Ungerer #endif 571*144077eaSGreg Ungerer 572*144077eaSGreg Ungerer errorcode = (mmusr & MMU_I) ? 0 : 1; 573*144077eaSGreg Ungerer if (!(ssw & RW) || (ssw & RM)) 574*144077eaSGreg Ungerer errorcode |= 2; 575*144077eaSGreg Ungerer 576*144077eaSGreg Ungerer if (mmusr & (MMU_I | MMU_WP)) { 577*144077eaSGreg Ungerer if (ssw & 4) { 578*144077eaSGreg Ungerer printk("Data %s fault at %#010lx in %s (pc=%#lx)\n", 579*144077eaSGreg Ungerer ssw & RW ? "read" : "write", 580*144077eaSGreg Ungerer fp->un.fmtb.daddr, 581*144077eaSGreg Ungerer space_names[ssw & DFC], fp->ptregs.pc); 582*144077eaSGreg Ungerer goto buserr; 583*144077eaSGreg Ungerer } 584*144077eaSGreg Ungerer /* Don't try to do anything further if an exception was 585*144077eaSGreg Ungerer handled. */ 586*144077eaSGreg Ungerer if (do_page_fault (&fp->ptregs, addr, errorcode) < 0) 587*144077eaSGreg Ungerer return; 588*144077eaSGreg Ungerer } else if (!(mmusr & MMU_I)) { 589*144077eaSGreg Ungerer /* probably a 020 cas fault */ 590*144077eaSGreg Ungerer if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0) 591*144077eaSGreg Ungerer printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr); 592*144077eaSGreg Ungerer } else if (mmusr & (MMU_B|MMU_L|MMU_S)) { 593*144077eaSGreg Ungerer printk("invalid %s access at %#lx from pc %#lx\n", 594*144077eaSGreg Ungerer !(ssw & RW) ? "write" : "read", addr, 595*144077eaSGreg Ungerer fp->ptregs.pc); 596*144077eaSGreg Ungerer die_if_kernel("Oops",&fp->ptregs,mmusr); 597*144077eaSGreg Ungerer force_sig(SIGSEGV, current); 598*144077eaSGreg Ungerer return; 599*144077eaSGreg Ungerer } else { 600*144077eaSGreg Ungerer #if 0 601*144077eaSGreg Ungerer static volatile long tlong; 602*144077eaSGreg Ungerer #endif 603*144077eaSGreg Ungerer 604*144077eaSGreg Ungerer printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n", 605*144077eaSGreg Ungerer !(ssw & RW) ? "write" : "read", addr, 606*144077eaSGreg Ungerer fp->ptregs.pc, ssw); 607*144077eaSGreg Ungerer asm volatile ("ptestr #1,%1@,#0\n\t" 608*144077eaSGreg Ungerer "pmove %%psr,%0@" 609*144077eaSGreg Ungerer : /* no outputs */ 610*144077eaSGreg Ungerer : "a" (&temp), "a" (addr)); 611*144077eaSGreg Ungerer mmusr = temp; 612*144077eaSGreg Ungerer 613*144077eaSGreg Ungerer printk ("level 0 mmusr is %#x\n", mmusr); 614*144077eaSGreg Ungerer #if 0 615*144077eaSGreg Ungerer asm volatile ("pmove %%tt0,%0@" 616*144077eaSGreg Ungerer : /* no outputs */ 617*144077eaSGreg Ungerer : "a" (&tlong)); 618*144077eaSGreg Ungerer printk("tt0 is %#lx, ", tlong); 619*144077eaSGreg Ungerer asm volatile ("pmove %%tt1,%0@" 620*144077eaSGreg Ungerer : /* no outputs */ 621*144077eaSGreg Ungerer : "a" (&tlong)); 622*144077eaSGreg Ungerer printk("tt1 is %#lx\n", tlong); 623*144077eaSGreg Ungerer #endif 624*144077eaSGreg Ungerer #ifdef DEBUG 625*144077eaSGreg Ungerer printk("Unknown SIGSEGV - 1\n"); 626*144077eaSGreg Ungerer #endif 627*144077eaSGreg Ungerer die_if_kernel("Oops",&fp->ptregs,mmusr); 628*144077eaSGreg Ungerer force_sig(SIGSEGV, current); 629*144077eaSGreg Ungerer return; 630*144077eaSGreg Ungerer } 631*144077eaSGreg Ungerer 632*144077eaSGreg Ungerer /* setup an ATC entry for the access about to be retried */ 633*144077eaSGreg Ungerer if (!(ssw & RW) || (ssw & RM)) 634*144077eaSGreg Ungerer asm volatile ("ploadw %1,%0@" : /* no outputs */ 635*144077eaSGreg Ungerer : "a" (addr), "d" (ssw)); 636*144077eaSGreg Ungerer else 637*144077eaSGreg Ungerer asm volatile ("ploadr %1,%0@" : /* no outputs */ 638*144077eaSGreg Ungerer : "a" (addr), "d" (ssw)); 639*144077eaSGreg Ungerer } 640*144077eaSGreg Ungerer 641*144077eaSGreg Ungerer /* Now handle the instruction fault. */ 642*144077eaSGreg Ungerer 643*144077eaSGreg Ungerer if (!(ssw & (FC|FB))) 644*144077eaSGreg Ungerer return; 645*144077eaSGreg Ungerer 646*144077eaSGreg Ungerer if (fp->ptregs.sr & PS_S) { 647*144077eaSGreg Ungerer printk("Instruction fault at %#010lx\n", 648*144077eaSGreg Ungerer fp->ptregs.pc); 649*144077eaSGreg Ungerer buserr: 650*144077eaSGreg Ungerer printk ("BAD KERNEL BUSERR\n"); 651*144077eaSGreg Ungerer die_if_kernel("Oops",&fp->ptregs,0); 652*144077eaSGreg Ungerer force_sig(SIGKILL, current); 653*144077eaSGreg Ungerer return; 654*144077eaSGreg Ungerer } 655*144077eaSGreg Ungerer 656*144077eaSGreg Ungerer /* get the fault address */ 657*144077eaSGreg Ungerer if (fp->ptregs.format == 10) 658*144077eaSGreg Ungerer addr = fp->ptregs.pc + 4; 659*144077eaSGreg Ungerer else 660*144077eaSGreg Ungerer addr = fp->un.fmtb.baddr; 661*144077eaSGreg Ungerer if (ssw & FC) 662*144077eaSGreg Ungerer addr -= 2; 663*144077eaSGreg Ungerer 664*144077eaSGreg Ungerer if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0) 665*144077eaSGreg Ungerer /* Insn fault on same page as data fault. But we 666*144077eaSGreg Ungerer should still create the ATC entry. */ 667*144077eaSGreg Ungerer goto create_atc_entry; 668*144077eaSGreg Ungerer 669*144077eaSGreg Ungerer #ifdef DEBUG 670*144077eaSGreg Ungerer asm volatile ("ptestr #1,%2@,#7,%0\n\t" 671*144077eaSGreg Ungerer "pmove %%psr,%1@" 672*144077eaSGreg Ungerer : "=a&" (desc) 673*144077eaSGreg Ungerer : "a" (&temp), "a" (addr)); 674*144077eaSGreg Ungerer #else 675*144077eaSGreg Ungerer asm volatile ("ptestr #1,%1@,#7\n\t" 676*144077eaSGreg Ungerer "pmove %%psr,%0@" 677*144077eaSGreg Ungerer : : "a" (&temp), "a" (addr)); 678*144077eaSGreg Ungerer #endif 679*144077eaSGreg Ungerer mmusr = temp; 680*144077eaSGreg Ungerer 681*144077eaSGreg Ungerer #ifdef DEBUG 682*144077eaSGreg Ungerer printk ("mmusr is %#x for addr %#lx in task %p\n", 683*144077eaSGreg Ungerer mmusr, addr, current); 684*144077eaSGreg Ungerer printk ("descriptor address is %#lx, contents %#lx\n", 685*144077eaSGreg Ungerer __va(desc), *(unsigned long *)__va(desc)); 686*144077eaSGreg Ungerer #endif 687*144077eaSGreg Ungerer 688*144077eaSGreg Ungerer if (mmusr & MMU_I) 689*144077eaSGreg Ungerer do_page_fault (&fp->ptregs, addr, 0); 690*144077eaSGreg Ungerer else if (mmusr & (MMU_B|MMU_L|MMU_S)) { 691*144077eaSGreg Ungerer printk ("invalid insn access at %#lx from pc %#lx\n", 692*144077eaSGreg Ungerer addr, fp->ptregs.pc); 693*144077eaSGreg Ungerer #ifdef DEBUG 694*144077eaSGreg Ungerer printk("Unknown SIGSEGV - 2\n"); 695*144077eaSGreg Ungerer #endif 696*144077eaSGreg Ungerer die_if_kernel("Oops",&fp->ptregs,mmusr); 697*144077eaSGreg Ungerer force_sig(SIGSEGV, current); 698*144077eaSGreg Ungerer return; 699*144077eaSGreg Ungerer } 700*144077eaSGreg Ungerer 701*144077eaSGreg Ungerer create_atc_entry: 702*144077eaSGreg Ungerer /* setup an ATC entry for the access about to be retried */ 703*144077eaSGreg Ungerer asm volatile ("ploadr #2,%0@" : /* no outputs */ 704*144077eaSGreg Ungerer : "a" (addr)); 705*144077eaSGreg Ungerer } 706*144077eaSGreg Ungerer #endif /* CPU_M68020_OR_M68030 */ 707*144077eaSGreg Ungerer #endif /* !CONFIG_SUN3 */ 708*144077eaSGreg Ungerer 709*144077eaSGreg Ungerer asmlinkage void buserr_c(struct frame *fp) 710*144077eaSGreg Ungerer { 711*144077eaSGreg Ungerer /* Only set esp0 if coming from user mode */ 712*144077eaSGreg Ungerer if (user_mode(&fp->ptregs)) 713*144077eaSGreg Ungerer current->thread.esp0 = (unsigned long) fp; 714*144077eaSGreg Ungerer 715*144077eaSGreg Ungerer #ifdef DEBUG 716*144077eaSGreg Ungerer printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format); 717*144077eaSGreg Ungerer #endif 718*144077eaSGreg Ungerer 719*144077eaSGreg Ungerer switch (fp->ptregs.format) { 720*144077eaSGreg Ungerer #if defined (CONFIG_M68060) 721*144077eaSGreg Ungerer case 4: /* 68060 access error */ 722*144077eaSGreg Ungerer access_error060 (fp); 723*144077eaSGreg Ungerer break; 724*144077eaSGreg Ungerer #endif 725*144077eaSGreg Ungerer #if defined (CONFIG_M68040) 726*144077eaSGreg Ungerer case 0x7: /* 68040 access error */ 727*144077eaSGreg Ungerer access_error040 (fp); 728*144077eaSGreg Ungerer break; 729*144077eaSGreg Ungerer #endif 730*144077eaSGreg Ungerer #if defined (CPU_M68020_OR_M68030) 731*144077eaSGreg Ungerer case 0xa: 732*144077eaSGreg Ungerer case 0xb: 733*144077eaSGreg Ungerer bus_error030 (fp); 734*144077eaSGreg Ungerer break; 735*144077eaSGreg Ungerer #endif 736*144077eaSGreg Ungerer default: 737*144077eaSGreg Ungerer die_if_kernel("bad frame format",&fp->ptregs,0); 738*144077eaSGreg Ungerer #ifdef DEBUG 739*144077eaSGreg Ungerer printk("Unknown SIGSEGV - 4\n"); 740*144077eaSGreg Ungerer #endif 741*144077eaSGreg Ungerer force_sig(SIGSEGV, current); 742*144077eaSGreg Ungerer } 743*144077eaSGreg Ungerer } 744*144077eaSGreg Ungerer 745*144077eaSGreg Ungerer 746*144077eaSGreg Ungerer static int kstack_depth_to_print = 48; 747*144077eaSGreg Ungerer 748*144077eaSGreg Ungerer void show_trace(unsigned long *stack) 749*144077eaSGreg Ungerer { 750*144077eaSGreg Ungerer unsigned long *endstack; 751*144077eaSGreg Ungerer unsigned long addr; 752*144077eaSGreg Ungerer int i; 753*144077eaSGreg Ungerer 754*144077eaSGreg Ungerer printk("Call Trace:"); 755*144077eaSGreg Ungerer addr = (unsigned long)stack + THREAD_SIZE - 1; 756*144077eaSGreg Ungerer endstack = (unsigned long *)(addr & -THREAD_SIZE); 757*144077eaSGreg Ungerer i = 0; 758*144077eaSGreg Ungerer while (stack + 1 <= endstack) { 759*144077eaSGreg Ungerer addr = *stack++; 760*144077eaSGreg Ungerer /* 761*144077eaSGreg Ungerer * If the address is either in the text segment of the 762*144077eaSGreg Ungerer * kernel, or in the region which contains vmalloc'ed 763*144077eaSGreg Ungerer * memory, it *may* be the address of a calling 764*144077eaSGreg Ungerer * routine; if so, print it so that someone tracing 765*144077eaSGreg Ungerer * down the cause of the crash will be able to figure 766*144077eaSGreg Ungerer * out the call path that was taken. 767*144077eaSGreg Ungerer */ 768*144077eaSGreg Ungerer if (__kernel_text_address(addr)) { 769*144077eaSGreg Ungerer #ifndef CONFIG_KALLSYMS 770*144077eaSGreg Ungerer if (i % 5 == 0) 771*144077eaSGreg Ungerer printk("\n "); 772*144077eaSGreg Ungerer #endif 773*144077eaSGreg Ungerer printk(" [<%08lx>] %pS\n", addr, (void *)addr); 774*144077eaSGreg Ungerer i++; 775*144077eaSGreg Ungerer } 776*144077eaSGreg Ungerer } 777*144077eaSGreg Ungerer printk("\n"); 778*144077eaSGreg Ungerer } 779*144077eaSGreg Ungerer 780*144077eaSGreg Ungerer void show_registers(struct pt_regs *regs) 781*144077eaSGreg Ungerer { 782*144077eaSGreg Ungerer struct frame *fp = (struct frame *)regs; 783*144077eaSGreg Ungerer mm_segment_t old_fs = get_fs(); 784*144077eaSGreg Ungerer u16 c, *cp; 785*144077eaSGreg Ungerer unsigned long addr; 786*144077eaSGreg Ungerer int i; 787*144077eaSGreg Ungerer 788*144077eaSGreg Ungerer print_modules(); 789*144077eaSGreg Ungerer printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc); 790*144077eaSGreg Ungerer printk("SR: %04x SP: %p a2: %08lx\n", regs->sr, regs, regs->a2); 791*144077eaSGreg Ungerer printk("d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", 792*144077eaSGreg Ungerer regs->d0, regs->d1, regs->d2, regs->d3); 793*144077eaSGreg Ungerer printk("d4: %08lx d5: %08lx a0: %08lx a1: %08lx\n", 794*144077eaSGreg Ungerer regs->d4, regs->d5, regs->a0, regs->a1); 795*144077eaSGreg Ungerer 796*144077eaSGreg Ungerer printk("Process %s (pid: %d, task=%p)\n", 797*144077eaSGreg Ungerer current->comm, task_pid_nr(current), current); 798*144077eaSGreg Ungerer addr = (unsigned long)&fp->un; 799*144077eaSGreg Ungerer printk("Frame format=%X ", regs->format); 800*144077eaSGreg Ungerer switch (regs->format) { 801*144077eaSGreg Ungerer case 0x2: 802*144077eaSGreg Ungerer printk("instr addr=%08lx\n", fp->un.fmt2.iaddr); 803*144077eaSGreg Ungerer addr += sizeof(fp->un.fmt2); 804*144077eaSGreg Ungerer break; 805*144077eaSGreg Ungerer case 0x3: 806*144077eaSGreg Ungerer printk("eff addr=%08lx\n", fp->un.fmt3.effaddr); 807*144077eaSGreg Ungerer addr += sizeof(fp->un.fmt3); 808*144077eaSGreg Ungerer break; 809*144077eaSGreg Ungerer case 0x4: 810*144077eaSGreg Ungerer printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n" 811*144077eaSGreg Ungerer : "eff addr=%08lx pc=%08lx\n"), 812*144077eaSGreg Ungerer fp->un.fmt4.effaddr, fp->un.fmt4.pc); 813*144077eaSGreg Ungerer addr += sizeof(fp->un.fmt4); 814*144077eaSGreg Ungerer break; 815*144077eaSGreg Ungerer case 0x7: 816*144077eaSGreg Ungerer printk("eff addr=%08lx ssw=%04x faddr=%08lx\n", 817*144077eaSGreg Ungerer fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr); 818*144077eaSGreg Ungerer printk("wb 1 stat/addr/data: %04x %08lx %08lx\n", 819*144077eaSGreg Ungerer fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0); 820*144077eaSGreg Ungerer printk("wb 2 stat/addr/data: %04x %08lx %08lx\n", 821*144077eaSGreg Ungerer fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d); 822*144077eaSGreg Ungerer printk("wb 3 stat/addr/data: %04x %08lx %08lx\n", 823*144077eaSGreg Ungerer fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d); 824*144077eaSGreg Ungerer printk("push data: %08lx %08lx %08lx %08lx\n", 825*144077eaSGreg Ungerer fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2, 826*144077eaSGreg Ungerer fp->un.fmt7.pd3); 827*144077eaSGreg Ungerer addr += sizeof(fp->un.fmt7); 828*144077eaSGreg Ungerer break; 829*144077eaSGreg Ungerer case 0x9: 830*144077eaSGreg Ungerer printk("instr addr=%08lx\n", fp->un.fmt9.iaddr); 831*144077eaSGreg Ungerer addr += sizeof(fp->un.fmt9); 832*144077eaSGreg Ungerer break; 833*144077eaSGreg Ungerer case 0xa: 834*144077eaSGreg Ungerer printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", 835*144077eaSGreg Ungerer fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb, 836*144077eaSGreg Ungerer fp->un.fmta.daddr, fp->un.fmta.dobuf); 837*144077eaSGreg Ungerer addr += sizeof(fp->un.fmta); 838*144077eaSGreg Ungerer break; 839*144077eaSGreg Ungerer case 0xb: 840*144077eaSGreg Ungerer printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n", 841*144077eaSGreg Ungerer fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb, 842*144077eaSGreg Ungerer fp->un.fmtb.daddr, fp->un.fmtb.dobuf); 843*144077eaSGreg Ungerer printk("baddr=%08lx dibuf=%08lx ver=%x\n", 844*144077eaSGreg Ungerer fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver); 845*144077eaSGreg Ungerer addr += sizeof(fp->un.fmtb); 846*144077eaSGreg Ungerer break; 847*144077eaSGreg Ungerer default: 848*144077eaSGreg Ungerer printk("\n"); 849*144077eaSGreg Ungerer } 850*144077eaSGreg Ungerer show_stack(NULL, (unsigned long *)addr); 851*144077eaSGreg Ungerer 852*144077eaSGreg Ungerer printk("Code:"); 853*144077eaSGreg Ungerer set_fs(KERNEL_DS); 854*144077eaSGreg Ungerer cp = (u16 *)regs->pc; 855*144077eaSGreg Ungerer for (i = -8; i < 16; i++) { 856*144077eaSGreg Ungerer if (get_user(c, cp + i) && i >= 0) { 857*144077eaSGreg Ungerer printk(" Bad PC value."); 858*144077eaSGreg Ungerer break; 859*144077eaSGreg Ungerer } 860*144077eaSGreg Ungerer printk(i ? " %04x" : " <%04x>", c); 861*144077eaSGreg Ungerer } 862*144077eaSGreg Ungerer set_fs(old_fs); 863*144077eaSGreg Ungerer printk ("\n"); 864*144077eaSGreg Ungerer } 865*144077eaSGreg Ungerer 866*144077eaSGreg Ungerer void show_stack(struct task_struct *task, unsigned long *stack) 867*144077eaSGreg Ungerer { 868*144077eaSGreg Ungerer unsigned long *p; 869*144077eaSGreg Ungerer unsigned long *endstack; 870*144077eaSGreg Ungerer int i; 871*144077eaSGreg Ungerer 872*144077eaSGreg Ungerer if (!stack) { 873*144077eaSGreg Ungerer if (task) 874*144077eaSGreg Ungerer stack = (unsigned long *)task->thread.esp0; 875*144077eaSGreg Ungerer else 876*144077eaSGreg Ungerer stack = (unsigned long *)&stack; 877*144077eaSGreg Ungerer } 878*144077eaSGreg Ungerer endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE); 879*144077eaSGreg Ungerer 880*144077eaSGreg Ungerer printk("Stack from %08lx:", (unsigned long)stack); 881*144077eaSGreg Ungerer p = stack; 882*144077eaSGreg Ungerer for (i = 0; i < kstack_depth_to_print; i++) { 883*144077eaSGreg Ungerer if (p + 1 > endstack) 884*144077eaSGreg Ungerer break; 885*144077eaSGreg Ungerer if (i % 8 == 0) 886*144077eaSGreg Ungerer printk("\n "); 887*144077eaSGreg Ungerer printk(" %08lx", *p++); 888*144077eaSGreg Ungerer } 889*144077eaSGreg Ungerer printk("\n"); 890*144077eaSGreg Ungerer show_trace(stack); 891*144077eaSGreg Ungerer } 892*144077eaSGreg Ungerer 893*144077eaSGreg Ungerer /* 894*144077eaSGreg Ungerer * The architecture-independent backtrace generator 895*144077eaSGreg Ungerer */ 896*144077eaSGreg Ungerer void dump_stack(void) 897*144077eaSGreg Ungerer { 898*144077eaSGreg Ungerer unsigned long stack; 899*144077eaSGreg Ungerer 900*144077eaSGreg Ungerer show_trace(&stack); 901*144077eaSGreg Ungerer } 902*144077eaSGreg Ungerer 903*144077eaSGreg Ungerer EXPORT_SYMBOL(dump_stack); 904*144077eaSGreg Ungerer 905*144077eaSGreg Ungerer /* 906*144077eaSGreg Ungerer * The vector number returned in the frame pointer may also contain 907*144077eaSGreg Ungerer * the "fs" (Fault Status) bits on ColdFire. These are in the bottom 908*144077eaSGreg Ungerer * 2 bits, and upper 2 bits. So we need to mask out the real vector 909*144077eaSGreg Ungerer * number before using it in comparisons. You don't need to do this on 910*144077eaSGreg Ungerer * real 68k parts, but it won't hurt either. 911*144077eaSGreg Ungerer */ 912*144077eaSGreg Ungerer 913*144077eaSGreg Ungerer void bad_super_trap (struct frame *fp) 914*144077eaSGreg Ungerer { 915*144077eaSGreg Ungerer int vector = (fp->ptregs.vector >> 2) & 0xff; 916*144077eaSGreg Ungerer 917*144077eaSGreg Ungerer console_verbose(); 918*144077eaSGreg Ungerer if (vector < ARRAY_SIZE(vec_names)) 919*144077eaSGreg Ungerer printk ("*** %s *** FORMAT=%X\n", 920*144077eaSGreg Ungerer vec_names[vector], 921*144077eaSGreg Ungerer fp->ptregs.format); 922*144077eaSGreg Ungerer else 923*144077eaSGreg Ungerer printk ("*** Exception %d *** FORMAT=%X\n", 924*144077eaSGreg Ungerer vector, fp->ptregs.format); 925*144077eaSGreg Ungerer if (vector == VEC_ADDRERR && CPU_IS_020_OR_030) { 926*144077eaSGreg Ungerer unsigned short ssw = fp->un.fmtb.ssw; 927*144077eaSGreg Ungerer 928*144077eaSGreg Ungerer printk ("SSW=%#06x ", ssw); 929*144077eaSGreg Ungerer 930*144077eaSGreg Ungerer if (ssw & RC) 931*144077eaSGreg Ungerer printk ("Pipe stage C instruction fault at %#010lx\n", 932*144077eaSGreg Ungerer (fp->ptregs.format) == 0xA ? 933*144077eaSGreg Ungerer fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2); 934*144077eaSGreg Ungerer if (ssw & RB) 935*144077eaSGreg Ungerer printk ("Pipe stage B instruction fault at %#010lx\n", 936*144077eaSGreg Ungerer (fp->ptregs.format) == 0xA ? 937*144077eaSGreg Ungerer fp->ptregs.pc + 4 : fp->un.fmtb.baddr); 938*144077eaSGreg Ungerer if (ssw & DF) 939*144077eaSGreg Ungerer printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n", 940*144077eaSGreg Ungerer ssw & RW ? "read" : "write", 941*144077eaSGreg Ungerer fp->un.fmtb.daddr, space_names[ssw & DFC], 942*144077eaSGreg Ungerer fp->ptregs.pc); 943*144077eaSGreg Ungerer } 944*144077eaSGreg Ungerer printk ("Current process id is %d\n", task_pid_nr(current)); 945*144077eaSGreg Ungerer die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0); 946*144077eaSGreg Ungerer } 947*144077eaSGreg Ungerer 948*144077eaSGreg Ungerer asmlinkage void trap_c(struct frame *fp) 949*144077eaSGreg Ungerer { 950*144077eaSGreg Ungerer int sig; 951*144077eaSGreg Ungerer int vector = (fp->ptregs.vector >> 2) & 0xff; 952*144077eaSGreg Ungerer siginfo_t info; 953*144077eaSGreg Ungerer 954*144077eaSGreg Ungerer if (fp->ptregs.sr & PS_S) { 955*144077eaSGreg Ungerer if (vector == VEC_TRACE) { 956*144077eaSGreg Ungerer /* traced a trapping instruction on a 68020/30, 957*144077eaSGreg Ungerer * real exception will be executed afterwards. 958*144077eaSGreg Ungerer */ 959*144077eaSGreg Ungerer } else if (!handle_kernel_fault(&fp->ptregs)) 960*144077eaSGreg Ungerer bad_super_trap(fp); 961*144077eaSGreg Ungerer return; 962*144077eaSGreg Ungerer } 963*144077eaSGreg Ungerer 964*144077eaSGreg Ungerer /* send the appropriate signal to the user program */ 965*144077eaSGreg Ungerer switch (vector) { 966*144077eaSGreg Ungerer case VEC_ADDRERR: 967*144077eaSGreg Ungerer info.si_code = BUS_ADRALN; 968*144077eaSGreg Ungerer sig = SIGBUS; 969*144077eaSGreg Ungerer break; 970*144077eaSGreg Ungerer case VEC_ILLEGAL: 971*144077eaSGreg Ungerer case VEC_LINE10: 972*144077eaSGreg Ungerer case VEC_LINE11: 973*144077eaSGreg Ungerer info.si_code = ILL_ILLOPC; 974*144077eaSGreg Ungerer sig = SIGILL; 975*144077eaSGreg Ungerer break; 976*144077eaSGreg Ungerer case VEC_PRIV: 977*144077eaSGreg Ungerer info.si_code = ILL_PRVOPC; 978*144077eaSGreg Ungerer sig = SIGILL; 979*144077eaSGreg Ungerer break; 980*144077eaSGreg Ungerer case VEC_COPROC: 981*144077eaSGreg Ungerer info.si_code = ILL_COPROC; 982*144077eaSGreg Ungerer sig = SIGILL; 983*144077eaSGreg Ungerer break; 984*144077eaSGreg Ungerer case VEC_TRAP1: 985*144077eaSGreg Ungerer case VEC_TRAP2: 986*144077eaSGreg Ungerer case VEC_TRAP3: 987*144077eaSGreg Ungerer case VEC_TRAP4: 988*144077eaSGreg Ungerer case VEC_TRAP5: 989*144077eaSGreg Ungerer case VEC_TRAP6: 990*144077eaSGreg Ungerer case VEC_TRAP7: 991*144077eaSGreg Ungerer case VEC_TRAP8: 992*144077eaSGreg Ungerer case VEC_TRAP9: 993*144077eaSGreg Ungerer case VEC_TRAP10: 994*144077eaSGreg Ungerer case VEC_TRAP11: 995*144077eaSGreg Ungerer case VEC_TRAP12: 996*144077eaSGreg Ungerer case VEC_TRAP13: 997*144077eaSGreg Ungerer case VEC_TRAP14: 998*144077eaSGreg Ungerer info.si_code = ILL_ILLTRP; 999*144077eaSGreg Ungerer sig = SIGILL; 1000*144077eaSGreg Ungerer break; 1001*144077eaSGreg Ungerer case VEC_FPBRUC: 1002*144077eaSGreg Ungerer case VEC_FPOE: 1003*144077eaSGreg Ungerer case VEC_FPNAN: 1004*144077eaSGreg Ungerer info.si_code = FPE_FLTINV; 1005*144077eaSGreg Ungerer sig = SIGFPE; 1006*144077eaSGreg Ungerer break; 1007*144077eaSGreg Ungerer case VEC_FPIR: 1008*144077eaSGreg Ungerer info.si_code = FPE_FLTRES; 1009*144077eaSGreg Ungerer sig = SIGFPE; 1010*144077eaSGreg Ungerer break; 1011*144077eaSGreg Ungerer case VEC_FPDIVZ: 1012*144077eaSGreg Ungerer info.si_code = FPE_FLTDIV; 1013*144077eaSGreg Ungerer sig = SIGFPE; 1014*144077eaSGreg Ungerer break; 1015*144077eaSGreg Ungerer case VEC_FPUNDER: 1016*144077eaSGreg Ungerer info.si_code = FPE_FLTUND; 1017*144077eaSGreg Ungerer sig = SIGFPE; 1018*144077eaSGreg Ungerer break; 1019*144077eaSGreg Ungerer case VEC_FPOVER: 1020*144077eaSGreg Ungerer info.si_code = FPE_FLTOVF; 1021*144077eaSGreg Ungerer sig = SIGFPE; 1022*144077eaSGreg Ungerer break; 1023*144077eaSGreg Ungerer case VEC_ZERODIV: 1024*144077eaSGreg Ungerer info.si_code = FPE_INTDIV; 1025*144077eaSGreg Ungerer sig = SIGFPE; 1026*144077eaSGreg Ungerer break; 1027*144077eaSGreg Ungerer case VEC_CHK: 1028*144077eaSGreg Ungerer case VEC_TRAP: 1029*144077eaSGreg Ungerer info.si_code = FPE_INTOVF; 1030*144077eaSGreg Ungerer sig = SIGFPE; 1031*144077eaSGreg Ungerer break; 1032*144077eaSGreg Ungerer case VEC_TRACE: /* ptrace single step */ 1033*144077eaSGreg Ungerer info.si_code = TRAP_TRACE; 1034*144077eaSGreg Ungerer sig = SIGTRAP; 1035*144077eaSGreg Ungerer break; 1036*144077eaSGreg Ungerer case VEC_TRAP15: /* breakpoint */ 1037*144077eaSGreg Ungerer info.si_code = TRAP_BRKPT; 1038*144077eaSGreg Ungerer sig = SIGTRAP; 1039*144077eaSGreg Ungerer break; 1040*144077eaSGreg Ungerer default: 1041*144077eaSGreg Ungerer info.si_code = ILL_ILLOPC; 1042*144077eaSGreg Ungerer sig = SIGILL; 1043*144077eaSGreg Ungerer break; 1044*144077eaSGreg Ungerer } 1045*144077eaSGreg Ungerer info.si_signo = sig; 1046*144077eaSGreg Ungerer info.si_errno = 0; 1047*144077eaSGreg Ungerer switch (fp->ptregs.format) { 1048*144077eaSGreg Ungerer default: 1049*144077eaSGreg Ungerer info.si_addr = (void *) fp->ptregs.pc; 1050*144077eaSGreg Ungerer break; 1051*144077eaSGreg Ungerer case 2: 1052*144077eaSGreg Ungerer info.si_addr = (void *) fp->un.fmt2.iaddr; 1053*144077eaSGreg Ungerer break; 1054*144077eaSGreg Ungerer case 7: 1055*144077eaSGreg Ungerer info.si_addr = (void *) fp->un.fmt7.effaddr; 1056*144077eaSGreg Ungerer break; 1057*144077eaSGreg Ungerer case 9: 1058*144077eaSGreg Ungerer info.si_addr = (void *) fp->un.fmt9.iaddr; 1059*144077eaSGreg Ungerer break; 1060*144077eaSGreg Ungerer case 10: 1061*144077eaSGreg Ungerer info.si_addr = (void *) fp->un.fmta.daddr; 1062*144077eaSGreg Ungerer break; 1063*144077eaSGreg Ungerer case 11: 1064*144077eaSGreg Ungerer info.si_addr = (void *) fp->un.fmtb.daddr; 1065*144077eaSGreg Ungerer break; 1066*144077eaSGreg Ungerer } 1067*144077eaSGreg Ungerer force_sig_info (sig, &info, current); 1068*144077eaSGreg Ungerer } 1069*144077eaSGreg Ungerer 1070*144077eaSGreg Ungerer void die_if_kernel (char *str, struct pt_regs *fp, int nr) 1071*144077eaSGreg Ungerer { 1072*144077eaSGreg Ungerer if (!(fp->sr & PS_S)) 1073*144077eaSGreg Ungerer return; 1074*144077eaSGreg Ungerer 1075*144077eaSGreg Ungerer console_verbose(); 1076*144077eaSGreg Ungerer printk("%s: %08x\n",str,nr); 1077*144077eaSGreg Ungerer show_registers(fp); 1078*144077eaSGreg Ungerer add_taint(TAINT_DIE); 1079*144077eaSGreg Ungerer do_exit(SIGSEGV); 1080*144077eaSGreg Ungerer } 1081*144077eaSGreg Ungerer 1082*144077eaSGreg Ungerer asmlinkage void set_esp0(unsigned long ssp) 1083*144077eaSGreg Ungerer { 1084*144077eaSGreg Ungerer current->thread.esp0 = ssp; 1085*144077eaSGreg Ungerer } 1086*144077eaSGreg Ungerer 1087*144077eaSGreg Ungerer /* 1088*144077eaSGreg Ungerer * This function is called if an error occur while accessing 1089*144077eaSGreg Ungerer * user-space from the fpsp040 code. 1090*144077eaSGreg Ungerer */ 1091*144077eaSGreg Ungerer asmlinkage void fpsp040_die(void) 1092*144077eaSGreg Ungerer { 1093*144077eaSGreg Ungerer do_exit(SIGSEGV); 1094*144077eaSGreg Ungerer } 1095*144077eaSGreg Ungerer 1096*144077eaSGreg Ungerer #ifdef CONFIG_M68KFPU_EMU 1097*144077eaSGreg Ungerer asmlinkage void fpemu_signal(int signal, int code, void *addr) 1098*144077eaSGreg Ungerer { 1099*144077eaSGreg Ungerer siginfo_t info; 1100*144077eaSGreg Ungerer 1101*144077eaSGreg Ungerer info.si_signo = signal; 1102*144077eaSGreg Ungerer info.si_errno = 0; 1103*144077eaSGreg Ungerer info.si_code = code; 1104*144077eaSGreg Ungerer info.si_addr = addr; 1105*144077eaSGreg Ungerer force_sig_info(signal, &info, current); 1106*144077eaSGreg Ungerer } 11071da177e4SLinus Torvalds #endif 1108