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