summaryrefslogtreecommitdiff
path: root/arch/blackfin/cpu
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2010-04-29 00:31:36 -0400
committerMike Frysinger <vapier@gentoo.org>2010-07-05 04:18:18 -0400
commit66a4909a3d4d684f7a102f4d4d2ba8ae8c66d786 (patch)
tree1a585944dd5c648748d82b5883f90552a2493ae8 /arch/blackfin/cpu
parent54841ab50c20d6fa6c9cc3eb826989da3a22d934 (diff)
Blackfin: clean up trace buffer handling when crashing
Avoid banging on the trace MMRs when debugging is disabled, avoid calling the funcs multiple times in a row, disable the trace buffer earlier in the exception handler to avoid eating more user entries, and dump the buffer before calling the kgdb hook. This way we maximize useful debugging info up front rather than needing external tools (like gdb/serial/etc...). Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/cpu')
-rw-r--r--arch/blackfin/cpu/cpu.h1
-rw-r--r--arch/blackfin/cpu/traps.c76
2 files changed, 49 insertions, 28 deletions
diff --git a/arch/blackfin/cpu/cpu.h b/arch/blackfin/cpu/cpu.h
index 0a13c285e0..c8bec115a1 100644
--- a/arch/blackfin/cpu/cpu.h
+++ b/arch/blackfin/cpu/cpu.h
@@ -29,6 +29,7 @@
void board_reset(void) __attribute__((__weak__));
void bfin_reset_or_hang(void) __attribute__((__noreturn__));
+void bfin_dump(struct pt_regs *reg);
void bfin_panic(struct pt_regs *reg);
void dump(struct pt_regs *regs);
diff --git a/arch/blackfin/cpu/traps.c b/arch/blackfin/cpu/traps.c
index caaea94106..09388aa3d5 100644
--- a/arch/blackfin/cpu/traps.c
+++ b/arch/blackfin/cpu/traps.c
@@ -29,14 +29,26 @@
#include <asm/deferred.h>
#include "cpu.h"
+#ifdef CONFIG_DEBUG_DUMP
+# define ENABLE_DUMP 1
+#else
+# define ENABLE_DUMP 0
+#endif
+
#define trace_buffer_save(x) \
do { \
+ if (!ENABLE_DUMP) \
+ break; \
(x) = bfin_read_TBUFCTL(); \
bfin_write_TBUFCTL((x) & ~TBUFEN); \
} while (0)
#define trace_buffer_restore(x) \
- bfin_write_TBUFCTL((x))
+ do { \
+ if (!ENABLE_DUMP) \
+ break; \
+ bfin_write_TBUFCTL((x)); \
+ } while (0);
/* The purpose of this map is to provide a mapping of address<->cplb settings
* rather than an exact map of what is actually addressable on the part. This
@@ -82,8 +94,16 @@ int trap_c(struct pt_regs *regs, uint32_t level)
{
uint32_t ret = 0;
uint32_t trapnr = (regs->seqstat & EXCAUSE);
+ unsigned long tflags;
bool data = false;
+ /*
+ * Keep the trace buffer so that a miss here points people
+ * to the right place (their code). Crashes here rarely
+ * happen. If they do, only the Blackfin maintainer cares.
+ */
+ trace_buffer_save(tflags);
+
switch (trapnr) {
/* 0x26 - Data CPLB Miss */
case VEC_CPLB_M:
@@ -97,7 +117,7 @@ int trap_c(struct pt_regs *regs, uint32_t level)
*/
if (last_cplb_fault_retx != regs->retx) {
last_cplb_fault_retx = regs->retx;
- return ret;
+ break;
}
}
@@ -110,7 +130,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
uint32_t new_cplb_addr = 0, new_cplb_data = 0;
static size_t last_evicted;
size_t i;
- unsigned long tflags;
#ifdef CONFIG_EXCEPTION_DEFER
/* This should never happen */
@@ -118,13 +137,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
bfin_panic(regs);
#endif
- /*
- * Keep the trace buffer so that a miss here points people
- * to the right place (their code). Crashes here rarely
- * happen. If they do, only the Blackfin maintainer cares.
- */
- trace_buffer_save(tflags);
-
new_cplb_addr = (data ? bfin_read_DCPLB_FAULT_ADDR() : bfin_read_ICPLB_FAULT_ADDR()) & ~(4 * 1024 * 1024 - 1);
for (i = 0; i < ARRAY_SIZE(bfin_memory_map); ++i) {
@@ -180,7 +192,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
for (i = 0; i < 16; ++i)
debug("%2i 0x%p 0x%08X\n", i, *CPLB_ADDR++, *CPLB_DATA++);
- trace_buffer_restore(tflags);
break;
}
#ifdef CONFIG_CMD_KGDB
@@ -208,23 +219,21 @@ int trap_c(struct pt_regs *regs, uint32_t level)
#ifdef CONFIG_CMD_KGDB
if (level == 3) {
/* We need to handle this at EVT5, so try again */
+ bfin_dump(regs);
ret = 1;
break;
}
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
- return 0;
+ break;
#endif
bfin_panic(regs);
}
+
+ trace_buffer_restore(tflags);
+
return ret;
}
-#ifdef CONFIG_DEBUG_DUMP
-# define ENABLE_DUMP 1
-#else
-# define ENABLE_DUMP 0
-#endif
-
#ifndef CONFIG_KALLSYMS
const char *symbol_lookup(unsigned long addr, unsigned long *caddr)
{
@@ -364,17 +373,14 @@ void dump(struct pt_regs *fp)
printf("\n");
}
-void dump_bfin_trace_buffer(void)
+static void _dump_bfin_trace_buffer(void)
{
char buf[150];
- unsigned long tflags;
int i = 0;
if (!ENABLE_DUMP)
return;
- trace_buffer_save(tflags);
-
printf("Hardware Trace:\n");
if (bfin_read_TBUFSTAT() & TBUFCNT) {
@@ -385,16 +391,21 @@ void dump_bfin_trace_buffer(void)
printf(" Source : %s\n", buf);
}
}
+}
+void dump_bfin_trace_buffer(void)
+{
+ unsigned long tflags;
+ trace_buffer_save(tflags);
+ _dump_bfin_trace_buffer();
trace_buffer_restore(tflags);
}
-void bfin_panic(struct pt_regs *regs)
+void bfin_dump(struct pt_regs *regs)
{
- if (ENABLE_DUMP) {
- unsigned long tflags;
- trace_buffer_save(tflags);
- }
+ unsigned long tflags;
+
+ trace_buffer_save(tflags);
puts(
"\n"
@@ -404,7 +415,16 @@ void bfin_panic(struct pt_regs *regs)
"\n"
);
dump(regs);
- dump_bfin_trace_buffer();
+ _dump_bfin_trace_buffer();
puts("\n");
+
+ trace_buffer_restore(tflags);
+}
+
+void bfin_panic(struct pt_regs *regs)
+{
+ unsigned long tflags;
+ trace_buffer_save(tflags);
+ bfin_dump(regs);
bfin_reset_or_hang();
}