diff options
author | Robin Getz <rgetz@blackfin.uclinux.org> | 2008-10-08 04:27:12 -0400 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2008-10-08 04:27:12 -0400 |
commit | 0c7a6b2135c1bcb5139ca9ca87f292caafcb9410 (patch) | |
tree | ee1e8b36a4dba9120035ddac270e63ba91dc649c /arch/blackfin/kernel | |
parent | f4585a08479a730fb809606b8ee327a5398c117c (diff) |
Blackfin arch: add supporting for double fault debug handling
Signed-off-by: Robin Getz <rgetz@blackfin.uclinux.org>
Signed-off-by: Mike Frysinger <vapier.adi@gmail.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r-- | arch/blackfin/kernel/setup.c | 30 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 34 |
2 files changed, 50 insertions, 14 deletions
diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 7a82d10b4ebf..8e639dc886a3 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c | |||
@@ -52,7 +52,8 @@ EXPORT_SYMBOL(mtd_size); | |||
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | char __initdata command_line[COMMAND_LINE_SIZE]; | 54 | char __initdata command_line[COMMAND_LINE_SIZE]; |
55 | unsigned int __initdata *__retx; | 55 | void __initdata *init_retx, *init_saved_retx, *init_saved_seqstat, |
56 | *init_saved_icplb_fault_addr, *init_saved_dcplb_fault_addr; | ||
56 | 57 | ||
57 | /* boot memmap, for parsing "memmap=" */ | 58 | /* boot memmap, for parsing "memmap=" */ |
58 | #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ | 59 | #define BFIN_MEMMAP_MAX 128 /* number of entries in bfin_memmap */ |
@@ -782,16 +783,25 @@ void __init setup_arch(char **cmdline_p) | |||
782 | 783 | ||
783 | _bfin_swrst = bfin_read_SWRST(); | 784 | _bfin_swrst = bfin_read_SWRST(); |
784 | 785 | ||
785 | /* If we double fault, reset the system - otherwise we hang forever */ | 786 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT |
786 | bfin_write_SWRST(DOUBLE_FAULT); | 787 | bfin_write_SWRST(_bfin_swrst & ~DOUBLE_FAULT); |
788 | #endif | ||
789 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_RESET | ||
790 | bfin_write_SWRST(_bfin_swrst | DOUBLE_FAULT); | ||
791 | #endif | ||
787 | 792 | ||
788 | if (_bfin_swrst & RESET_DOUBLE) | 793 | if (_bfin_swrst & RESET_DOUBLE) { |
789 | /* | 794 | printk(KERN_EMERG "Recovering from DOUBLE FAULT event\n"); |
790 | * don't decode the address, since you don't know if this | 795 | #ifdef CONFIG_DEBUG_DOUBLEFAULT |
791 | * kernel's symbol map is the same as the crashing kernel | 796 | /* We assume the crashing kernel, and the current symbol table match */ |
792 | */ | 797 | printk(KERN_EMERG " While handling exception (EXCAUSE = 0x%x) at %pF\n", |
793 | printk(KERN_INFO "Recovering from Double Fault event at %pF\n", __retx); | 798 | (int)init_saved_seqstat & SEQSTAT_EXCAUSE, init_saved_retx); |
794 | else if (_bfin_swrst & RESET_WDOG) | 799 | printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %pF\n", init_saved_dcplb_fault_addr); |
800 | printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %pF\n", init_saved_icplb_fault_addr); | ||
801 | #endif | ||
802 | printk(KERN_NOTICE " The instruction at %pF caused a double exception\n", | ||
803 | init_retx); | ||
804 | } else if (_bfin_swrst & RESET_WDOG) | ||
795 | printk(KERN_INFO "Recovering from Watchdog event\n"); | 805 | printk(KERN_INFO "Recovering from Watchdog event\n"); |
796 | else if (_bfin_swrst & RESET_SOFTWARE) | 806 | else if (_bfin_swrst & RESET_SOFTWARE) |
797 | printk(KERN_NOTICE "Reset caused by Software reset\n"); | 807 | printk(KERN_NOTICE "Reset caused by Software reset\n"); |
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index fd24e04fc19e..bd41fca315dd 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -68,7 +68,15 @@ void __init trap_init(void) | |||
68 | CSYNC(); | 68 | CSYNC(); |
69 | } | 69 | } |
70 | 70 | ||
71 | unsigned long saved_icplb_fault_addr, saved_dcplb_fault_addr; | 71 | /* |
72 | * Used to save the RETX, SEQSTAT, I/D CPLB FAULT ADDR | ||
73 | * values across the transition from exception to IRQ5. | ||
74 | * We put these in L1, so they are going to be in a valid | ||
75 | * location during exception context | ||
76 | */ | ||
77 | __attribute__((l1_data)) | ||
78 | unsigned long saved_retx, saved_seqstat, | ||
79 | saved_icplb_fault_addr, saved_dcplb_fault_addr; | ||
72 | 80 | ||
73 | static void decode_address(char *buf, unsigned long address) | 81 | static void decode_address(char *buf, unsigned long address) |
74 | { | 82 | { |
@@ -186,9 +194,27 @@ asmlinkage void double_fault_c(struct pt_regs *fp) | |||
186 | console_verbose(); | 194 | console_verbose(); |
187 | oops_in_progress = 1; | 195 | oops_in_progress = 1; |
188 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); | 196 | printk(KERN_EMERG "\n" KERN_EMERG "Double Fault\n"); |
189 | dump_bfin_process(fp); | 197 | #ifdef CONFIG_DEBUG_DOUBLEFAULT_PRINT |
190 | dump_bfin_mem(fp); | 198 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { |
191 | show_regs(fp); | 199 | char buf[150]; |
200 | decode_address(buf, saved_retx); | ||
201 | printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", | ||
202 | (int)saved_seqstat & SEQSTAT_EXCAUSE, buf); | ||
203 | decode_address(buf, saved_dcplb_fault_addr); | ||
204 | printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); | ||
205 | decode_address(buf, saved_icplb_fault_addr); | ||
206 | printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); | ||
207 | |||
208 | decode_address(buf, fp->retx); | ||
209 | printk(KERN_NOTICE "The instruction at %s caused a double exception\n", | ||
210 | buf); | ||
211 | } else | ||
212 | #endif | ||
213 | { | ||
214 | dump_bfin_process(fp); | ||
215 | dump_bfin_mem(fp); | ||
216 | show_regs(fp); | ||
217 | } | ||
192 | panic("Double Fault - unrecoverable event\n"); | 218 | panic("Double Fault - unrecoverable event\n"); |
193 | 219 | ||
194 | } | 220 | } |