linux/arch/openrisc/kernel/traps.c
<<
>>
Prefs
   1/*
   2 * OpenRISC traps.c
   3 *
   4 * Linux architectural port borrowing liberally from similar works of
   5 * others.  All original copyrights apply as per the original source
   6 * declaration.
   7 *
   8 * Modifications for the OpenRISC architecture:
   9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
  10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
  11 *
  12 *      This program is free software; you can redistribute it and/or
  13 *      modify it under the terms of the GNU General Public License
  14 *      as published by the Free Software Foundation; either version
  15 *      2 of the License, or (at your option) any later version.
  16 *
  17 *  Here we handle the break vectors not used by the system call
  18 *  mechanism, as well as some general stack/register dumping
  19 *  things.
  20 *
  21 */
  22
  23#include <linux/init.h>
  24#include <linux/sched.h>
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/kmod.h>
  28#include <linux/string.h>
  29#include <linux/errno.h>
  30#include <linux/ptrace.h>
  31#include <linux/timer.h>
  32#include <linux/mm.h>
  33#include <linux/kallsyms.h>
  34#include <asm/uaccess.h>
  35
  36#include <asm/segment.h>
  37#include <asm/io.h>
  38#include <asm/pgtable.h>
  39
  40extern char _etext, _stext;
  41
  42int kstack_depth_to_print = 0x180;
  43
  44static inline int valid_stack_ptr(struct thread_info *tinfo, void *p)
  45{
  46        return p > (void *)tinfo && p < (void *)tinfo + THREAD_SIZE - 3;
  47}
  48
  49void show_trace(struct task_struct *task, unsigned long *stack)
  50{
  51        struct thread_info *context;
  52        unsigned long addr;
  53
  54        context = (struct thread_info *)
  55            ((unsigned long)stack & (~(THREAD_SIZE - 1)));
  56
  57        while (valid_stack_ptr(context, stack)) {
  58                addr = *stack++;
  59                if (__kernel_text_address(addr)) {
  60                        printk(" [<%08lx>]", addr);
  61                        print_symbol(" %s", addr);
  62                        printk("\n");
  63                }
  64        }
  65        printk(" =======================\n");
  66}
  67
  68/* displays a short stack trace */
  69void show_stack(struct task_struct *task, unsigned long *esp)
  70{
  71        unsigned long addr, *stack;
  72        int i;
  73
  74        if (esp == NULL)
  75                esp = (unsigned long *)&esp;
  76
  77        stack = esp;
  78
  79        printk("Stack dump [0x%08lx]:\n", (unsigned long)esp);
  80        for (i = 0; i < kstack_depth_to_print; i++) {
  81                if (kstack_end(stack))
  82                        break;
  83                if (__get_user(addr, stack)) {
  84                        /* This message matches "failing address" marked
  85                           s390 in ksymoops, so lines containing it will
  86                           not be filtered out by ksymoops.  */
  87                        printk("Failing address 0x%lx\n", (unsigned long)stack);
  88                        break;
  89                }
  90                stack++;
  91
  92                printk("sp + %02d: 0x%08lx\n", i * 4, addr);
  93        }
  94        printk("\n");
  95
  96        show_trace(task, esp);
  97
  98        return;
  99}
 100
 101void show_trace_task(struct task_struct *tsk)
 102{
 103        /*
 104         * TODO: SysRq-T trace dump...
 105         */
 106}
 107
 108void show_registers(struct pt_regs *regs)
 109{
 110        int i;
 111        int in_kernel = 1;
 112        unsigned long esp;
 113
 114        esp = (unsigned long)(&regs->sp);
 115        if (user_mode(regs))
 116                in_kernel = 0;
 117
 118        printk("CPU #: %d\n"
 119               "   PC: %08lx    SR: %08lx    SP: %08lx\n",
 120               smp_processor_id(), regs->pc, regs->sr, regs->sp);
 121        printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
 122               0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
 123        printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
 124               regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
 125        printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
 126               regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
 127        printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
 128               regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
 129        printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
 130               regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
 131        printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
 132               regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
 133        printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
 134               regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
 135        printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
 136               regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
 137        printk("  RES: %08lx oGPR11: %08lx\n",
 138               regs->gpr[11], regs->orig_gpr11);
 139
 140        printk("Process %s (pid: %d, stackpage=%08lx)\n",
 141               current->comm, current->pid, (unsigned long)current);
 142        /*
 143         * When in-kernel, we also print out the stack and code at the
 144         * time of the fault..
 145         */
 146        if (in_kernel) {
 147
 148                printk("\nStack: ");
 149                show_stack(NULL, (unsigned long *)esp);
 150
 151                printk("\nCode: ");
 152                if (regs->pc < PAGE_OFFSET)
 153                        goto bad;
 154
 155                for (i = -24; i < 24; i++) {
 156                        unsigned char c;
 157                        if (__get_user(c, &((unsigned char *)regs->pc)[i])) {
 158bad:
 159                                printk(" Bad PC value.");
 160                                break;
 161                        }
 162
 163                        if (i == 0)
 164                                printk("(%02x) ", c);
 165                        else
 166                                printk("%02x ", c);
 167                }
 168        }
 169        printk("\n");
 170}
 171
 172void nommu_dump_state(struct pt_regs *regs,
 173                      unsigned long ea, unsigned long vector)
 174{
 175        int i;
 176        unsigned long addr, stack = regs->sp;
 177
 178        printk("\n\r[nommu_dump_state] :: ea %lx, vector %lx\n\r", ea, vector);
 179
 180        printk("CPU #: %d\n"
 181               "   PC: %08lx    SR: %08lx    SP: %08lx\n",
 182               0, regs->pc, regs->sr, regs->sp);
 183        printk("GPR00: %08lx GPR01: %08lx GPR02: %08lx GPR03: %08lx\n",
 184               0L, regs->gpr[1], regs->gpr[2], regs->gpr[3]);
 185        printk("GPR04: %08lx GPR05: %08lx GPR06: %08lx GPR07: %08lx\n",
 186               regs->gpr[4], regs->gpr[5], regs->gpr[6], regs->gpr[7]);
 187        printk("GPR08: %08lx GPR09: %08lx GPR10: %08lx GPR11: %08lx\n",
 188               regs->gpr[8], regs->gpr[9], regs->gpr[10], regs->gpr[11]);
 189        printk("GPR12: %08lx GPR13: %08lx GPR14: %08lx GPR15: %08lx\n",
 190               regs->gpr[12], regs->gpr[13], regs->gpr[14], regs->gpr[15]);
 191        printk("GPR16: %08lx GPR17: %08lx GPR18: %08lx GPR19: %08lx\n",
 192               regs->gpr[16], regs->gpr[17], regs->gpr[18], regs->gpr[19]);
 193        printk("GPR20: %08lx GPR21: %08lx GPR22: %08lx GPR23: %08lx\n",
 194               regs->gpr[20], regs->gpr[21], regs->gpr[22], regs->gpr[23]);
 195        printk("GPR24: %08lx GPR25: %08lx GPR26: %08lx GPR27: %08lx\n",
 196               regs->gpr[24], regs->gpr[25], regs->gpr[26], regs->gpr[27]);
 197        printk("GPR28: %08lx GPR29: %08lx GPR30: %08lx GPR31: %08lx\n",
 198               regs->gpr[28], regs->gpr[29], regs->gpr[30], regs->gpr[31]);
 199        printk("  RES: %08lx oGPR11: %08lx\n",
 200               regs->gpr[11], regs->orig_gpr11);
 201
 202        printk("Process %s (pid: %d, stackpage=%08lx)\n",
 203               ((struct task_struct *)(__pa(current)))->comm,
 204               ((struct task_struct *)(__pa(current)))->pid,
 205               (unsigned long)current);
 206
 207        printk("\nStack: ");
 208        printk("Stack dump [0x%08lx]:\n", (unsigned long)stack);
 209        for (i = 0; i < kstack_depth_to_print; i++) {
 210                if (((long)stack & (THREAD_SIZE - 1)) == 0)
 211                        break;
 212                stack++;
 213
 214                printk("%lx :: sp + %02d: 0x%08lx\n", stack, i * 4,
 215                       *((unsigned long *)(__pa(stack))));
 216        }
 217        printk("\n");
 218
 219        printk("Call Trace:   ");
 220        i = 1;
 221        while (((long)stack & (THREAD_SIZE - 1)) != 0) {
 222                addr = *((unsigned long *)__pa(stack));
 223                stack++;
 224
 225                if (kernel_text_address(addr)) {
 226                        if (i && ((i % 6) == 0))
 227                                printk("\n ");
 228                        printk(" [<%08lx>]", addr);
 229                        i++;
 230                }
 231        }
 232        printk("\n");
 233
 234        printk("\nCode: ");
 235
 236        for (i = -24; i < 24; i++) {
 237                unsigned char c;
 238                c = ((unsigned char *)(__pa(regs->pc)))[i];
 239
 240                if (i == 0)
 241                        printk("(%02x) ", c);
 242                else
 243                        printk("%02x ", c);
 244        }
 245        printk("\n");
 246}
 247
 248/* This is normally the 'Oops' routine */
 249void die(const char *str, struct pt_regs *regs, long err)
 250{
 251
 252        console_verbose();
 253        printk("\n%s#: %04lx\n", str, err & 0xffff);
 254        show_registers(regs);
 255#ifdef CONFIG_JUMP_UPON_UNHANDLED_EXCEPTION
 256        printk("\n\nUNHANDLED_EXCEPTION: entering infinite loop\n");
 257
 258        /* shut down interrupts */
 259        local_irq_disable();
 260
 261        __asm__ __volatile__("l.nop   1");
 262        do {} while (1);
 263#endif
 264        do_exit(SIGSEGV);
 265}
 266
 267/* This is normally the 'Oops' routine */
 268void die_if_kernel(const char *str, struct pt_regs *regs, long err)
 269{
 270        if (user_mode(regs))
 271                return;
 272
 273        die(str, regs, err);
 274}
 275
 276void unhandled_exception(struct pt_regs *regs, int ea, int vector)
 277{
 278        printk("Unable to handle exception at EA =0x%x, vector 0x%x",
 279               ea, vector);
 280        die("Oops", regs, 9);
 281}
 282
 283void __init trap_init(void)
 284{
 285        /* Nothing needs to be done */
 286}
 287
 288asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
 289{
 290        siginfo_t info;
 291        memset(&info, 0, sizeof(info));
 292        info.si_signo = SIGTRAP;
 293        info.si_code = TRAP_TRACE;
 294        info.si_addr = (void *)address;
 295        force_sig_info(SIGTRAP, &info, current);
 296
 297        regs->pc += 4;
 298}
 299
 300asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
 301{
 302        siginfo_t info;
 303
 304        if (user_mode(regs)) {
 305                /* Send a SIGSEGV */
 306                info.si_signo = SIGSEGV;
 307                info.si_errno = 0;
 308                /* info.si_code has been set above */
 309                info.si_addr = (void *)address;
 310                force_sig_info(SIGSEGV, &info, current);
 311        } else {
 312                printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
 313                show_registers(regs);
 314                die("Die:", regs, address);
 315        }
 316
 317}
 318
 319asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)
 320{
 321        siginfo_t info;
 322
 323        if (user_mode(regs)) {
 324                /* Send a SIGBUS */
 325                info.si_signo = SIGBUS;
 326                info.si_errno = 0;
 327                info.si_code = BUS_ADRERR;
 328                info.si_addr = (void *)address;
 329                force_sig_info(SIGBUS, &info, current);
 330        } else {                /* Kernel mode */
 331                printk("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address);
 332                show_registers(regs);
 333                die("Die:", regs, address);
 334        }
 335}
 336
 337asmlinkage void do_illegal_instruction(struct pt_regs *regs,
 338                                       unsigned long address)
 339{
 340        siginfo_t info;
 341
 342        if (user_mode(regs)) {
 343                /* Send a SIGILL */
 344                info.si_signo = SIGILL;
 345                info.si_errno = 0;
 346                info.si_code = ILL_ILLOPC;
 347                info.si_addr = (void *)address;
 348                force_sig_info(SIGBUS, &info, current);
 349        } else {                /* Kernel mode */
 350                printk("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n",
 351                       address);
 352                show_registers(regs);
 353                die("Die:", regs, address);
 354        }
 355}
 356