1/* 2 * Main exception handling logic. 3 * 4 * Copyright 2004-2010 Analog Devices Inc. 5 * 6 * Licensed under the GPL-2 or later 7 */ 8 9#include <linux/bug.h> 10#include <linux/uaccess.h> 11#include <linux/module.h> 12#include <asm/traps.h> 13#include <asm/cplb.h> 14#include <asm/blackfin.h> 15#include <asm/irq_handler.h> 16#include <linux/irq.h> 17#include <asm/trace.h> 18#include <asm/fixed_code.h> 19#include <asm/pseudo_instructions.h> 20#include <asm/pda.h> 21 22#ifdef CONFIG_KGDB 23# include <linux/kgdb.h> 24 25# define CHK_DEBUGGER_TRAP() \ 26 do { \ 27 kgdb_handle_exception(trapnr, sig, info.si_code, fp); \ 28 } while (0) 29# define CHK_DEBUGGER_TRAP_MAYBE() \ 30 do { \ 31 if (kgdb_connected) \ 32 CHK_DEBUGGER_TRAP(); \ 33 } while (0) 34#else 35# define CHK_DEBUGGER_TRAP() do { } while (0) 36# define CHK_DEBUGGER_TRAP_MAYBE() do { } while (0) 37#endif 38 39 40#ifdef CONFIG_DEBUG_VERBOSE 41#define verbose_printk(fmt, arg...) \ 42 printk(fmt, ##arg) 43#else 44#define verbose_printk(fmt, arg...) \ 45 ({ if (0) printk(fmt, ##arg); 0; }) 46#endif 47 48#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE) 49u32 last_seqstat; 50#ifdef CONFIG_DEBUG_MMRS_MODULE 51EXPORT_SYMBOL(last_seqstat); 52#endif 53#endif 54 55/* Initiate the event table handler */ 56void __init trap_init(void) 57{ 58 CSYNC(); 59 bfin_write_EVT3(trap); 60 CSYNC(); 61} 62 63static int kernel_mode_regs(struct pt_regs *regs) 64{ 65 return regs->ipend & 0xffc0; 66} 67 68asmlinkage notrace void trap_c(struct pt_regs *fp) 69{ 70#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 71 int j; 72#endif 73#ifdef CONFIG_BFIN_PSEUDODBG_INSNS 74 int opcode; 75#endif 76 unsigned int cpu = raw_smp_processor_id(); 77 const char *strerror = NULL; 78 int sig = 0; 79 siginfo_t info; 80 unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; 81 82 trace_buffer_save(j); 83#if defined(CONFIG_DEBUG_MMRS) || defined(CONFIG_DEBUG_MMRS_MODULE) 84 last_seqstat = (u32)fp->seqstat; 85#endif 86 87 /* Important - be very careful dereferncing pointers - will lead to 88 * double faults if the stack has become corrupt 89 */ 90 91 /* trap_c() will be called for exceptions. During exceptions 92 * processing, the pc value should be set with retx value. 93 * With this change we can cleanup some code in signal.c- TODO 94 */ 95 fp->orig_pc = fp->retx; 96 /* printk("exception: 0x%x, ipend=%x, reti=%x, retx=%x\n", 97 trapnr, fp->ipend, fp->pc, fp->retx); */ 98 99 /* send the appropriate signal to the user program */ 100 switch (trapnr) { 101 102 /* This table works in conjunction with the one in ./mach-common/entry.S 103 * Some exceptions are handled there (in assembly, in exception space) 104 * Some are handled here, (in C, in interrupt space) 105 * Some, like CPLB, are handled in both, where the normal path is 106 * handled in assembly/exception space, and the error path is handled 107 * here 108 */ 109 110 /* 0x00 - Linux Syscall, getting here is an error */ 111 /* 0x01 - userspace gdb breakpoint, handled here */ 112 case VEC_EXCPT01: 113 info.si_code = TRAP_ILLTRAP; 114 sig = SIGTRAP; 115 CHK_DEBUGGER_TRAP_MAYBE(); 116 /* Check if this is a breakpoint in kernel space */ 117 if (kernel_mode_regs(fp)) 118 goto traps_done; 119 else 120 break; 121 /* 0x03 - User Defined, userspace stack overflow */ 122 case VEC_EXCPT03: 123 info.si_code = SEGV_STACKFLOW; 124 sig = SIGSEGV; 125 strerror = KERN_NOTICE EXC_0x03(KERN_NOTICE); 126 CHK_DEBUGGER_TRAP_MAYBE(); 127 break; 128 /* 0x02 - KGDB initial connection and break signal trap */ 129 case VEC_EXCPT02: 130#ifdef CONFIG_KGDB 131 info.si_code = TRAP_ILLTRAP; 132 sig = SIGTRAP; 133 CHK_DEBUGGER_TRAP(); 134 goto traps_done; 135#endif 136 /* 0x04 - User Defined */ 137 /* 0x05 - User Defined */ 138 /* 0x06 - User Defined */ 139 /* 0x07 - User Defined */ 140 /* 0x08 - User Defined */ 141 /* 0x09 - User Defined */ 142 /* 0x0A - User Defined */ 143 /* 0x0B - User Defined */ 144 /* 0x0C - User Defined */ 145 /* 0x0D - User Defined */ 146 /* 0x0E - User Defined */ 147 /* 0x0F - User Defined */ 148 /* If we got here, it is most likely that someone was trying to use a 149 * custom exception handler, and it is not actually installed properly 150 */ 151 case VEC_EXCPT04 ... VEC_EXCPT15: 152 info.si_code = ILL_ILLPARAOP; 153 sig = SIGILL; 154 strerror = KERN_NOTICE EXC_0x04(KERN_NOTICE); 155 CHK_DEBUGGER_TRAP_MAYBE(); 156 break; 157 /* 0x10 HW Single step, handled here */ 158 case VEC_STEP: 159 info.si_code = TRAP_STEP; 160 sig = SIGTRAP; 161 CHK_DEBUGGER_TRAP_MAYBE(); 162 /* Check if this is a single step in kernel space */ 163 if (kernel_mode_regs(fp)) 164 goto traps_done; 165 else 166 break; 167 /* 0x11 - Trace Buffer Full, handled here */ 168 case VEC_OVFLOW: 169 info.si_code = TRAP_TRACEFLOW; 170 sig = SIGTRAP; 171 strerror = KERN_NOTICE EXC_0x11(KERN_NOTICE); 172 CHK_DEBUGGER_TRAP_MAYBE(); 173 break; 174 /* 0x12 - Reserved, Caught by default */ 175 /* 0x13 - Reserved, Caught by default */ 176 /* 0x14 - Reserved, Caught by default */ 177 /* 0x15 - Reserved, Caught by default */ 178 /* 0x16 - Reserved, Caught by default */ 179 /* 0x17 - Reserved, Caught by default */ 180 /* 0x18 - Reserved, Caught by default */ 181 /* 0x19 - Reserved, Caught by default */ 182 /* 0x1A - Reserved, Caught by default */ 183 /* 0x1B - Reserved, Caught by default */ 184 /* 0x1C - Reserved, Caught by default */ 185 /* 0x1D - Reserved, Caught by default */ 186 /* 0x1E - Reserved, Caught by default */ 187 /* 0x1F - Reserved, Caught by default */ 188 /* 0x20 - Reserved, Caught by default */ 189 /* 0x21 - Undefined Instruction, handled here */ 190 case VEC_UNDEF_I: 191#ifdef CONFIG_BUG 192 if (kernel_mode_regs(fp)) { 193 switch (report_bug(fp->pc, fp)) { 194 case BUG_TRAP_TYPE_NONE: 195 break; 196 case BUG_TRAP_TYPE_WARN: 197 dump_bfin_trace_buffer(); 198 fp->pc += 2; 199 goto traps_done; 200 case BUG_TRAP_TYPE_BUG: 201 /* call to panic() will dump trace, and it is 202 * off at this point, so it won't be clobbered 203 */ 204 panic("BUG()"); 205 } 206 } 207#endif 208#ifdef CONFIG_BFIN_PSEUDODBG_INSNS 209 /* 210 * Support for the fake instructions, if the instruction fails, 211 * then just execute a illegal opcode failure (like normal). 212 * Don't support these instructions inside the kernel 213 */ 214 if (!kernel_mode_regs(fp) && get_instruction(&opcode, (unsigned short *)fp->pc)) { 215 if (execute_pseudodbg_assert(fp, opcode)) 216 goto traps_done; 217 if (execute_pseudodbg(fp, opcode)) 218 goto traps_done; 219 } 220#endif 221 info.si_code = ILL_ILLOPC; 222 sig = SIGILL; 223 strerror = KERN_NOTICE EXC_0x21(KERN_NOTICE); 224 CHK_DEBUGGER_TRAP_MAYBE(); 225 break; 226 /* 0x22 - Illegal Instruction Combination, handled here */ 227 case VEC_ILGAL_I: 228 info.si_code = ILL_ILLPARAOP; 229 sig = SIGILL; 230 strerror = KERN_NOTICE EXC_0x22(KERN_NOTICE); 231 CHK_DEBUGGER_TRAP_MAYBE(); 232 break; 233 /* 0x23 - Data CPLB protection violation, handled here */ 234 case VEC_CPLB_VL: 235 info.si_code = ILL_CPLB_VI; 236 sig = SIGSEGV; 237 strerror = KERN_NOTICE EXC_0x23(KERN_NOTICE); 238 CHK_DEBUGGER_TRAP_MAYBE(); 239 break; 240 /* 0x24 - Data access misaligned, handled here */ 241 case VEC_MISALI_D: 242 info.si_code = BUS_ADRALN; 243 sig = SIGBUS; 244 strerror = KERN_NOTICE EXC_0x24(KERN_NOTICE); 245 CHK_DEBUGGER_TRAP_MAYBE(); 246 break; 247 /* 0x25 - Unrecoverable Event, handled here */ 248 case VEC_UNCOV: 249 info.si_code = ILL_ILLEXCPT; 250 sig = SIGILL; 251 strerror = KERN_NOTICE EXC_0x25(KERN_NOTICE); 252 CHK_DEBUGGER_TRAP_MAYBE(); 253 break; 254 /* 0x26 - Data CPLB Miss, normal case is handled in _cplb_hdr, 255 error case is handled here */ 256 case VEC_CPLB_M: 257 info.si_code = BUS_ADRALN; 258 sig = SIGBUS; 259 strerror = KERN_NOTICE EXC_0x26(KERN_NOTICE); 260 break; 261 /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero, handled here */ 262 case VEC_CPLB_MHIT: 263 info.si_code = ILL_CPLB_MULHIT; 264 sig = SIGSEGV; 265#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 266 if (cpu_pda[cpu].dcplb_fault_addr < FIXED_CODE_START) 267 strerror = KERN_NOTICE "NULL pointer access\n"; 268 else 269#endif 270 strerror = KERN_NOTICE EXC_0x27(KERN_NOTICE); 271 CHK_DEBUGGER_TRAP_MAYBE(); 272 break; 273 /* 0x28 - Emulation Watchpoint, handled here */ 274 case VEC_WATCH: 275 info.si_code = TRAP_WATCHPT; 276 sig = SIGTRAP; 277 pr_debug(EXC_0x28(KERN_DEBUG)); 278 CHK_DEBUGGER_TRAP_MAYBE(); 279 /* Check if this is a watchpoint in kernel space */ 280 if (kernel_mode_regs(fp)) 281 goto traps_done; 282 else 283 break; 284#ifdef CONFIG_BF535 285 /* 0x29 - Instruction fetch access error (535 only) */ 286 case VEC_ISTRU_VL: /* ADSP-BF535 only (MH) */ 287 info.si_code = BUS_OPFETCH; 288 sig = SIGBUS; 289 strerror = KERN_NOTICE "BF535: VEC_ISTRU_VL\n"; 290 CHK_DEBUGGER_TRAP_MAYBE(); 291 break; 292#else 293 /* 0x29 - Reserved, Caught by default */ 294#endif 295 /* 0x2A - Instruction fetch misaligned, handled here */ 296 case VEC_MISALI_I: 297 info.si_code = BUS_ADRALN; 298 sig = SIGBUS; 299 strerror = KERN_NOTICE EXC_0x2A(KERN_NOTICE); 300 CHK_DEBUGGER_TRAP_MAYBE(); 301 break; 302 /* 0x2B - Instruction CPLB protection violation, handled here */ 303 case VEC_CPLB_I_VL: 304 info.si_code = ILL_CPLB_VI; 305 sig = SIGBUS; 306 strerror = KERN_NOTICE EXC_0x2B(KERN_NOTICE); 307 CHK_DEBUGGER_TRAP_MAYBE(); 308 break; 309 /* 0x2C - Instruction CPLB miss, handled in _cplb_hdr */ 310 case VEC_CPLB_I_M: 311 info.si_code = ILL_CPLB_MISS; 312 sig = SIGBUS; 313 strerror = KERN_NOTICE EXC_0x2C(KERN_NOTICE); 314 break; 315 /* 0x2D - Instruction CPLB Multiple Hits, handled here */ 316 case VEC_CPLB_I_MHIT: 317 info.si_code = ILL_CPLB_MULHIT; 318 sig = SIGSEGV; 319#ifdef CONFIG_DEBUG_HUNT_FOR_ZERO 320 if (cpu_pda[cpu].icplb_fault_addr < FIXED_CODE_START) 321 strerror = KERN_NOTICE "Jump to NULL address\n"; 322 else 323#endif 324 strerror = KERN_NOTICE EXC_0x2D(KERN_NOTICE); 325 CHK_DEBUGGER_TRAP_MAYBE(); 326 break; 327 /* 0x2E - Illegal use of Supervisor Resource, handled here */ 328 case VEC_ILL_RES: 329 info.si_code = ILL_PRVOPC; 330 sig = SIGILL; 331 strerror = KERN_NOTICE EXC_0x2E(KERN_NOTICE); 332 CHK_DEBUGGER_TRAP_MAYBE(); 333 break; 334 /* 0x2F - Reserved, Caught by default */ 335 /* 0x30 - Reserved, Caught by default */ 336 /* 0x31 - Reserved, Caught by default */ 337 /* 0x32 - Reserved, Caught by default */ 338 /* 0x33 - Reserved, Caught by default */ 339 /* 0x34 - Reserved, Caught by default */ 340 /* 0x35 - Reserved, Caught by default */ 341 /* 0x36 - Reserved, Caught by default */ 342 /* 0x37 - Reserved, Caught by default */ 343 /* 0x38 - Reserved, Caught by default */ 344 /* 0x39 - Reserved, Caught by default */ 345 /* 0x3A - Reserved, Caught by default */ 346 /* 0x3B - Reserved, Caught by default */ 347 /* 0x3C - Reserved, Caught by default */ 348 /* 0x3D - Reserved, Caught by default */ 349 /* 0x3E - Reserved, Caught by default */ 350 /* 0x3F - Reserved, Caught by default */ 351 case VEC_HWERR: 352 info.si_code = BUS_ADRALN; 353 sig = SIGBUS; 354 switch (fp->seqstat & SEQSTAT_HWERRCAUSE) { 355 /* System MMR Error */ 356 case (SEQSTAT_HWERRCAUSE_SYSTEM_MMR): 357 info.si_code = BUS_ADRALN; 358 sig = SIGBUS; 359 strerror = KERN_NOTICE HWC_x2(KERN_NOTICE); 360 break; 361 /* External Memory Addressing Error */ 362 case (SEQSTAT_HWERRCAUSE_EXTERN_ADDR): 363 if (ANOMALY_05000310) { 364 static unsigned long anomaly_rets; 365 366 if ((fp->pc >= (L1_CODE_START + L1_CODE_LENGTH - 512)) && 367 (fp->pc < (L1_CODE_START + L1_CODE_LENGTH))) { 368 /* 369 * A false hardware error will happen while fetching at 370 * the L1 instruction SRAM boundary. Ignore it. 371 */ 372 anomaly_rets = fp->rets; 373 goto traps_done; 374 } else if (fp->rets == anomaly_rets) { 375 /* 376 * While boundary code returns to a function, at the ret 377 * point, a new false hardware error might occur too based 378 * on tests. Ignore it too. 379 */ 380 goto traps_done; 381 } else if ((fp->rets >= (L1_CODE_START + L1_CODE_LENGTH - 512)) && 382 (fp->rets < (L1_CODE_START + L1_CODE_LENGTH))) { 383 /* 384 * If boundary code calls a function, at the entry point, 385 * a new false hardware error maybe happen based on tests. 386 * Ignore it too. 387 */ 388 goto traps_done; 389 } else 390 anomaly_rets = 0; 391 } 392 393 info.si_code = BUS_ADRERR; 394 sig = SIGBUS; 395 strerror = KERN_NOTICE HWC_x3(KERN_NOTICE); 396 break; 397 /* Performance Monitor Overflow */ 398 case (SEQSTAT_HWERRCAUSE_PERF_FLOW): 399 strerror = KERN_NOTICE HWC_x12(KERN_NOTICE); 400 break; 401 /* RAISE 5 instruction */ 402 case (SEQSTAT_HWERRCAUSE_RAISE_5): 403 printk(KERN_NOTICE HWC_x18(KERN_NOTICE)); 404 break; 405 default: /* Reserved */ 406 printk(KERN_NOTICE HWC_default(KERN_NOTICE)); 407 break; 408 } 409 CHK_DEBUGGER_TRAP_MAYBE(); 410 break; 411 /* 412 * We should be handling all known exception types above, 413 * if we get here we hit a reserved one, so panic 414 */ 415 default: 416 info.si_code = ILL_ILLPARAOP; 417 sig = SIGILL; 418 verbose_printk(KERN_EMERG "Caught Unhandled Exception, code = %08lx\n", 419 (fp->seqstat & SEQSTAT_EXCAUSE)); 420 CHK_DEBUGGER_TRAP_MAYBE(); 421 break; 422 } 423 424 BUG_ON(sig == 0); 425 426 /* If the fault was caused by a kernel thread, or interrupt handler 427 * we will kernel panic, so the system reboots. 428 */ 429 if (kernel_mode_regs(fp) || (current && !current->mm)) { 430 console_verbose(); 431 oops_in_progress = 1; 432 } 433 434 if (sig != SIGTRAP) { 435 if (strerror) 436 verbose_printk(strerror); 437 438 dump_bfin_process(fp); 439 dump_bfin_mem(fp); 440 show_regs(fp); 441 442 /* Print out the trace buffer if it makes sense */ 443#ifndef CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE 444 if (trapnr == VEC_CPLB_I_M || trapnr == VEC_CPLB_M) 445 verbose_printk(KERN_NOTICE "No trace since you do not have " 446 "CONFIG_DEBUG_BFIN_NO_KERN_HWTRACE enabled\n\n"); 447 else 448#endif 449 dump_bfin_trace_buffer(); 450 451 if (oops_in_progress) { 452 /* Dump the current kernel stack */ 453 verbose_printk(KERN_NOTICE "Kernel Stack\n"); 454 show_stack(current, NULL); 455 print_modules(); 456#ifndef CONFIG_ACCESS_CHECK 457 verbose_printk(KERN_EMERG "Please turn on " 458 "CONFIG_ACCESS_CHECK\n"); 459#endif 460 panic("Kernel exception"); 461 } else { 462#ifdef CONFIG_DEBUG_VERBOSE 463 unsigned long *stack; 464 /* Dump the user space stack */ 465 stack = (unsigned long *)rdusp(); 466 verbose_printk(KERN_NOTICE "Userspace Stack\n"); 467 show_stack(NULL, stack); 468#endif 469 } 470 } 471 472#ifdef CONFIG_IPIPE 473 if (!ipipe_trap_notify(fp->seqstat & 0x3f, fp)) 474#endif 475 { 476 info.si_signo = sig; 477 info.si_errno = 0; 478 switch (trapnr) { 479 case VEC_CPLB_VL: 480 case VEC_MISALI_D: 481 case VEC_CPLB_M: 482 case VEC_CPLB_MHIT: 483 info.si_addr = (void __user *)cpu_pda[cpu].dcplb_fault_addr; 484 break; 485 default: 486 info.si_addr = (void __user *)fp->pc; 487 break; 488 } 489 force_sig_info(sig, &info, current); 490 } 491 492 if ((ANOMALY_05000461 && trapnr == VEC_HWERR && !access_ok(VERIFY_READ, fp->pc, 8)) || 493 (ANOMALY_05000281 && trapnr == VEC_HWERR) || 494 (ANOMALY_05000189 && (trapnr == VEC_CPLB_I_VL || trapnr == VEC_CPLB_VL))) 495 fp->pc = SAFE_USER_INSTRUCTION; 496 497 traps_done: 498 trace_buffer_restore(j); 499} 500 501asmlinkage void double_fault_c(struct pt_regs *fp) 502{ 503#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON 504 int j; 505 trace_buffer_save(j); 506#endif 507 508 console_verbose(); 509 oops_in_progress = 1; 510#ifdef CONFIG_DEBUG_VERBOSE 511 printk(KERN_EMERG "Double Fault\n"); 512#ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT 513 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { 514 unsigned int cpu = raw_smp_processor_id(); 515 char buf[150]; 516 decode_address(buf, cpu_pda[cpu].retx_doublefault); 517 printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", 518 (unsigned int)cpu_pda[cpu].seqstat_doublefault & SEQSTAT_EXCAUSE, buf); 519 decode_address(buf, cpu_pda[cpu].dcplb_doublefault_addr); 520 printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); 521 decode_address(buf, cpu_pda[cpu].icplb_doublefault_addr); 522 printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); 523 524 decode_address(buf, fp->retx); 525 printk(KERN_NOTICE "The instruction at %s caused a double exception\n", buf); 526 } else 527#endif 528 { 529 dump_bfin_process(fp); 530 dump_bfin_mem(fp); 531 show_regs(fp); 532 dump_bfin_trace_buffer(); 533 } 534#endif 535 panic("Double Fault - unrecoverable event"); 536 537} 538 539 540void panic_cplb_error(int cplb_panic, struct pt_regs *fp) 541{ 542 switch (cplb_panic) { 543 case CPLB_NO_UNLOCKED: 544 printk(KERN_EMERG "All CPLBs are locked\n"); 545 break; 546 case CPLB_PROT_VIOL: 547 return; 548 case CPLB_NO_ADDR_MATCH: 549 return; 550 case CPLB_UNKNOWN_ERR: 551 printk(KERN_EMERG "Unknown CPLB Exception\n"); 552 break; 553 } 554 555 oops_in_progress = 1; 556 557 dump_bfin_process(fp); 558 dump_bfin_mem(fp); 559 show_regs(fp); 560 dump_stack(); 561 panic("Unrecoverable event"); 562} 563 564#ifdef CONFIG_BUG 565int is_valid_bugaddr(unsigned long addr) 566{ 567 unsigned int opcode; 568 569 if (!get_instruction(&opcode, (unsigned short *)addr)) 570 return 0; 571 572 return opcode == BFIN_BUG_OPCODE; 573} 574#endif 575 576/* stub this out */ 577#ifndef CONFIG_DEBUG_VERBOSE 578void show_regs(struct pt_regs *fp) 579{ 580 581} 582#endif 583