diff options
author | Mike Frysinger <vapier@gentoo.org> | 2010-04-29 00:31:36 -0400 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2010-07-05 04:18:18 -0400 |
commit | 66a4909a3d4d684f7a102f4d4d2ba8ae8c66d786 (patch) | |
tree | 1a585944dd5c648748d82b5883f90552a2493ae8 /arch/blackfin/cpu | |
parent | 54841ab50c20d6fa6c9cc3eb826989da3a22d934 (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.h | 1 | ||||
-rw-r--r-- | arch/blackfin/cpu/traps.c | 76 |
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(); } |