aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/cris/kernel/traps.c')
-rw-r--r--arch/cris/kernel/traps.c226
1 files changed, 139 insertions, 87 deletions
diff --git a/arch/cris/kernel/traps.c b/arch/cris/kernel/traps.c
index 520d92205fed..541efbf09371 100644
--- a/arch/cris/kernel/traps.c
+++ b/arch/cris/kernel/traps.c
@@ -1,66 +1,78 @@
1/* $Id: traps.c,v 1.11 2005/01/24 16:03:19 orjanf Exp $ 1/*
2 *
3 * linux/arch/cris/traps.c 2 * linux/arch/cris/traps.c
4 * 3 *
5 * Here we handle the break vectors not used by the system call 4 * Here we handle the break vectors not used by the system call
6 * mechanism, as well as some general stack/register dumping 5 * mechanism, as well as some general stack/register dumping
7 * things. 6 * things.
8 * 7 *
9 * Copyright (C) 2000-2002 Axis Communications AB 8 * Copyright (C) 2000-2007 Axis Communications AB
10 * 9 *
11 * Authors: Bjorn Wesen 10 * Authors: Bjorn Wesen
12 * Hans-Peter Nilsson 11 * Hans-Peter Nilsson
13 * 12 *
14 */ 13 */
15 14
16#include <linux/init.h> 15#include <linux/init.h>
17#include <linux/module.h> 16#include <linux/module.h>
17
18#include <asm/pgtable.h> 18#include <asm/pgtable.h>
19#include <asm/uaccess.h> 19#include <asm/uaccess.h>
20 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
21static int kstack_depth_to_print = 24; 32static int kstack_depth_to_print = 24;
22 33
23extern int raw_printk(const char *fmt, ...); 34void (*nmi_handler)(struct pt_regs *);
24 35
25void show_trace(unsigned long * stack) 36void
37show_trace(unsigned long *stack)
26{ 38{
27 unsigned long addr, module_start, module_end; 39 unsigned long addr, module_start, module_end;
28 extern char _stext, _etext; 40 extern char _stext, _etext;
29 int i; 41 int i;
30 42
31 raw_printk("\nCall Trace: "); 43 printk("\nCall Trace: ");
32 44
33 i = 1; 45 i = 1;
34 module_start = VMALLOC_START; 46 module_start = VMALLOC_START;
35 module_end = VMALLOC_END; 47 module_end = VMALLOC_END;
36 48
37 while (((long) stack & (THREAD_SIZE-1)) != 0) { 49 while (((long)stack & (THREAD_SIZE-1)) != 0) {
38 if (__get_user (addr, stack)) { 50 if (__get_user(addr, stack)) {
39 /* This message matches "failing address" marked 51 /* This message matches "failing address" marked
40 s390 in ksymoops, so lines containing it will 52 s390 in ksymoops, so lines containing it will
41 not be filtered out by ksymoops. */ 53 not be filtered out by ksymoops. */
42 raw_printk ("Failing address 0x%lx\n", (unsigned long)stack); 54 printk("Failing address 0x%lx\n", (unsigned long)stack);
43 break; 55 break;
44 } 56 }
45 stack++; 57 stack++;
46 58
47 /* 59 /*
48 * If the address is either in the text segment of the 60 * If the address is either in the text segment of the
49 * kernel, or in the region which contains vmalloc'ed 61 * kernel, or in the region which contains vmalloc'ed
50 * memory, it *may* be the address of a calling 62 * memory, it *may* be the address of a calling
51 * routine; if so, print it so that someone tracing 63 * routine; if so, print it so that someone tracing
52 * down the cause of the crash will be able to figure 64 * down the cause of the crash will be able to figure
53 * out the call path that was taken. 65 * out the call path that was taken.
54 */ 66 */
55 if (((addr >= (unsigned long) &_stext) && 67 if (((addr >= (unsigned long)&_stext) &&
56 (addr <= (unsigned long) &_etext)) || 68 (addr <= (unsigned long)&_etext)) ||
57 ((addr >= module_start) && (addr <= module_end))) { 69 ((addr >= module_start) && (addr <= module_end))) {
58 if (i && ((i % 8) == 0)) 70 if (i && ((i % 8) == 0))
59 raw_printk("\n "); 71 printk("\n ");
60 raw_printk("[<%08lx>] ", addr); 72 printk("[<%08lx>] ", addr);
61 i++; 73 i++;
62 } 74 }
63 } 75 }
64} 76}
65 77
66/* 78/*
@@ -78,109 +90,149 @@ void show_trace(unsigned long * stack)
78 * with the ksymoops maintainer. 90 * with the ksymoops maintainer.
79 */ 91 */
80 92
81void 93void
82show_stack(struct task_struct *task, unsigned long *sp) 94show_stack(struct task_struct *task, unsigned long *sp)
83{ 95{
84 unsigned long *stack, addr; 96 unsigned long *stack, addr;
85 int i; 97 int i;
86 98
87 /* 99 /*
88 * debugging aid: "show_stack(NULL);" prints a 100 * debugging aid: "show_stack(NULL);" prints a
89 * back trace. 101 * back trace.
90 */ 102 */
91 103
92 if(sp == NULL) { 104 if (sp == NULL) {
93 if (task) 105 if (task)
94 sp = (unsigned long*)task->thread.ksp; 106 sp = (unsigned long*)task->thread.ksp;
95 else 107 else
96 sp = (unsigned long*)rdsp(); 108 sp = (unsigned long*)rdsp();
97 } 109 }
98 110
99 stack = sp; 111 stack = sp;
100 112
101 raw_printk("\nStack from %08lx:\n ", (unsigned long)stack); 113 printk("\nStack from %08lx:\n ", (unsigned long)stack);
102 for(i = 0; i < kstack_depth_to_print; i++) { 114 for (i = 0; i < kstack_depth_to_print; i++) {
103 if (((long) stack & (THREAD_SIZE-1)) == 0) 115 if (((long)stack & (THREAD_SIZE-1)) == 0)
104 break; 116 break;
105 if (i && ((i % 8) == 0)) 117 if (i && ((i % 8) == 0))
106 raw_printk("\n "); 118 printk("\n ");
107 if (__get_user (addr, stack)) { 119 if (__get_user(addr, stack)) {
108 /* This message matches "failing address" marked 120 /* This message matches "failing address" marked
109 s390 in ksymoops, so lines containing it will 121 s390 in ksymoops, so lines containing it will
110 not be filtered out by ksymoops. */ 122 not be filtered out by ksymoops. */
111 raw_printk ("Failing address 0x%lx\n", (unsigned long)stack); 123 printk("Failing address 0x%lx\n", (unsigned long)stack);
112 break; 124 break;
113 } 125 }
114 stack++; 126 stack++;
115 raw_printk("%08lx ", addr); 127 printk("%08lx ", addr);
116 } 128 }
117 show_trace(sp); 129 show_trace(sp);
118} 130}
119 131
120static void (*nmi_handler)(struct pt_regs*); 132#if 0
121extern void arch_enable_nmi(void); 133/* displays a short stack trace */
122 134
123void set_nmi_handler(void (*handler)(struct pt_regs*)) 135int
136show_stack(void)
124{ 137{
125 nmi_handler = handler; 138 unsigned long *sp = (unsigned long *)rdusp();
126 arch_enable_nmi(); 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;
127} 145}
146#endif
128 147
129void handle_nmi(struct pt_regs* regs) 148void
149dump_stack(void)
130{ 150{
131 if (nmi_handler) 151 show_stack(NULL, NULL);
132 nmi_handler(regs); 152}
153EXPORT_SYMBOL(dump_stack);
154
155void
156set_nmi_handler(void (*handler)(struct pt_regs *))
157{
158 nmi_handler = handler;
159 arch_enable_nmi();
133} 160}
134 161
135#ifdef CONFIG_DEBUG_NMI_OOPS 162#ifdef CONFIG_DEBUG_NMI_OOPS
136void oops_nmi_handler(struct pt_regs* regs) 163void
164oops_nmi_handler(struct pt_regs *regs)
137{ 165{
138 stop_watchdog(); 166 stop_watchdog();
139 raw_printk("NMI!\n"); 167 oops_in_progress = 1;
140 show_registers(regs); 168 printk("NMI!\n");
169 show_registers(regs);
170 oops_in_progress = 0;
141} 171}
142 172
143static int 173static int __init
144__init oops_nmi_register(void) 174oops_nmi_register(void)
145{ 175{
146 set_nmi_handler(oops_nmi_handler); 176 set_nmi_handler(oops_nmi_handler);
147 return 0; 177 return 0;
148} 178}
149 179
150__initcall(oops_nmi_register); 180__initcall(oops_nmi_register);
151 181
152#endif 182#endif
153 183
154#if 0 184/*
155/* displays a short stack trace */ 185 * This gets called from entry.S when the watchdog has bitten. Show something
156 186 * similiar to an Oops dump, and if the kernel is configured to be a nice
157int 187 * doggy, then halt instead of reboot.
158show_stack() 188 */
189void
190watchdog_bite_hook(struct pt_regs *regs)
159{ 191{
160 unsigned long *sp = (unsigned long *)rdusp(); 192#ifdef CONFIG_ETRAX_WATCHDOG_NICE_DOGGY
161 int i; 193 local_irq_disable();
162 raw_printk("Stack dump [0x%08lx]:\n", (unsigned long)sp); 194 stop_watchdog();
163 for(i = 0; i < 16; i++) 195 show_registers(regs);
164 raw_printk("sp + %d: 0x%08lx\n", i*4, sp[i]); 196
165 return 0; 197 while (1)
166} 198 ; /* Do nothing. */
199#else
200 show_registers(regs);
167#endif 201#endif
202}
168 203
169void dump_stack(void) 204/* This is normally the Oops function. */
205void
206die_if_kernel(const char *str, struct pt_regs *regs, long err)
170{ 207{
171 show_stack(NULL, NULL); 208 if (user_mode(regs))
172} 209 return;
173 210
174EXPORT_SYMBOL(dump_stack); 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
175 219
176void __init 220 handle_BUG(regs);
177trap_init(void) 221
178{ 222 printk("%s: %04lx\n", str, err & 0xffff);
179 /* Nothing needs to be done */ 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);
180} 232}
181 233
182void spinning_cpu(void* addr) 234void __init
235trap_init(void)
183{ 236{
184 raw_printk("CPU %d spinning on %X\n", smp_processor_id(), addr); 237 /* Nothing needs to be done */
185 dump_stack();
186} 238}