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