aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorRobin Getz <rgetz@blackfin.uclinux.org>2008-10-08 04:27:12 -0400
committerBryan Wu <cooloney@kernel.org>2008-10-08 04:27:12 -0400
commit0c7a6b2135c1bcb5139ca9ca87f292caafcb9410 (patch)
treeee1e8b36a4dba9120035ddac270e63ba91dc649c /arch/blackfin/kernel
parentf4585a08479a730fb809606b8ee327a5398c117c (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.c30
-rw-r--r--arch/blackfin/kernel/traps.c34
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
54char __initdata command_line[COMMAND_LINE_SIZE]; 54char __initdata command_line[COMMAND_LINE_SIZE];
55unsigned int __initdata *__retx; 55void __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
71unsigned 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))
78unsigned long saved_retx, saved_seqstat,
79 saved_icplb_fault_addr, saved_dcplb_fault_addr;
72 80
73static void decode_address(char *buf, unsigned long address) 81static 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}