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