1/* MN10300 Exception handling 2 * 3 * Copyright (C) 2007 Matsushita Electric Industrial Co., Ltd. 4 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 5 * Modified by David Howells (dhowells@redhat.com) 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public Licence 9 * as published by the Free Software Foundation; either version 10 * 2 of the Licence, or (at your option) any later version. 11 */ 12#include <linux/sched.h> 13#include <linux/kernel.h> 14#include <linux/string.h> 15#include <linux/errno.h> 16#include <linux/ptrace.h> 17#include <linux/timer.h> 18#include <linux/mm.h> 19#include <linux/smp.h> 20#include <linux/init.h> 21#include <linux/delay.h> 22#include <linux/spinlock.h> 23#include <linux/interrupt.h> 24#include <linux/kallsyms.h> 25#include <linux/pci.h> 26#include <linux/kdebug.h> 27#include <linux/bug.h> 28#include <linux/irq.h> 29#include <asm/processor.h> 30#include <asm/system.h> 31#include <asm/uaccess.h> 32#include <asm/io.h> 33#include <asm/atomic.h> 34#include <asm/smp.h> 35#include <asm/pgalloc.h> 36#include <asm/cacheflush.h> 37#include <asm/cpu-regs.h> 38#include <asm/busctl-regs.h> 39#include <unit/leds.h> 40#include <asm/fpu.h> 41#include <asm/gdb-stub.h> 42#include <asm/sections.h> 43 44#if (CONFIG_INTERRUPT_VECTOR_BASE & 0xffffff) 45#error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!" 46#endif 47 48struct pt_regs *__frame; /* current frame pointer */ 49EXPORT_SYMBOL(__frame); 50 51int kstack_depth_to_print = 24; 52 53spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock); 54 55ATOMIC_NOTIFIER_HEAD(mn10300_die_chain); 56 57/* 58 * These constants are for searching for possible module text 59 * segments. MODULE_RANGE is a guess of how much space is likely 60 * to be vmalloced. 61 */ 62#define MODULE_RANGE (8 * 1024 * 1024) 63 64#define DO_ERROR(signr, prologue, str, name) \ 65asmlinkage void name(struct pt_regs *regs, u32 intcode) \ 66{ \ 67 prologue; \ 68 if (die_if_no_fixup(str, regs, intcode)) \ 69 return; \ 70 force_sig(signr, current); \ 71} 72 73#define DO_EINFO(signr, prologue, str, name, sicode) \ 74asmlinkage void name(struct pt_regs *regs, u32 intcode) \ 75{ \ 76 siginfo_t info; \ 77 prologue; \ 78 if (die_if_no_fixup(str, regs, intcode)) \ 79 return; \ 80 info.si_signo = signr; \ 81 if (signr == SIGILL && sicode == ILL_ILLOPC) { \ 82 uint8_t opcode; \ 83 if (get_user(opcode, (uint8_t __user *)regs->pc) == 0) \ 84 if (opcode == 0xff) \ 85 info.si_signo = SIGTRAP; \ 86 } \ 87 info.si_errno = 0; \ 88 info.si_code = sicode; \ 89 info.si_addr = (void *) regs->pc; \ 90 force_sig_info(info.si_signo, &info, current); \ 91} 92 93DO_ERROR(SIGTRAP, {}, "trap", trap); 94DO_ERROR(SIGSEGV, {}, "ibreak", ibreak); 95DO_ERROR(SIGSEGV, {}, "obreak", obreak); 96DO_EINFO(SIGSEGV, {}, "access error", access_error, SEGV_ACCERR); 97DO_EINFO(SIGSEGV, {}, "insn access error", insn_acc_error, SEGV_ACCERR); 98DO_EINFO(SIGSEGV, {}, "data access error", data_acc_error, SEGV_ACCERR); 99DO_EINFO(SIGILL, {}, "privileged opcode", priv_op, ILL_PRVOPC); 100DO_EINFO(SIGILL, {}, "invalid opcode", invalid_op, ILL_ILLOPC); 101DO_EINFO(SIGILL, {}, "invalid ex opcode", invalid_exop, ILL_ILLOPC); 102DO_EINFO(SIGBUS, {}, "invalid address", mem_error, BUS_ADRERR); 103DO_EINFO(SIGBUS, {}, "bus error", bus_error, BUS_ADRERR); 104DO_EINFO(SIGILL, {}, "FPU invalid opcode", fpu_invalid_op, ILL_COPROC); 105 106DO_ERROR(SIGTRAP, 107#ifndef CONFIG_MN10300_USING_JTAG 108 DCR &= ~0x0001, 109#else 110 {}, 111#endif 112 "single step", istep); 113 114/* 115 * handle NMI 116 */ 117asmlinkage void nmi(struct pt_regs *regs, enum exception_code code) 118{ 119 /* see if gdbstub wants to deal with it */ 120#ifdef CONFIG_GDBSTUB 121 if (gdbstub_intercept(regs, code)) 122 return; 123#endif 124 125 printk(KERN_WARNING "--- Register Dump ---\n"); 126 show_registers(regs); 127 printk(KERN_WARNING "---------------------\n"); 128} 129 130/* 131 * show a stack trace from the specified stack pointer 132 */ 133void show_trace(unsigned long *sp) 134{ 135 unsigned long *stack, addr, module_start, module_end; 136 int i; 137 138 printk(KERN_EMERG "\nCall Trace:"); 139 140 stack = sp; 141 i = 0; 142 module_start = VMALLOC_START; 143 module_end = VMALLOC_END; 144 145 while (((long) stack & (THREAD_SIZE - 1)) != 0) { 146 addr = *stack++; 147 if (__kernel_text_address(addr)) { 148 printk(" [<%08lx>]", addr); 149 print_symbol(" %s", addr); 150 printk("\n"); 151 } 152 } 153 154 printk("\n"); 155} 156 157/* 158 * show the raw stack from the specified stack pointer 159 */ 160void show_stack(struct task_struct *task, unsigned long *sp) 161{ 162 unsigned long *stack; 163 int i; 164 165 if (!sp) 166 sp = (unsigned long *) &sp; 167 168 stack = sp; 169 printk(KERN_EMERG "Stack:"); 170 for (i = 0; i < kstack_depth_to_print; i++) { 171 if (((long) stack & (THREAD_SIZE - 1)) == 0) 172 break; 173 if ((i % 8) == 0) 174 printk(KERN_EMERG " "); 175 printk("%08lx ", *stack++); 176 } 177 178 show_trace(sp); 179} 180 181/* 182 * the architecture-independent dump_stack generator 183 */ 184void dump_stack(void) 185{ 186 unsigned long stack; 187 188 show_stack(current, &stack); 189} 190EXPORT_SYMBOL(dump_stack); 191 192/* 193 * dump the register file in the specified exception frame 194 */ 195void show_registers_only(struct pt_regs *regs) 196{ 197 unsigned long ssp; 198 199 ssp = (unsigned long) regs + sizeof(*regs); 200 201 printk(KERN_EMERG "PC: %08lx EPSW: %08lx SSP: %08lx mode: %s\n", 202 regs->pc, regs->epsw, ssp, user_mode(regs) ? "User" : "Super"); 203 printk(KERN_EMERG "d0: %08lx d1: %08lx d2: %08lx d3: %08lx\n", 204 regs->d0, regs->d1, regs->d2, regs->d3); 205 printk(KERN_EMERG "a0: %08lx a1: %08lx a2: %08lx a3: %08lx\n", 206 regs->a0, regs->a1, regs->a2, regs->a3); 207 printk(KERN_EMERG "e0: %08lx e1: %08lx e2: %08lx e3: %08lx\n", 208 regs->e0, regs->e1, regs->e2, regs->e3); 209 printk(KERN_EMERG "e4: %08lx e5: %08lx e6: %08lx e7: %08lx\n", 210 regs->e4, regs->e5, regs->e6, regs->e7); 211 printk(KERN_EMERG "lar: %08lx lir: %08lx mdr: %08lx usp: %08lx\n", 212 regs->lar, regs->lir, regs->mdr, regs->sp); 213 printk(KERN_EMERG "cvf: %08lx crl: %08lx crh: %08lx drq: %08lx\n", 214 regs->mcvf, regs->mcrl, regs->mcrh, regs->mdrq); 215 printk(KERN_EMERG "threadinfo=%p task=%p)\n", 216 current_thread_info(), current); 217 218 if ((unsigned long) current >= 0x90000000UL && 219 (unsigned long) current < 0x94000000UL) 220 printk(KERN_EMERG "Process %s (pid: %d)\n", 221 current->comm, current->pid); 222 223 printk(KERN_EMERG "CPUP: %04hx\n", CPUP); 224 printk(KERN_EMERG "TBR: %08x\n", TBR); 225 printk(KERN_EMERG "DEAR: %08x\n", DEAR); 226 printk(KERN_EMERG "sISR: %08x\n", sISR); 227 printk(KERN_EMERG "NMICR: %04hx\n", NMICR); 228 printk(KERN_EMERG "BCBERR: %08x\n", BCBERR); 229 printk(KERN_EMERG "BCBEAR: %08x\n", BCBEAR); 230 printk(KERN_EMERG "MMUFCR: %08x\n", MMUFCR); 231 printk(KERN_EMERG "IPTEU : %08x IPTEL2: %08x\n", IPTEU, IPTEL2); 232 printk(KERN_EMERG "DPTEU: %08x DPTEL2: %08x\n", DPTEU, DPTEL2); 233} 234 235/* 236 * dump the registers and the stack 237 */ 238void show_registers(struct pt_regs *regs) 239{ 240 unsigned long sp; 241 int i; 242 243 show_registers_only(regs); 244 245 if (!user_mode(regs)) 246 sp = (unsigned long) regs + sizeof(*regs); 247 else 248 sp = regs->sp; 249 250 /* when in-kernel, we also print out the stack and code at the 251 * time of the fault.. 252 */ 253 if (!user_mode(regs)) { 254 printk(KERN_EMERG "\n"); 255 show_stack(current, (unsigned long *) sp); 256 257 i = 0; 258 } 259 260 printk("\n"); 261 return; 262 263} 264 265/* 266 * 267 */ 268void show_trace_task(struct task_struct *tsk) 269{ 270 unsigned long sp = tsk->thread.sp; 271 272 /* User space on another CPU? */ 273 if ((sp ^ (unsigned long) tsk) & (PAGE_MASK << 1)) 274 return; 275 276 show_trace((unsigned long *) sp); 277} 278 279/* 280 * note the untimely death of part of the kernel 281 */ 282void die(const char *str, struct pt_regs *regs, enum exception_code code) 283{ 284 console_verbose(); 285 spin_lock_irq(&die_lock); 286 printk(KERN_EMERG "\n%s: %04x\n", 287 str, code & 0xffff); 288 show_registers(regs); 289 290 if (regs->pc >= 0x02000000 && regs->pc < 0x04000000 && 291 (regs->epsw & (EPSW_IM | EPSW_IE)) != (EPSW_IM | EPSW_IE)) { 292 printk(KERN_EMERG "Exception in usermode interrupt handler\n"); 293 printk(KERN_EMERG "\nPlease connect to kernel debugger !!\n"); 294 asm volatile ("0: bra 0b"); 295 } 296 297 spin_unlock_irq(&die_lock); 298 do_exit(SIGSEGV); 299} 300 301/* 302 * see if there's a fixup handler we can force a jump to when an exception 303 * happens due to something kernel code did 304 */ 305int die_if_no_fixup(const char *str, struct pt_regs *regs, 306 enum exception_code code) 307{ 308 if (user_mode(regs)) 309 return 0; 310 311 peripheral_leds_display_exception(code); 312 313 switch (code) { 314 /* see if we can fixup the kernel accessing memory */ 315 case EXCEP_ITLBMISS: 316 case EXCEP_DTLBMISS: 317 case EXCEP_IAERROR: 318 case EXCEP_DAERROR: 319 case EXCEP_MEMERR: 320 case EXCEP_MISALIGN: 321 case EXCEP_BUSERROR: 322 case EXCEP_ILLDATACC: 323 case EXCEP_IOINSACC: 324 case EXCEP_PRIVINSACC: 325 case EXCEP_PRIVDATACC: 326 case EXCEP_DATINSACC: 327 if (fixup_exception(regs)) 328 return 1; 329 case EXCEP_UNIMPINS: 330 if (regs->pc && *(uint8_t *)regs->pc == 0xff) 331 if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0)) 332 return 1; 333 break; 334 default: 335 break; 336 } 337 338 /* see if gdbstub wants to deal with it */ 339#ifdef CONFIG_GDBSTUB 340 if (gdbstub_intercept(regs, code)) 341 return 1; 342#endif 343 344 if (notify_die(DIE_GPF, str, regs, code, 0, 0)) 345 return 1; 346 347 /* make the process die as the last resort */ 348 die(str, regs, code); 349} 350 351/* 352 * handle unsupported syscall instructions (syscall 1-15) 353 */ 354static asmlinkage void unsupported_syscall(struct pt_regs *regs, 355 enum exception_code code) 356{ 357 struct task_struct *tsk = current; 358 siginfo_t info; 359 360 /* catch a kernel BUG() */ 361 if (code == EXCEP_SYSCALL15 && !user_mode(regs)) { 362 if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_BUG) { 363#ifdef CONFIG_GDBSTUB 364 gdbstub_intercept(regs, code); 365#endif 366 } 367 } 368 369 regs->pc -= 2; /* syscall return addr is _after_ the instruction */ 370 371 die_if_no_fixup("An unsupported syscall insn was used by the kernel\n", 372 regs, code); 373 374 info.si_signo = SIGILL; 375 info.si_errno = ENOSYS; 376 info.si_code = ILL_ILLTRP; 377 info.si_addr = (void *) regs->pc; 378 force_sig_info(SIGILL, &info, tsk); 379} 380 381/* 382 * display the register file when the stack pointer gets clobbered 383 */ 384asmlinkage void do_double_fault(struct pt_regs *regs) 385{ 386 struct task_struct *tsk = current; 387 388 strcpy(tsk->comm, "emergency tsk"); 389 tsk->pid = 0; 390 console_verbose(); 391 printk(KERN_EMERG "--- double fault ---\n"); 392 show_registers(regs); 393} 394 395/* 396 * asynchronous bus error (external, usually I/O DMA) 397 */ 398asmlinkage void io_bus_error(u32 bcberr, u32 bcbear, struct pt_regs *regs) 399{ 400 console_verbose(); 401 402 printk(KERN_EMERG "Asynchronous I/O Bus Error\n"); 403 printk(KERN_EMERG "==========================\n"); 404 405 if (bcberr & BCBERR_BEME) 406 printk(KERN_EMERG "- Multiple recorded errors\n"); 407 408 printk(KERN_EMERG "- Faulting Buses:%s%s%s\n", 409 bcberr & BCBERR_BEMR_CI ? " CPU-Ins-Fetch" : "", 410 bcberr & BCBERR_BEMR_CD ? " CPU-Data" : "", 411 bcberr & BCBERR_BEMR_DMA ? " DMA" : ""); 412 413 printk(KERN_EMERG "- %s %s access made to %s at address %08x\n", 414 bcberr & BCBERR_BEBST ? "Burst" : "Single", 415 bcberr & BCBERR_BERW ? "Read" : "Write", 416 bcberr & BCBERR_BESB_MON ? "Monitor Space" : 417 bcberr & BCBERR_BESB_IO ? "Internal CPU I/O Space" : 418 bcberr & BCBERR_BESB_EX ? "External I/O Bus" : 419 bcberr & BCBERR_BESB_OPEX ? "External Memory Bus" : 420 "On Chip Memory", 421 bcbear 422 ); 423 424 printk(KERN_EMERG "- Detected by the %s\n", 425 bcberr&BCBERR_BESD ? "Bus Control Unit" : "Slave Bus"); 426 427#ifdef CONFIG_PCI 428#define BRIDGEREGB(X) (*(volatile __u8 *)(0xBE040000 + (X))) 429#define BRIDGEREGW(X) (*(volatile __u16 *)(0xBE040000 + (X))) 430#define BRIDGEREGL(X) (*(volatile __u32 *)(0xBE040000 + (X))) 431 432 printk(KERN_EMERG "- PCI Memory Paging Reg: %08x\n", 433 *(volatile __u32 *) (0xBFFFFFF4)); 434 printk(KERN_EMERG "- PCI Bridge Base Address 0: %08x\n", 435 BRIDGEREGL(PCI_BASE_ADDRESS_0)); 436 printk(KERN_EMERG "- PCI Bridge AMPCI Base Address: %08x\n", 437 BRIDGEREGL(0x48)); 438 printk(KERN_EMERG "- PCI Bridge Command: %04hx\n", 439 BRIDGEREGW(PCI_COMMAND)); 440 printk(KERN_EMERG "- PCI Bridge Status: %04hx\n", 441 BRIDGEREGW(PCI_STATUS)); 442 printk(KERN_EMERG "- PCI Bridge Int Status: %08hx\n", 443 BRIDGEREGL(0x4c)); 444#endif 445 446 printk(KERN_EMERG "\n"); 447 show_registers(regs); 448 449 panic("Halted due to asynchronous I/O Bus Error\n"); 450} 451 452/* 453 * handle an exception for which a handler has not yet been installed 454 */ 455asmlinkage void uninitialised_exception(struct pt_regs *regs, 456 enum exception_code code) 457{ 458 459 /* see if gdbstub wants to deal with it */ 460#ifdef CONFIG_GDBSTUB 461 if (gdbstub_intercept(regs, code)) 462 return; 463#endif 464 465 peripheral_leds_display_exception(code); 466 printk(KERN_EMERG "Uninitialised Exception 0x%04x\n", code & 0xFFFF); 467 show_registers(regs); 468 469 for (;;) 470 continue; 471} 472 473/* 474 * set an interrupt stub to jump to a handler 475 * ! NOTE: this does *not* flush the caches 476 */ 477void __init __set_intr_stub(enum exception_code code, void *handler) 478{ 479 unsigned long addr; 480 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code); 481 482 addr = (unsigned long) handler - (unsigned long) vector; 483 vector[0] = 0xdc; /* JMP handler */ 484 vector[1] = addr; 485 vector[2] = addr >> 8; 486 vector[3] = addr >> 16; 487 vector[4] = addr >> 24; 488 vector[5] = 0xcb; 489 vector[6] = 0xcb; 490 vector[7] = 0xcb; 491} 492 493/* 494 * set an interrupt stub to jump to a handler 495 */ 496void __init set_intr_stub(enum exception_code code, void *handler) 497{ 498 unsigned long addr; 499 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code); 500 501 addr = (unsigned long) handler - (unsigned long) vector; 502 vector[0] = 0xdc; /* JMP handler */ 503 vector[1] = addr; 504 vector[2] = addr >> 8; 505 vector[3] = addr >> 16; 506 vector[4] = addr >> 24; 507 vector[5] = 0xcb; 508 vector[6] = 0xcb; 509 vector[7] = 0xcb; 510 511 mn10300_dcache_flush_inv(); 512 mn10300_icache_inv(); 513} 514 515/* 516 * set an interrupt stub to invoke the JTAG unit and then jump to a handler 517 */ 518void __init set_jtag_stub(enum exception_code code, void *handler) 519{ 520 unsigned long addr; 521 u8 *vector = (u8 *)(CONFIG_INTERRUPT_VECTOR_BASE + code); 522 523 addr = (unsigned long) handler - ((unsigned long) vector + 1); 524 vector[0] = 0xff; /* PI to jump into JTAG debugger */ 525 vector[1] = 0xdc; /* jmp handler */ 526 vector[2] = addr; 527 vector[3] = addr >> 8; 528 vector[4] = addr >> 16; 529 vector[5] = addr >> 24; 530 vector[6] = 0xcb; 531 vector[7] = 0xcb; 532 533 mn10300_dcache_flush_inv(); 534 flush_icache_range((unsigned long) vector, (unsigned long) vector + 8); 535} 536 537/* 538 * initialise the exception table 539 */ 540void __init trap_init(void) 541{ 542 set_excp_vector(EXCEP_TRAP, trap); 543 set_excp_vector(EXCEP_ISTEP, istep); 544 set_excp_vector(EXCEP_IBREAK, ibreak); 545 set_excp_vector(EXCEP_OBREAK, obreak); 546 547 set_excp_vector(EXCEP_PRIVINS, priv_op); 548 set_excp_vector(EXCEP_UNIMPINS, invalid_op); 549 set_excp_vector(EXCEP_UNIMPEXINS, invalid_exop); 550 set_excp_vector(EXCEP_MEMERR, mem_error); 551 set_excp_vector(EXCEP_MISALIGN, misalignment); 552 set_excp_vector(EXCEP_BUSERROR, bus_error); 553 set_excp_vector(EXCEP_ILLINSACC, insn_acc_error); 554 set_excp_vector(EXCEP_ILLDATACC, data_acc_error); 555 set_excp_vector(EXCEP_IOINSACC, insn_acc_error); 556 set_excp_vector(EXCEP_PRIVINSACC, insn_acc_error); 557 set_excp_vector(EXCEP_PRIVDATACC, data_acc_error); 558 set_excp_vector(EXCEP_DATINSACC, insn_acc_error); 559 set_excp_vector(EXCEP_FPU_DISABLED, fpu_disabled); 560 set_excp_vector(EXCEP_FPU_UNIMPINS, fpu_invalid_op); 561 set_excp_vector(EXCEP_FPU_OPERATION, fpu_exception); 562 563 set_excp_vector(EXCEP_NMI, nmi); 564 565 set_excp_vector(EXCEP_SYSCALL1, unsupported_syscall); 566 set_excp_vector(EXCEP_SYSCALL2, unsupported_syscall); 567 set_excp_vector(EXCEP_SYSCALL3, unsupported_syscall); 568 set_excp_vector(EXCEP_SYSCALL4, unsupported_syscall); 569 set_excp_vector(EXCEP_SYSCALL5, unsupported_syscall); 570 set_excp_vector(EXCEP_SYSCALL6, unsupported_syscall); 571 set_excp_vector(EXCEP_SYSCALL7, unsupported_syscall); 572 set_excp_vector(EXCEP_SYSCALL8, unsupported_syscall); 573 set_excp_vector(EXCEP_SYSCALL9, unsupported_syscall); 574 set_excp_vector(EXCEP_SYSCALL10, unsupported_syscall); 575 set_excp_vector(EXCEP_SYSCALL11, unsupported_syscall); 576 set_excp_vector(EXCEP_SYSCALL12, unsupported_syscall); 577 set_excp_vector(EXCEP_SYSCALL13, unsupported_syscall); 578 set_excp_vector(EXCEP_SYSCALL14, unsupported_syscall); 579 set_excp_vector(EXCEP_SYSCALL15, unsupported_syscall); 580} 581 582/* 583 * determine if a program counter value is a valid bug address 584 */ 585int is_valid_bugaddr(unsigned long pc) 586{ 587 return pc >= PAGE_OFFSET; 588} 589