root/arch/openrisc/kernel/traps.c

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

DEFINITIONS

This source file includes following definitions.
  1. print_trace
  2. show_stack
  3. show_trace_task
  4. show_registers
  5. nommu_dump_state
  6. die
  7. die_if_kernel
  8. unhandled_exception
  9. trap_init
  10. do_trap
  11. do_unaligned_access
  12. do_bus_fault
  13. in_delay_slot
  14. adjust_pc
  15. simulate_lwa
  16. simulate_swa
  17. do_illegal_instruction

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * OpenRISC traps.c
   4  *
   5  * Linux architectural port borrowing liberally from similar works of
   6  * others.  All original copyrights apply as per the original source
   7  * declaration.
   8  *
   9  * Modifications for the OpenRISC architecture:
  10  * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
  11  * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
  12  *
  13  *  Here we handle the break vectors not used by the system call
  14  *  mechanism, as well as some general stack/register dumping
  15  *  things.
  16  */
  17 
  18 #include <linux/init.h>
  19 #include <linux/sched.h>
  20 #include <linux/sched/debug.h>
  21 #include <linux/sched/task_stack.h>
  22 #include <linux/kernel.h>
  23 #include <linux/extable.h>
  24 #include <linux/kmod.h>
  25 #include <linux/string.h>
  26 #include <linux/errno.h>
  27 #include <linux/ptrace.h>
  28 #include <linux/timer.h>
  29 #include <linux/mm.h>
  30 #include <linux/kallsyms.h>
  31 #include <linux/uaccess.h>
  32 
  33 #include <asm/io.h>
  34 #include <asm/pgtable.h>
  35 #include <asm/unwinder.h>
  36 #include <asm/sections.h>
  37 
  38 int kstack_depth_to_print = 0x180;
  39 int lwa_flag;
  40 unsigned long __user *lwa_addr;
  41 
  42 void print_trace(void *data, unsigned long addr, int reliable)
  43 {
  44         pr_emerg("[<%p>] %s%pS\n", (void *) addr, reliable ? "" : "? ",
  45                (void *) addr);
  46 }
  47 
  48 /* displays a short stack trace */
  49 void show_stack(struct task_struct *task, unsigned long *esp)
  50 {
  51         if (esp == NULL)
  52                 esp = (unsigned long *)&esp;
  53 
  54         pr_emerg("Call trace:\n");
  55         unwind_stack(NULL, esp, print_trace);
  56 }
  57 
  58 void show_trace_task(struct task_struct *tsk)
  59 {
  60         /*
  61          * TODO: SysRq-T trace dump...
  62          */
  63 }
  64 
  65 void show_registers(struct pt_regs *regs)
  66 {
  67         int i;
  68         int in_kernel = 1;
  69         unsigned long esp;
  70 
  71         esp = (unsigned long)(regs->sp);
  72         if (user_mode(regs))
  73                 in_kernel = 0;
  74 
  75         printk("CPU #: %d\n"
  76                "   PC: %08lx    SR: %08lx    SP: %08lx\n",
  77                smp_processor_id(), regs->pc, regs->sr, regs->sp);
  78         printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
  79                0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
  80         printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
  81                regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
  82         printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
  83                regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
  84         printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
  85                regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
  86         printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
  87                regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
  88         printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
  89                regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
  90         printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
  91                regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
  92         printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
  93                regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
  94         printk("  RES: %08lx oGPR11: %08lx\n",
  95                regs->gpr[11], regs->orig_gpr11);
  96 
  97         printk("Process %s (pid: %d, stackpage=%08lx)\n",
  98                current->comm, current->pid, (unsigned long)current);
  99         /*
 100          * When in-kernel, we also print out the stack and code at the
 101          * time of the fault..
 102          */
 103         if (in_kernel) {
 104 
 105                 printk("\nStack: ");
 106                 show_stack(NULL, (unsigned long *)esp);
 107 
 108                 printk("\nCode: ");
 109                 if (regs->pc < PAGE_OFFSET)
 110                         goto bad;
 111 
 112                 for (i = -24; i < 24; i++) {
 113                         unsigned char c;
 114                         if (__get_user(c, &((unsigned char *)regs->pc)[i])) {
 115 bad:
 116                                 printk(" Bad PC value.");
 117                                 break;
 118                         }
 119 
 120                         if (i == 0)
 121                                 printk("(%02x) ", c);
 122                         else
 123                                 printk("%02x ", c);
 124                 }
 125         }
 126         printk("\n");
 127 }
 128 
 129 void nommu_dump_state(struct pt_regs *regs,
 130                       unsigned long ea, unsigned long vector)
 131 {
 132         int i;
 133         unsigned long addr, stack = regs->sp;
 134 
 135         printk("\n\r[nommu_dump_state] :: ea %lx, vector %lx\n\r", ea, vector);
 136 
 137         printk("CPU #: %d\n"
 138                "   PC: %08lx    SR: %08lx    SP: %08lx\n",
 139                0, regs->pc, regs->sr, regs->sp);
 140         printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
 141                0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
 142         printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
 143                regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
 144         printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
 145                regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
 146         printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
 147                regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
 148         printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
 149                regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
 150         printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
 151                regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
 152         printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
 153                regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
 154         printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
 155                regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
 156         printk("  RES: %08lx oGPR11: %08lx\n",
 157                regs->gpr[11], regs->orig_gpr11);
 158 
 159         printk("Process %s (pid: %d, stackpage=%08lx)\n",
 160                ((struct task_struct *)(__pa(current)))->comm,
 161                ((struct task_struct *)(__pa(current)))->pid,
 162                (unsigned long)current);
 163 
 164         printk("\nStack: ");
 165         printk("Stack dump [0x%08lx]:\n", (unsigned long)stack);
 166         for (i = 0; i < kstack_depth_to_print; i++) {
 167                 if (((long)stack & (THREAD_SIZE - 1)) == 0)
 168                         break;
 169                 stack++;
 170 
 171                 printk("%lx :: sp + %02d: 0x%08lx\n", stack, i * 4,
 172                        *((unsigned long *)(__pa(stack))));
 173         }
 174         printk("\n");
 175 
 176         printk("Call Trace:   ");
 177         i = 1;
 178         while (((long)stack & (THREAD_SIZE - 1)) != 0) {
 179                 addr = *((unsigned long *)__pa(stack));
 180                 stack++;
 181 
 182                 if (kernel_text_address(addr)) {
 183                         if (i && ((i % 6) == 0))
 184                                 printk("\n ");
 185                         printk(" [<%08lx>]", addr);
 186                         i++;
 187                 }
 188         }
 189         printk("\n");
 190 
 191         printk("\nCode: ");
 192 
 193         for (i = -24; i < 24; i++) {
 194                 unsigned char c;
 195                 c = ((unsigned char *)(__pa(regs->pc)))[i];
 196 
 197                 if (i == 0)
 198                         printk("(%02x) ", c);
 199                 else
 200                         printk("%02x ", c);
 201         }
 202         printk("\n");
 203 }
 204 
 205 /* This is normally the 'Oops' routine */
 206 void die(const char *str, struct pt_regs *regs, long err)
 207 {
 208 
 209         console_verbose();
 210         printk("\n%s#: %04lx\n", str, err & 0xffff);
 211         show_registers(regs);
 212 #ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
 213         printk("\n\nUNHANDLED_EXCEPTION: entering infinite loop\n");
 214 
 215         /* shut down interrupts */
 216         local_irq_disable();
 217 
 218         __asm__ __volatile__("l.nop   1");
 219         do {} while (1);
 220 #endif
 221         do_exit(SIGSEGV);
 222 }
 223 
 224 /* This is normally the 'Oops' routine */
 225 void die_if_kernel(const char *str, struct pt_regs *regs, long err)
 226 {
 227         if (user_mode(regs))
 228                 return;
 229 
 230         die(str, regs, err);
 231 }
 232 
 233 void unhandled_exception(struct pt_regs *regs, int ea, int vector)
 234 {
 235         printk("Unable to handle exception at EA =0x%x, vector 0x%x",
 236                ea, vector);
 237         die("Oops", regs, 9);
 238 }
 239 
 240 void __init trap_init(void)
 241 {
 242         /* Nothing needs to be done */
 243 }
 244 
 245 asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
 246 {
 247         force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)address);
 248 
 249         regs->pc += 4;
 250 }
 251 
 252 asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
 253 {
 254         if (user_mode(regs)) {
 255                 /* Send a SIGBUS */
 256                 force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)address);
 257         } else {
 258                 printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
 259                 show_registers(regs);
 260                 die("Die:", regs, address);
 261         }
 262 
 263 }
 264 
 265 asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)
 266 {
 267         if (user_mode(regs)) {
 268                 /* Send a SIGBUS */
 269                 force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address);
 270         } else {                /* Kernel mode */
 271                 printk("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address);
 272                 show_registers(regs);
 273                 die("Die:", regs, address);
 274         }
 275 }
 276 
 277 static inline int in_delay_slot(struct pt_regs *regs)
 278 {
 279 #ifdef CONFIG_OPENRISC_NO_SPR_SR_DSX
 280         /* No delay slot flag, do the old way */
 281         unsigned int op, insn;
 282 
 283         insn = *((unsigned int *)regs->pc);
 284         op = insn >> 26;
 285         switch (op) {
 286         case 0x00: /* l.j */
 287         case 0x01: /* l.jal */
 288         case 0x03: /* l.bnf */
 289         case 0x04: /* l.bf */
 290         case 0x11: /* l.jr */
 291         case 0x12: /* l.jalr */
 292                 return 1;
 293         default:
 294                 return 0;
 295         }
 296 #else
 297         return mfspr(SPR_SR) & SPR_SR_DSX;
 298 #endif
 299 }
 300 
 301 static inline void adjust_pc(struct pt_regs *regs, unsigned long address)
 302 {
 303         int displacement;
 304         unsigned int rb, op, jmp;
 305 
 306         if (unlikely(in_delay_slot(regs))) {
 307                 /* In delay slot, instruction at pc is a branch, simulate it */
 308                 jmp = *((unsigned int *)regs->pc);
 309 
 310                 displacement = sign_extend32(((jmp) & 0x3ffffff) << 2, 27);
 311                 rb = (jmp & 0x0000ffff) >> 11;
 312                 op = jmp >> 26;
 313 
 314                 switch (op) {
 315                 case 0x00: /* l.j */
 316                         regs->pc += displacement;
 317                         return;
 318                 case 0x01: /* l.jal */
 319                         regs->pc += displacement;
 320                         regs->gpr[9] = regs->pc + 8;
 321                         return;
 322                 case 0x03: /* l.bnf */
 323                         if (regs->sr & SPR_SR_F)
 324                                 regs->pc += 8;
 325                         else
 326                                 regs->pc += displacement;
 327                         return;
 328                 case 0x04: /* l.bf */
 329                         if (regs->sr & SPR_SR_F)
 330                                 regs->pc += displacement;
 331                         else
 332                                 regs->pc += 8;
 333                         return;
 334                 case 0x11: /* l.jr */
 335                         regs->pc = regs->gpr[rb];
 336                         return;
 337                 case 0x12: /* l.jalr */
 338                         regs->pc = regs->gpr[rb];
 339                         regs->gpr[9] = regs->pc + 8;
 340                         return;
 341                 default:
 342                         break;
 343                 }
 344         } else {
 345                 regs->pc += 4;
 346         }
 347 }
 348 
 349 static inline void simulate_lwa(struct pt_regs *regs, unsigned long address,
 350                                 unsigned int insn)
 351 {
 352         unsigned int ra, rd;
 353         unsigned long value;
 354         unsigned long orig_pc;
 355         long imm;
 356 
 357         const struct exception_table_entry *entry;
 358 
 359         orig_pc = regs->pc;
 360         adjust_pc(regs, address);
 361 
 362         ra = (insn >> 16) & 0x1f;
 363         rd = (insn >> 21) & 0x1f;
 364         imm = (short)insn;
 365         lwa_addr = (unsigned long __user *)(regs->gpr[ra] + imm);
 366 
 367         if ((unsigned long)lwa_addr & 0x3) {
 368                 do_unaligned_access(regs, address);
 369                 return;
 370         }
 371 
 372         if (get_user(value, lwa_addr)) {
 373                 if (user_mode(regs)) {
 374                         force_sig(SIGSEGV);
 375                         return;
 376                 }
 377 
 378                 if ((entry = search_exception_tables(orig_pc))) {
 379                         regs->pc = entry->fixup;
 380                         return;
 381                 }
 382 
 383                 /* kernel access in kernel space, load it directly */
 384                 value = *((unsigned long *)lwa_addr);
 385         }
 386 
 387         lwa_flag = 1;
 388         regs->gpr[rd] = value;
 389 }
 390 
 391 static inline void simulate_swa(struct pt_regs *regs, unsigned long address,
 392                                 unsigned int insn)
 393 {
 394         unsigned long __user *vaddr;
 395         unsigned long orig_pc;
 396         unsigned int ra, rb;
 397         long imm;
 398 
 399         const struct exception_table_entry *entry;
 400 
 401         orig_pc = regs->pc;
 402         adjust_pc(regs, address);
 403 
 404         ra = (insn >> 16) & 0x1f;
 405         rb = (insn >> 11) & 0x1f;
 406         imm = (short)(((insn & 0x2200000) >> 10) | (insn & 0x7ff));
 407         vaddr = (unsigned long __user *)(regs->gpr[ra] + imm);
 408 
 409         if (!lwa_flag || vaddr != lwa_addr) {
 410                 regs->sr &= ~SPR_SR_F;
 411                 return;
 412         }
 413 
 414         if ((unsigned long)vaddr & 0x3) {
 415                 do_unaligned_access(regs, address);
 416                 return;
 417         }
 418 
 419         if (put_user(regs->gpr[rb], vaddr)) {
 420                 if (user_mode(regs)) {
 421                         force_sig(SIGSEGV);
 422                         return;
 423                 }
 424 
 425                 if ((entry = search_exception_tables(orig_pc))) {
 426                         regs->pc = entry->fixup;
 427                         return;
 428                 }
 429 
 430                 /* kernel access in kernel space, store it directly */
 431                 *((unsigned long *)vaddr) = regs->gpr[rb];
 432         }
 433 
 434         lwa_flag = 0;
 435         regs->sr |= SPR_SR_F;
 436 }
 437 
 438 #define INSN_LWA        0x1b
 439 #define INSN_SWA        0x33
 440 
 441 asmlinkage void do_illegal_instruction(struct pt_regs *regs,
 442                                        unsigned long address)
 443 {
 444         unsigned int op;
 445         unsigned int insn = *((unsigned int *)address);
 446 
 447         op = insn >> 26;
 448 
 449         switch (op) {
 450         case INSN_LWA:
 451                 simulate_lwa(regs, address, insn);
 452                 return;
 453 
 454         case INSN_SWA:
 455                 simulate_swa(regs, address, insn);
 456                 return;
 457 
 458         default:
 459                 break;
 460         }
 461 
 462         if (user_mode(regs)) {
 463                 /* Send a SIGILL */
 464                 force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)address);
 465         } else {                /* Kernel mode */
 466                 printk("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n",
 467                        address);
 468                 show_registers(regs);
 469                 die("Die:", regs, address);
 470         }
 471 }

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