Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

m68k: merge the mmu and non-mmu traps.c files

The code for handling traps in the non-mmu case is a subset of the mmu
enabled case. Merge the non-mmu traps_no.c code back to a single traps.c.
There is actually no code mmu specific here at all, and the processor
specific code (for the more complex 68020/68030/68040/68060) is already
proplerly conditionaly used.

The format of console exception dump is a little different, but I don't
think will cause any one problems, it is purely for debug purposes.

Signed-off-by: Greg Ungerer <gerg@uclinux.org>

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