linux/arch/cris/kernel/traps.c
<<
>>
Prefs
   1/*
   2 *  linux/arch/cris/traps.c
   3 *
   4 *  Here we handle the break vectors not used by the system call
   5 *  mechanism, as well as some general stack/register dumping
   6 *  things.
   7 *
   8 *  Copyright (C) 2000-2007 Axis Communications AB
   9 *
  10 *  Authors:   Bjorn Wesen
  11 *             Hans-Peter Nilsson
  12 *
  13 */
  14
  15#include <linux/init.h>
  16#include <linux/module.h>
  17
  18#include <asm/pgtable.h>
  19#include <asm/uaccess.h>
  20
  21extern void arch_enable_nmi(void);
  22extern void stop_watchdog(void);
  23extern void reset_watchdog(void);
  24extern void show_registers(struct pt_regs *regs);
  25
  26#ifdef CONFIG_DEBUG_BUGVERBOSE
  27extern void handle_BUG(struct pt_regs *regs);
  28#else
  29#define handle_BUG(regs)
  30#endif
  31
  32static int kstack_depth_to_print = 24;
  33
  34void (*nmi_handler)(struct pt_regs *);
  35
  36void
  37show_trace(unsigned long *stack)
  38{
  39        unsigned long addr, module_start, module_end;
  40        extern char _stext, _etext;
  41        int i;
  42
  43        printk("\nCall Trace: ");
  44
  45        i = 1;
  46        module_start = VMALLOC_START;
  47        module_end = VMALLOC_END;
  48
  49        while (((long)stack & (THREAD_SIZE-1)) != 0) {
  50                if (__get_user(addr, stack)) {
  51                        /* This message matches "failing address" marked
  52                           s390 in ksymoops, so lines containing it will
  53                           not be filtered out by ksymoops.  */
  54                        printk("Failing address 0x%lx\n", (unsigned long)stack);
  55                        break;
  56                }
  57                stack++;
  58
  59                /*
  60                 * If the address is either in the text segment of the
  61                 * kernel, or in the region which contains vmalloc'ed
  62                 * memory, it *may* be the address of a calling
  63                 * routine; if so, print it so that someone tracing
  64                 * down the cause of the crash will be able to figure
  65                 * out the call path that was taken.
  66                 */
  67                if (((addr >= (unsigned long)&_stext) &&
  68                     (addr <= (unsigned long)&_etext)) ||
  69                    ((addr >= module_start) && (addr <= module_end))) {
  70                        if (i && ((i % 8) == 0))
  71                                printk("\n       ");
  72                        printk("[<%08lx>] ", addr);
  73                        i++;
  74                }
  75        }
  76}
  77
  78/*
  79 * These constants are for searching for possible module text
  80 * segments. MODULE_RANGE is a guess of how much space is likely
  81 * to be vmalloced.
  82 */
  83
  84#define MODULE_RANGE (8*1024*1024)
  85
  86/*
  87 * The output (format, strings and order) is adjusted to be usable with
  88 * ksymoops-2.4.1 with some necessary CRIS-specific patches.  Please don't
  89 * change it unless you're serious about adjusting ksymoops and syncing
  90 * with the ksymoops maintainer.
  91 */
  92
  93void
  94show_stack(struct task_struct *task, unsigned long *sp)
  95{
  96        unsigned long *stack, addr;
  97        int i;
  98
  99        /*
 100         * debugging aid: "show_stack(NULL);" prints a
 101         * back trace.
 102         */
 103
 104        if (sp == NULL) {
 105                if (task)
 106                        sp = (unsigned long*)task->thread.ksp;
 107                else
 108                        sp = (unsigned long*)rdsp();
 109        }
 110
 111        stack = sp;
 112
 113        printk("\nStack from %08lx:\n       ", (unsigned long)stack);
 114        for (i = 0; i < kstack_depth_to_print; i++) {
 115                if (((long)stack & (THREAD_SIZE-1)) == 0)
 116                        break;
 117                if (i && ((i % 8) == 0))
 118                        printk("\n       ");
 119                if (__get_user(addr, stack)) {
 120                        /* This message matches "failing address" marked
 121                           s390 in ksymoops, so lines containing it will
 122                           not be filtered out by ksymoops.  */
 123                        printk("Failing address 0x%lx\n", (unsigned long)stack);
 124                        break;
 125                }
 126                stack++;
 127                printk("%08lx ", addr);
 128        }
 129        show_trace(sp);
 130}
 131
 132#if 0
 133/* displays a short stack trace */
 134
 135int
 136show_stack(void)
 137{
 138        unsigned long *sp = (unsigned long *)rdusp();
 139        int i;
 140
 141        printk("Stack dump [0x%08lx]:\n", (unsigned long)sp);
 142        for (i = 0; i < 16; i++)
 143                printk("sp + %d: 0x%08lx\n", i*4, sp[i]);
 144        return 0;
 145}
 146#endif
 147
 148void
 149dump_stack(void)
 150{
 151        show_stack(NULL, NULL);
 152}
 153EXPORT_SYMBOL(dump_stack);
 154
 155void
 156set_nmi_handler(void (*handler)(struct pt_regs *))
 157{
 158        nmi_handler = handler;
 159        arch_enable_nmi();
 160}
 161
 162#ifdef CONFIG_DEBUG_NMI_OOPS
 163void
 164oops_nmi_handler(struct pt_regs *regs)
 165{
 166        stop_watchdog();
 167        oops_in_progress = 1;
 168        printk("NMI!\n");
 169        show_registers(regs);
 170        oops_in_progress = 0;
 171}
 172
 173static int __init
 174oops_nmi_register(void)
 175{
 176        set_nmi_handler(oops_nmi_handler);
 177        return 0;
 178}
 179
 180__initcall(oops_nmi_register);
 181
 182#endif
 183
 184/*
 185 * This gets called from entry.S when the watchdog has bitten. Show something
 186 * similiar to an Oops dump, and if the kernel is configured to be a nice
 187 * doggy, then halt instead of reboot.
 188 */
 189void
 190watchdog_bite_hook(struct pt_regs *regs)
 191{
 192#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
 193        local_irq_disable();
 194        stop_watchdog();
 195        show_registers(regs);
 196
 197        while (1)
 198                ; /* Do nothing. */
 199#else
 200        show_registers(regs);
 201#endif
 202}
 203
 204/* This is normally the Oops function. */
 205void
 206die_if_kernel(const char *str, struct pt_regs *regs, long err)
 207{
 208        if (user_mode(regs))
 209                return;
 210
 211#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
 212        /*
 213         * This printout might take too long and could trigger
 214         * the watchdog normally. If NICE_DOGGY is set, simply
 215         * stop the watchdog during the printout.
 216         */
 217        stop_watchdog();
 218#endif
 219
 220        handle_BUG(regs);
 221
 222        printk("%s: %04lx\n", str, err & 0xffff);
 223
 224        show_registers(regs);
 225
 226        oops_in_progress = 0;
 227
 228#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
 229        reset_watchdog();
 230#endif
 231        do_exit(SIGSEGV);
 232}
 233
 234void __init
 235trap_init(void)
 236{
 237        /* Nothing needs to be done */
 238}
 239