|
@@ -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();
|
|
|
}
|