1/* 2 * Port on Texas Instruments TMS320C6x architecture 3 * 4 * Copyright (C) 2004, 2006, 2009, 2010, 2011 Texas Instruments Incorporated 5 * Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 */ 11#include <linux/module.h> 12#include <linux/ptrace.h> 13#include <linux/kallsyms.h> 14#include <linux/bug.h> 15 16#include <asm/soc.h> 17#include <asm/special_insns.h> 18#include <asm/traps.h> 19 20int (*c6x_nmi_handler)(struct pt_regs *regs); 21 22void __init trap_init(void) 23{ 24 ack_exception(EXCEPT_TYPE_NXF); 25 ack_exception(EXCEPT_TYPE_EXC); 26 ack_exception(EXCEPT_TYPE_IXF); 27 ack_exception(EXCEPT_TYPE_SXF); 28 enable_exception(); 29} 30 31void show_regs(struct pt_regs *regs) 32{ 33 pr_err("\n"); 34 show_regs_print_info(KERN_ERR); 35 pr_err("PC: %08lx SP: %08lx\n", regs->pc, regs->sp); 36 pr_err("Status: %08lx ORIG_A4: %08lx\n", regs->csr, regs->orig_a4); 37 pr_err("A0: %08lx B0: %08lx\n", regs->a0, regs->b0); 38 pr_err("A1: %08lx B1: %08lx\n", regs->a1, regs->b1); 39 pr_err("A2: %08lx B2: %08lx\n", regs->a2, regs->b2); 40 pr_err("A3: %08lx B3: %08lx\n", regs->a3, regs->b3); 41 pr_err("A4: %08lx B4: %08lx\n", regs->a4, regs->b4); 42 pr_err("A5: %08lx B5: %08lx\n", regs->a5, regs->b5); 43 pr_err("A6: %08lx B6: %08lx\n", regs->a6, regs->b6); 44 pr_err("A7: %08lx B7: %08lx\n", regs->a7, regs->b7); 45 pr_err("A8: %08lx B8: %08lx\n", regs->a8, regs->b8); 46 pr_err("A9: %08lx B9: %08lx\n", regs->a9, regs->b9); 47 pr_err("A10: %08lx B10: %08lx\n", regs->a10, regs->b10); 48 pr_err("A11: %08lx B11: %08lx\n", regs->a11, regs->b11); 49 pr_err("A12: %08lx B12: %08lx\n", regs->a12, regs->b12); 50 pr_err("A13: %08lx B13: %08lx\n", regs->a13, regs->b13); 51 pr_err("A14: %08lx B14: %08lx\n", regs->a14, regs->dp); 52 pr_err("A15: %08lx B15: %08lx\n", regs->a15, regs->sp); 53 pr_err("A16: %08lx B16: %08lx\n", regs->a16, regs->b16); 54 pr_err("A17: %08lx B17: %08lx\n", regs->a17, regs->b17); 55 pr_err("A18: %08lx B18: %08lx\n", regs->a18, regs->b18); 56 pr_err("A19: %08lx B19: %08lx\n", regs->a19, regs->b19); 57 pr_err("A20: %08lx B20: %08lx\n", regs->a20, regs->b20); 58 pr_err("A21: %08lx B21: %08lx\n", regs->a21, regs->b21); 59 pr_err("A22: %08lx B22: %08lx\n", regs->a22, regs->b22); 60 pr_err("A23: %08lx B23: %08lx\n", regs->a23, regs->b23); 61 pr_err("A24: %08lx B24: %08lx\n", regs->a24, regs->b24); 62 pr_err("A25: %08lx B25: %08lx\n", regs->a25, regs->b25); 63 pr_err("A26: %08lx B26: %08lx\n", regs->a26, regs->b26); 64 pr_err("A27: %08lx B27: %08lx\n", regs->a27, regs->b27); 65 pr_err("A28: %08lx B28: %08lx\n", regs->a28, regs->b28); 66 pr_err("A29: %08lx B29: %08lx\n", regs->a29, regs->b29); 67 pr_err("A30: %08lx B30: %08lx\n", regs->a30, regs->b30); 68 pr_err("A31: %08lx B31: %08lx\n", regs->a31, regs->b31); 69} 70 71void die(char *str, struct pt_regs *fp, int nr) 72{ 73 console_verbose(); 74 pr_err("%s: %08x\n", str, nr); 75 show_regs(fp); 76 77 pr_err("Process %s (pid: %d, stackpage=%08lx)\n", 78 current->comm, current->pid, (PAGE_SIZE + 79 (unsigned long) current)); 80 81 dump_stack(); 82 while (1) 83 ; 84} 85 86static void die_if_kernel(char *str, struct pt_regs *fp, int nr) 87{ 88 if (user_mode(fp)) 89 return; 90 91 die(str, fp, nr); 92} 93 94 95/* Internal exceptions */ 96static struct exception_info iexcept_table[10] = { 97 { "Oops - instruction fetch", SIGBUS, BUS_ADRERR }, 98 { "Oops - fetch packet", SIGBUS, BUS_ADRERR }, 99 { "Oops - execute packet", SIGILL, ILL_ILLOPC }, 100 { "Oops - undefined instruction", SIGILL, ILL_ILLOPC }, 101 { "Oops - resource conflict", SIGILL, ILL_ILLOPC }, 102 { "Oops - resource access", SIGILL, ILL_PRVREG }, 103 { "Oops - privilege", SIGILL, ILL_PRVOPC }, 104 { "Oops - loops buffer", SIGILL, ILL_ILLOPC }, 105 { "Oops - software exception", SIGILL, ILL_ILLTRP }, 106 { "Oops - unknown exception", SIGILL, ILL_ILLOPC } 107}; 108 109/* External exceptions */ 110static struct exception_info eexcept_table[128] = { 111 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 112 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 113 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 114 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 115 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 116 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 117 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 118 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 119 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 120 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 121 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 122 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 123 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 124 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 125 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 126 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 127 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 128 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 129 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 130 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 131 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 132 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 133 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 134 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 135 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 136 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 137 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 138 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 139 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 140 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 141 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 142 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 143 144 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 145 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 146 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 147 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 148 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 149 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 150 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 151 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 152 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 153 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 154 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 155 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 156 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 157 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 158 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 159 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 160 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 161 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 162 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 163 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 164 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 165 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 166 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 167 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 168 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 169 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 170 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 171 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 172 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 173 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 174 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 175 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 176 177 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 178 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 179 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 180 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 181 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 182 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 183 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 184 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 185 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 186 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 187 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 188 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 189 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 190 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 191 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 192 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 193 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 194 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 195 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 196 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 197 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 198 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 199 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 200 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 201 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 202 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 203 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 204 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 205 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 206 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 207 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 208 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 209 210 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 211 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 212 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 213 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 214 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 215 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 216 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 217 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 218 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 219 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 220 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 221 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 222 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 223 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 224 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 225 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 226 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 227 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 228 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 229 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 230 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 231 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 232 { "Oops - external exception", SIGBUS, BUS_ADRERR }, 233 { "Oops - CPU memory protection fault", SIGSEGV, SEGV_ACCERR }, 234 { "Oops - CPU memory protection fault in L1P", SIGSEGV, SEGV_ACCERR }, 235 { "Oops - DMA memory protection fault in L1P", SIGSEGV, SEGV_ACCERR }, 236 { "Oops - CPU memory protection fault in L1D", SIGSEGV, SEGV_ACCERR }, 237 { "Oops - DMA memory protection fault in L1D", SIGSEGV, SEGV_ACCERR }, 238 { "Oops - CPU memory protection fault in L2", SIGSEGV, SEGV_ACCERR }, 239 { "Oops - DMA memory protection fault in L2", SIGSEGV, SEGV_ACCERR }, 240 { "Oops - EMC CPU memory protection fault", SIGSEGV, SEGV_ACCERR }, 241 { "Oops - EMC bus error", SIGBUS, BUS_ADRERR } 242}; 243 244static void do_trap(struct exception_info *except_info, struct pt_regs *regs) 245{ 246 unsigned long addr = instruction_pointer(regs); 247 siginfo_t info; 248 249 if (except_info->code != TRAP_BRKPT) 250 pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n", 251 except_info->kernel_str, regs->pc, 252 except_info->signo, except_info->code); 253 254 die_if_kernel(except_info->kernel_str, regs, addr); 255 256 info.si_signo = except_info->signo; 257 info.si_errno = 0; 258 info.si_code = except_info->code; 259 info.si_addr = (void __user *)addr; 260 261 force_sig_info(except_info->signo, &info, current); 262} 263 264/* 265 * Process an internal exception (non maskable) 266 */ 267static int process_iexcept(struct pt_regs *regs) 268{ 269 unsigned int iexcept_report = get_iexcept(); 270 unsigned int iexcept_num; 271 272 ack_exception(EXCEPT_TYPE_IXF); 273 274 pr_err("IEXCEPT: PC[0x%lx]\n", regs->pc); 275 276 while (iexcept_report) { 277 iexcept_num = __ffs(iexcept_report); 278 iexcept_report &= ~(1 << iexcept_num); 279 set_iexcept(iexcept_report); 280 if (*(unsigned int *)regs->pc == BKPT_OPCODE) { 281 /* This is a breakpoint */ 282 struct exception_info bkpt_exception = { 283 "Oops - undefined instruction", 284 SIGTRAP, TRAP_BRKPT 285 }; 286 do_trap(&bkpt_exception, regs); 287 iexcept_report &= ~(0xFF); 288 set_iexcept(iexcept_report); 289 continue; 290 } 291 292 do_trap(&iexcept_table[iexcept_num], regs); 293 } 294 return 0; 295} 296 297/* 298 * Process an external exception (maskable) 299 */ 300static void process_eexcept(struct pt_regs *regs) 301{ 302 int evt; 303 304 pr_err("EEXCEPT: PC[0x%lx]\n", regs->pc); 305 306 while ((evt = soc_get_exception()) >= 0) 307 do_trap(&eexcept_table[evt], regs); 308 309 ack_exception(EXCEPT_TYPE_EXC); 310} 311 312/* 313 * Main exception processing 314 */ 315asmlinkage int process_exception(struct pt_regs *regs) 316{ 317 unsigned int type; 318 unsigned int type_num; 319 unsigned int ie_num = 9; /* default is unknown exception */ 320 321 while ((type = get_except_type()) != 0) { 322 type_num = fls(type) - 1; 323 324 switch (type_num) { 325 case EXCEPT_TYPE_NXF: 326 ack_exception(EXCEPT_TYPE_NXF); 327 if (c6x_nmi_handler) 328 (c6x_nmi_handler)(regs); 329 else 330 pr_alert("NMI interrupt!\n"); 331 break; 332 333 case EXCEPT_TYPE_IXF: 334 if (process_iexcept(regs)) 335 return 1; 336 break; 337 338 case EXCEPT_TYPE_EXC: 339 process_eexcept(regs); 340 break; 341 342 case EXCEPT_TYPE_SXF: 343 ie_num = 8; 344 default: 345 ack_exception(type_num); 346 do_trap(&iexcept_table[ie_num], regs); 347 break; 348 } 349 } 350 return 0; 351} 352 353static int kstack_depth_to_print = 48; 354 355static void show_trace(unsigned long *stack, unsigned long *endstack) 356{ 357 unsigned long addr; 358 int i; 359 360 pr_debug("Call trace:"); 361 i = 0; 362 while (stack + 1 <= endstack) { 363 addr = *stack++; 364 /* 365 * If the address is either in the text segment of the 366 * kernel, or in the region which contains vmalloc'ed 367 * memory, it *may* be the address of a calling 368 * routine; if so, print it so that someone tracing 369 * down the cause of the crash will be able to figure 370 * out the call path that was taken. 371 */ 372 if (__kernel_text_address(addr)) { 373#ifndef CONFIG_KALLSYMS 374 if (i % 5 == 0) 375 pr_debug("\n "); 376#endif 377 pr_debug(" [<%08lx>]", addr); 378 print_symbol(" %s\n", addr); 379 i++; 380 } 381 } 382 pr_debug("\n"); 383} 384 385void show_stack(struct task_struct *task, unsigned long *stack) 386{ 387 unsigned long *p, *endstack; 388 int i; 389 390 if (!stack) { 391 if (task && task != current) 392 /* We know this is a kernel stack, 393 so this is the start/end */ 394 stack = (unsigned long *)thread_saved_ksp(task); 395 else 396 stack = (unsigned long *)&stack; 397 } 398 endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) 399 & -THREAD_SIZE); 400 401 pr_debug("Stack from %08lx:", (unsigned long)stack); 402 for (i = 0, p = stack; i < kstack_depth_to_print; i++) { 403 if (p + 1 > endstack) 404 break; 405 if (i % 8 == 0) 406 pr_cont("\n "); 407 pr_cont(" %08lx", *p++); 408 } 409 pr_cont("\n"); 410 show_trace(stack, endstack); 411} 412 413int is_valid_bugaddr(unsigned long addr) 414{ 415 return __kernel_text_address(addr); 416} 417