aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/early_printk.c
diff options
context:
space:
mode:
authorRobin Getz <robin.getz@analog.com>2009-07-07 16:17:09 -0400
committerMike Frysinger <vapier@gentoo.org>2009-09-16 21:31:44 -0400
commit837ec2d56c41640d1f1238e52c350b2a516d29ba (patch)
tree1732468388385c411853c67cb2b288c2f8d17cc7 /arch/blackfin/kernel/early_printk.c
parent3f871feaf3390c6d6e578818f867917c2e4738a2 (diff)
Blackfin: catch hardware errors earlier during booting
Allow hardware errors to be caught during early portions of booting, and leave something in the shadow console that people can use to debug their system with (to be printed out by the bootloader on next reset). This enables the hardare error interrupts in head.S, allowing us to find hardware errors when they happen (well, as much as you can with a hardware error) and prints out the trace if it is enabled. This will catch errors (like booting the wrong image on a 533) which previously resulted in a infinite loop/hang, as well as random hardware errors before before setup_arch(). To disable this debug only feature - turn off EARLY_PRINTK. Signed-off-by: Robin Getz <robin.getz@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel/early_printk.c')
-rw-r--r--arch/blackfin/kernel/early_printk.c74
1 files changed, 70 insertions, 4 deletions
diff --git a/arch/blackfin/kernel/early_printk.c b/arch/blackfin/kernel/early_printk.c
index 2ab56811841c..931c78b5ea1f 100644
--- a/arch/blackfin/kernel/early_printk.c
+++ b/arch/blackfin/kernel/early_printk.c
@@ -27,6 +27,7 @@
27#include <linux/serial_core.h> 27#include <linux/serial_core.h>
28#include <linux/console.h> 28#include <linux/console.h>
29#include <linux/string.h> 29#include <linux/string.h>
30#include <linux/reboot.h>
30#include <asm/blackfin.h> 31#include <asm/blackfin.h>
31#include <asm/irq_handler.h> 32#include <asm/irq_handler.h>
32#include <asm/early_printk.h> 33#include <asm/early_printk.h>
@@ -181,6 +182,22 @@ asmlinkage void __init init_early_exception_vectors(void)
181 u32 evt; 182 u32 evt;
182 SSYNC(); 183 SSYNC();
183 184
185 /*
186 * This starts up the shadow buffer, incase anything crashes before
187 * setup arch
188 */
189 mark_shadow_error();
190 early_shadow_puts(linux_banner);
191 early_shadow_stamp();
192
193 if (CPUID != bfin_cpuid()) {
194 early_shadow_puts("Running on wrong machine type, expected");
195 early_shadow_reg(CPUID, 16);
196 early_shadow_puts(", but running on");
197 early_shadow_reg(bfin_cpuid(), 16);
198 early_shadow_puts("\n");
199 }
200
184 /* cannot program in software: 201 /* cannot program in software:
185 * evt0 - emulation (jtag) 202 * evt0 - emulation (jtag)
186 * evt1 - reset 203 * evt1 - reset
@@ -199,6 +216,7 @@ asmlinkage void __init init_early_exception_vectors(void)
199 216
200} 217}
201 218
219__attribute__((__noreturn__))
202asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr) 220asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
203{ 221{
204 /* This can happen before the uart is initialized, so initialize 222 /* This can happen before the uart is initialized, so initialize
@@ -210,10 +228,58 @@ asmlinkage void __init early_trap_c(struct pt_regs *fp, void *retaddr)
210 if (likely(early_console == NULL) && CPUID == bfin_cpuid()) 228 if (likely(early_console == NULL) && CPUID == bfin_cpuid())
211 setup_early_printk(DEFAULT_EARLY_PORT); 229 setup_early_printk(DEFAULT_EARLY_PORT);
212 230
213 printk(KERN_EMERG "Early panic\n"); 231 if (!shadow_console_enabled()) {
214 dump_bfin_mem(fp); 232 /* crap - we crashed before setup_arch() */
215 show_regs(fp); 233 early_shadow_puts("panic before setup_arch\n");
216 dump_bfin_trace_buffer(); 234 early_shadow_puts("IPEND:");
235 early_shadow_reg(fp->ipend, 16);
236 if (fp->seqstat & SEQSTAT_EXCAUSE) {
237 early_shadow_puts("\nEXCAUSE:");
238 early_shadow_reg(fp->seqstat & SEQSTAT_EXCAUSE, 8);
239 }
240 if (fp->seqstat & SEQSTAT_HWERRCAUSE) {
241 early_shadow_puts("\nHWERRCAUSE:");
242 early_shadow_reg(
243 (fp->seqstat & SEQSTAT_HWERRCAUSE) >> 14, 8);
244 }
245 early_shadow_puts("\nErr @");
246 if (fp->ipend & EVT_EVX)
247 early_shadow_reg(fp->retx, 32);
248 else
249 early_shadow_reg(fp->pc, 32);
250#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
251 early_shadow_puts("\nTrace:");
252 if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) {
253 while (bfin_read_TBUFSTAT() & TBUFCNT) {
254 early_shadow_puts("\nT :");
255 early_shadow_reg(bfin_read_TBUF(), 32);
256 early_shadow_puts("\n S :");
257 early_shadow_reg(bfin_read_TBUF(), 32);
258 }
259 }
260#endif
261 early_shadow_puts("\nUse bfin-elf-addr2line to determine "
262 "function names\n");
263 /*
264 * We should panic(), but we can't - since panic calls printk,
265 * and printk uses memcpy.
266 * we want to reboot, but if the machine type is different,
267 * can't due to machine specific reboot sequences
268 */
269 if (CPUID == bfin_cpuid()) {
270 early_shadow_puts("Trying to restart\n");
271 machine_restart("");
272 }
273
274 early_shadow_puts("Halting, since it is not safe to restart\n");
275 while (1)
276 asm volatile ("EMUEXCPT; IDLE;\n");
277
278 } else {
279 printk(KERN_EMERG "Early panic\n");
280 show_regs(fp);
281 dump_bfin_trace_buffer();
282 }
217 283
218 panic("Died early"); 284 panic("Died early");
219} 285}