root/arch/c6x/kernel/traps.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. trap_init
  2. show_regs
  3. die
  4. die_if_kernel
  5. do_trap
  6. process_iexcept
  7. process_eexcept
  8. process_exception
  9. show_trace
  10. show_stack
  11. is_valid_bugaddr

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

/* [<][>][^][v][top][bottom][index][help] */