Skip to content
Snippets Groups Projects
Commit 66a4909a authored by Mike Frysinger's avatar Mike Frysinger
Browse files

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: default avatarMike Frysinger <vapier@gentoo.org>
parent 54841ab5
No related branches found
No related tags found
No related merge requests found
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
void board_reset(void) __attribute__((__weak__)); void board_reset(void) __attribute__((__weak__));
void bfin_reset_or_hang(void) __attribute__((__noreturn__)); void bfin_reset_or_hang(void) __attribute__((__noreturn__));
void bfin_dump(struct pt_regs *reg);
void bfin_panic(struct pt_regs *reg); void bfin_panic(struct pt_regs *reg);
void dump(struct pt_regs *regs); void dump(struct pt_regs *regs);
......
...@@ -29,14 +29,26 @@ ...@@ -29,14 +29,26 @@
#include <asm/deferred.h> #include <asm/deferred.h>
#include "cpu.h" #include "cpu.h"
#ifdef CONFIG_DEBUG_DUMP
# define ENABLE_DUMP 1
#else
# define ENABLE_DUMP 0
#endif
#define trace_buffer_save(x) \ #define trace_buffer_save(x) \
do { \ do { \
if (!ENABLE_DUMP) \
break; \
(x) = bfin_read_TBUFCTL(); \ (x) = bfin_read_TBUFCTL(); \
bfin_write_TBUFCTL((x) & ~TBUFEN); \ bfin_write_TBUFCTL((x) & ~TBUFEN); \
} while (0) } while (0)
#define trace_buffer_restore(x) \ #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 /* 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 * 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) ...@@ -82,8 +94,16 @@ int trap_c(struct pt_regs *regs, uint32_t level)
{ {
uint32_t ret = 0; uint32_t ret = 0;
uint32_t trapnr = (regs->seqstat & EXCAUSE); uint32_t trapnr = (regs->seqstat & EXCAUSE);
unsigned long tflags;
bool data = false; 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) { switch (trapnr) {
/* 0x26 - Data CPLB Miss */ /* 0x26 - Data CPLB Miss */
case VEC_CPLB_M: case VEC_CPLB_M:
...@@ -97,7 +117,7 @@ int trap_c(struct pt_regs *regs, uint32_t level) ...@@ -97,7 +117,7 @@ int trap_c(struct pt_regs *regs, uint32_t level)
*/ */
if (last_cplb_fault_retx != regs->retx) { if (last_cplb_fault_retx != regs->retx) {
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) ...@@ -110,7 +130,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
uint32_t new_cplb_addr = 0, new_cplb_data = 0; uint32_t new_cplb_addr = 0, new_cplb_data = 0;
static size_t last_evicted; static size_t last_evicted;
size_t i; size_t i;
unsigned long tflags;
#ifdef CONFIG_EXCEPTION_DEFER #ifdef CONFIG_EXCEPTION_DEFER
/* This should never happen */ /* This should never happen */
...@@ -118,13 +137,6 @@ int trap_c(struct pt_regs *regs, uint32_t level) ...@@ -118,13 +137,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
bfin_panic(regs); bfin_panic(regs);
#endif #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); 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) { for (i = 0; i < ARRAY_SIZE(bfin_memory_map); ++i) {
...@@ -180,7 +192,6 @@ int trap_c(struct pt_regs *regs, uint32_t level) ...@@ -180,7 +192,6 @@ int trap_c(struct pt_regs *regs, uint32_t level)
for (i = 0; i < 16; ++i) for (i = 0; i < 16; ++i)
debug("%2i 0x%p 0x%08X\n", i, *CPLB_ADDR++, *CPLB_DATA++); debug("%2i 0x%p 0x%08X\n", i, *CPLB_ADDR++, *CPLB_DATA++);
trace_buffer_restore(tflags);
break; break;
} }
#ifdef CONFIG_CMD_KGDB #ifdef CONFIG_CMD_KGDB
...@@ -208,23 +219,21 @@ int trap_c(struct pt_regs *regs, uint32_t level) ...@@ -208,23 +219,21 @@ int trap_c(struct pt_regs *regs, uint32_t level)
#ifdef CONFIG_CMD_KGDB #ifdef CONFIG_CMD_KGDB
if (level == 3) { if (level == 3) {
/* We need to handle this at EVT5, so try again */ /* We need to handle this at EVT5, so try again */
bfin_dump(regs);
ret = 1; ret = 1;
break; break;
} }
if (debugger_exception_handler && (*debugger_exception_handler)(regs)) if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return 0; break;
#endif #endif
bfin_panic(regs); bfin_panic(regs);
} }
trace_buffer_restore(tflags);
return ret; return ret;
} }
#ifdef CONFIG_DEBUG_DUMP
# define ENABLE_DUMP 1
#else
# define ENABLE_DUMP 0
#endif
#ifndef CONFIG_KALLSYMS #ifndef CONFIG_KALLSYMS
const char *symbol_lookup(unsigned long addr, unsigned long *caddr) const char *symbol_lookup(unsigned long addr, unsigned long *caddr)
{ {
...@@ -364,17 +373,14 @@ void dump(struct pt_regs *fp) ...@@ -364,17 +373,14 @@ void dump(struct pt_regs *fp)
printf("\n"); printf("\n");
} }
void dump_bfin_trace_buffer(void) static void _dump_bfin_trace_buffer(void)
{ {
char buf[150]; char buf[150];
unsigned long tflags;
int i = 0; int i = 0;
if (!ENABLE_DUMP) if (!ENABLE_DUMP)
return; return;
trace_buffer_save(tflags);
printf("Hardware Trace:\n"); printf("Hardware Trace:\n");
if (bfin_read_TBUFSTAT() & TBUFCNT) { if (bfin_read_TBUFSTAT() & TBUFCNT) {
...@@ -385,16 +391,21 @@ void dump_bfin_trace_buffer(void) ...@@ -385,16 +391,21 @@ void dump_bfin_trace_buffer(void)
printf(" Source : %s\n", buf); 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); trace_buffer_restore(tflags);
} }
void bfin_panic(struct pt_regs *regs) void bfin_dump(struct pt_regs *regs)
{ {
if (ENABLE_DUMP) { unsigned long tflags;
unsigned long tflags;
trace_buffer_save(tflags); trace_buffer_save(tflags);
}
puts( puts(
"\n" "\n"
...@@ -404,7 +415,16 @@ void bfin_panic(struct pt_regs *regs) ...@@ -404,7 +415,16 @@ void bfin_panic(struct pt_regs *regs)
"\n" "\n"
); );
dump(regs); dump(regs);
dump_bfin_trace_buffer(); _dump_bfin_trace_buffer();
puts("\n"); 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(); bfin_reset_or_hang();
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment