diff options
author | Robin Getz <robin.getz@analog.com> | 2007-07-25 11:03:28 +0800 |
---|---|---|
committer | Bryan Wu <bryan.wu@analog.com> | 2007-07-25 11:03:28 +0800 |
commit | 518039bc24cbb9ce34665814fe120eac50bedd9a (patch) | |
tree | 6b089a05025ae224d6636b6dc9d95e7c9e4677eb /arch/blackfin/kernel | |
parent | f16295e7e7f2a2a15876f570f10d6dc8f1f36ab8 (diff) |
Blackfin arch: Add ability to expend the hardware trace buffer
Add ability to expend the hardware trace buffer via a configurable
software buffer - so you can have lots of history when a crash occurs.
The interesting way we do printk in the traps.c confusese the checking
script
Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/irqchip.c | 9 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 53 |
2 files changed, 55 insertions, 7 deletions
diff --git a/arch/blackfin/kernel/irqchip.c b/arch/blackfin/kernel/irqchip.c index 1fc001c7abd..462ae41144c 100644 --- a/arch/blackfin/kernel/irqchip.c +++ b/arch/blackfin/kernel/irqchip.c @@ -34,6 +34,7 @@ #include <linux/kallsyms.h> #include <linux/interrupt.h> #include <linux/irq.h> +#include <asm/trace.h> static unsigned long irq_err_count; static spinlock_t irq_controller_lock; @@ -144,4 +145,12 @@ void __init init_IRQ(void) } init_arch_irq(); + +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND + /* Now that evt_ivhw is set up, turn this on */ + trace_buff_offset = 0; + bfin_write_TBUFCTL(BFIN_TRACE_ON); + printk(KERN_INFO "Hardware Trace expanded to %ik\n", + 1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN); +#endif } diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index 792a8416fe1..0ec02fe663e 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c @@ -55,6 +55,7 @@ asmlinkage void trap_c(struct pt_regs *fp); int kstack_depth_to_print = 48; +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON static int printk_address(unsigned long address) { struct vm_list_struct *vml; @@ -131,10 +132,14 @@ static int printk_address(unsigned long address) /* we were unable to find this address anywhere */ return printk("[<0x%p>]", (void *)address); } +#endif asmlinkage void trap_c(struct pt_regs *fp) { - int j, sig = 0; +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON + int j; +#endif + int sig = 0; siginfo_t info; unsigned long trapnr = fp->seqstat & SEQSTAT_EXCAUSE; @@ -429,24 +434,56 @@ asmlinkage void trap_c(struct pt_regs *fp) /* Typical exception handling routines */ +#define EXPAND_LEN ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 256 - 1) + void dump_bfin_trace_buffer(void) { - int tflags; +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON + int tflags, i = 0; +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND + int j, index; +#endif + trace_buffer_save(tflags); + printk(KERN_EMERG "Hardware Trace:\n"); + if (likely(bfin_read_TBUFSTAT() & TBUFCNT)) { - int i; - printk(KERN_EMERG "Hardware Trace:\n"); - for (i = 0; bfin_read_TBUFSTAT() & TBUFCNT; i++) { - printk(KERN_EMERG "%2i Target : ", i); + for (; bfin_read_TBUFSTAT() & TBUFCNT; i++) { + printk(KERN_EMERG "%4i Target : ", i); printk_address((unsigned long)bfin_read_TBUF()); - printk("\n" KERN_EMERG " Source : "); + printk("\n" KERN_EMERG " Source : "); printk_address((unsigned long)bfin_read_TBUF()); printk("\n"); } } +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND + if (trace_buff_offset) + index = trace_buff_offset/4 - 1; + else + index = EXPAND_LEN; + + j = (1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN) * 128; + while (j) { + printk(KERN_EMERG "%4i Target : ", i); + printk_address(software_trace_buff[index]); + index -= 1; + if (index < 0 ) + index = EXPAND_LEN; + printk("\n" KERN_EMERG " Source : "); + printk_address(software_trace_buff[index]); + index -= 1; + if (index < 0) + index = EXPAND_LEN; + printk("\n"); + j--; + i++; + } +#endif + trace_buffer_restore(tflags); +#endif } EXPORT_SYMBOL(dump_bfin_trace_buffer); @@ -510,7 +547,9 @@ void show_stack(struct task_struct *task, unsigned long *stack) void dump_stack(void) { unsigned long stack; +#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON int tflags; +#endif trace_buffer_save(tflags); dump_bfin_trace_buffer(); show_stack(current, &stack); |