X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=arch%2Fblackfin%2Fcpu%2Ftraps.c;h=20aeab81a20418cce2c00de9fdfb202b43e516b4;hb=99310d144852a8f0b7dbb3d9c7b575c37781b2c1;hp=caaea94106a556d2095a85847967743a3eabfd19;hpb=c6fb83d21729321426308c3acff2a3dfb20d250b;p=u-boot diff --git a/arch/blackfin/cpu/traps.c b/arch/blackfin/cpu/traps.c index caaea94106..20aeab81a2 100644 --- a/arch/blackfin/cpu/traps.c +++ b/arch/blackfin/cpu/traps.c @@ -29,14 +29,26 @@ #include #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) { @@ -138,7 +150,10 @@ int trap_c(struct pt_regs *regs, uint32_t level) (data ? 'D' : 'I'), (void *)new_cplb_addr); bfin_panic(regs); } else - debug("CPLB addr %p matches map 0x%p - 0x%p\n", new_cplb_addr, bfin_memory_map[i].start, bfin_memory_map[i].end); + debug("CPLB addr %p matches map 0x%p - 0x%p\n", + (void *)new_cplb_addr, + (void *)bfin_memory_map[i].start, + (void *)bfin_memory_map[i].end); new_cplb_data = (data ? bfin_memory_map[i].data_flags : bfin_memory_map[i].inst_flags); if (data) { @@ -151,16 +166,17 @@ int trap_c(struct pt_regs *regs, uint32_t level) /* find the next unlocked entry and evict it */ i = last_evicted & 0xF; - debug("last evicted = %i\n", i); + debug("last evicted = %zu\n", i); CPLB_DATA = CPLB_DATA_BASE + i; while (*CPLB_DATA & CPLB_LOCK) { - debug("skipping %i %p - %08X\n", i, CPLB_DATA, *CPLB_DATA); + debug("skipping %zu %p - %08X\n", i, CPLB_DATA, *CPLB_DATA); i = (i + 1) & 0xF; /* wrap around */ CPLB_DATA = CPLB_DATA_BASE + i; } CPLB_ADDR = CPLB_ADDR_BASE + i; - debug("evicting entry %i: 0x%p 0x%08X\n", i, *CPLB_ADDR, *CPLB_DATA); + debug("evicting entry %zu: 0x%p 0x%08X\n", i, + (void *)*CPLB_ADDR, *CPLB_DATA); last_evicted = i + 1; /* need to turn off cplbs whenever we muck with the cplb table */ @@ -178,9 +194,9 @@ int trap_c(struct pt_regs *regs, uint32_t level) CPLB_ADDR = CPLB_ADDR_BASE; CPLB_DATA = CPLB_DATA_BASE; for (i = 0; i < 16; ++i) - debug("%2i 0x%p 0x%08X\n", i, *CPLB_ADDR++, *CPLB_DATA++); + debug("%2zu 0x%p 0x%08X\n", i, + (void *)*CPLB_ADDR++, *CPLB_DATA++); - trace_buffer_restore(tflags); break; } #ifdef CONFIG_CMD_KGDB @@ -208,23 +224,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 +378,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 +396,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 +420,16 @@ void bfin_panic(struct pt_regs *regs) "\n" ); dump(regs); - dump_bfin_trace_buffer(); + _dump_bfin_trace_buffer(); puts("\n"); - bfin_reset_or_hang(); + + trace_buffer_restore(tflags); +} + +void bfin_panic(struct pt_regs *regs) +{ + unsigned long tflags; + trace_buffer_save(tflags); + bfin_dump(regs); + panic("PANIC: Blackfin internal error"); }