aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGraf Yang <graf.yang@analog.com>2009-07-22 07:56:24 -0400
committerMike Frysinger <vapier@gentoo.org>2009-09-16 21:31:57 -0400
commit01b9f4b0ed3b1111b2080a3c9bcb66df1fdf48b7 (patch)
tree0963b346d63cc7ee44e3e769cc8435d224e17a87
parent858c5e9abc5c614b2eceb6a361118f31821ac968 (diff)
Blackfin: improve double fault debug handling
Since the hardware only provides reporting for the last exception handled, and the values are valid only when executing the exception handler, we need to save the context for reporting at a later point. While we do this for one exception, it doesn't work properly when handling a second one as the original exception is clobbered by the double fault. So when double fault debugging is enabled, create a dedicated shadow of these values and save/restore out of there. Now the crash report properly displays the first exception as well as the second one. Signed-off-by: Graf Yang <graf.yang@analog.com> Signed-off-by: Mike Frysinger <vapier@gentoo.org>
-rw-r--r--arch/blackfin/include/asm/pda.h6
-rw-r--r--arch/blackfin/kernel/asm-offsets.c6
-rw-r--r--arch/blackfin/kernel/traps.c8
-rw-r--r--arch/blackfin/mach-bf561/secondary.S8
-rw-r--r--arch/blackfin/mach-common/entry.S22
-rw-r--r--arch/blackfin/mach-common/head.S8
6 files changed, 37 insertions, 21 deletions
diff --git a/arch/blackfin/include/asm/pda.h b/arch/blackfin/include/asm/pda.h
index 69b96b40c188..a6f95695731d 100644
--- a/arch/blackfin/include/asm/pda.h
+++ b/arch/blackfin/include/asm/pda.h
@@ -61,6 +61,12 @@ struct blackfin_pda { /* Per-processor Data Area */
61 unsigned long retx; 61 unsigned long retx;
62 unsigned long seqstat; 62 unsigned long seqstat;
63 unsigned int __nmi_count; /* number of times NMI asserted on this CPU */ 63 unsigned int __nmi_count; /* number of times NMI asserted on this CPU */
64#ifdef CONFIG_DEBUG_DOUBLEFAULT
65 unsigned long dcplb_doublefault_addr;
66 unsigned long icplb_doublefault_addr;
67 unsigned long retx_doublefault;
68 unsigned long seqstat_doublefault;
69#endif
64}; 70};
65 71
66extern struct blackfin_pda cpu_pda[]; 72extern struct blackfin_pda cpu_pda[];
diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c
index 8ad4f2c69961..f05d1b99b0ef 100644
--- a/arch/blackfin/kernel/asm-offsets.c
+++ b/arch/blackfin/kernel/asm-offsets.c
@@ -153,6 +153,12 @@ int main(void)
153 DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr)); 153 DEFINE(PDA_ICPLB, offsetof(struct blackfin_pda, icplb_fault_addr));
154 DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx)); 154 DEFINE(PDA_RETX, offsetof(struct blackfin_pda, retx));
155 DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat)); 155 DEFINE(PDA_SEQSTAT, offsetof(struct blackfin_pda, seqstat));
156#ifdef CONFIG_DEBUG_DOUBLEFAULT
157 DEFINE(PDA_DF_DCPLB, offsetof(struct blackfin_pda, dcplb_doublefault_addr));
158 DEFINE(PDA_DF_ICPLB, offsetof(struct blackfin_pda, icplb_doublefault_addr));
159 DEFINE(PDA_DF_SEQSTAT, offsetof(struct blackfin_pda, seqstat_doublefault));
160 DEFINE(PDA_DF_RETX, offsetof(struct blackfin_pda, retx_doublefault));
161#endif
156#ifdef CONFIG_SMP 162#ifdef CONFIG_SMP
157 /* Inter-core lock (in L2 SRAM) */ 163 /* Inter-core lock (in L2 SRAM) */
158 DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot)); 164 DEFINE(SIZEOF_CORELOCK, sizeof(struct corelock_slot));
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c
index 644e35e33553..0904430d4137 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -229,12 +229,12 @@ asmlinkage void double_fault_c(struct pt_regs *fp)
229 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) { 229 if (((long)fp->seqstat & SEQSTAT_EXCAUSE) == VEC_UNCOV) {
230 unsigned int cpu = smp_processor_id(); 230 unsigned int cpu = smp_processor_id();
231 char buf[150]; 231 char buf[150];
232 decode_address(buf, cpu_pda[cpu].retx); 232 decode_address(buf, cpu_pda[cpu].retx_doublefault);
233 printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n", 233 printk(KERN_EMERG "While handling exception (EXCAUSE = 0x%x) at %s:\n",
234 (unsigned int)cpu_pda[cpu].seqstat & SEQSTAT_EXCAUSE, buf); 234 (unsigned int)cpu_pda[cpu].seqstat_doublefault & SEQSTAT_EXCAUSE, buf);
235 decode_address(buf, cpu_pda[cpu].dcplb_fault_addr); 235 decode_address(buf, cpu_pda[cpu].dcplb_doublefault_addr);
236 printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf); 236 printk(KERN_NOTICE " DCPLB_FAULT_ADDR: %s\n", buf);
237 decode_address(buf, cpu_pda[cpu].icplb_fault_addr); 237 decode_address(buf, cpu_pda[cpu].icplb_doublefault_addr);
238 printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf); 238 printk(KERN_NOTICE " ICPLB_FAULT_ADDR: %s\n", buf);
239 239
240 decode_address(buf, fp->retx); 240 decode_address(buf, fp->retx);
diff --git a/arch/blackfin/mach-bf561/secondary.S b/arch/blackfin/mach-bf561/secondary.S
index 35280f06b7b6..097550f7b558 100644
--- a/arch/blackfin/mach-bf561/secondary.S
+++ b/arch/blackfin/mach-bf561/secondary.S
@@ -126,22 +126,22 @@ ENTRY(_coreb_trampoline_start)
126 * below 126 * below
127 */ 127 */
128 GET_PDA(p0, r0); 128 GET_PDA(p0, r0);
129 r7 = [p0 + PDA_RETX]; 129 r7 = [p0 + PDA_DF_RETX];
130 p1.l = _init_saved_retx_coreb; 130 p1.l = _init_saved_retx_coreb;
131 p1.h = _init_saved_retx_coreb; 131 p1.h = _init_saved_retx_coreb;
132 [p1] = r7; 132 [p1] = r7;
133 133
134 r7 = [p0 + PDA_DCPLB]; 134 r7 = [p0 + PDA_DF_DCPLB];
135 p1.l = _init_saved_dcplb_fault_addr_coreb; 135 p1.l = _init_saved_dcplb_fault_addr_coreb;
136 p1.h = _init_saved_dcplb_fault_addr_coreb; 136 p1.h = _init_saved_dcplb_fault_addr_coreb;
137 [p1] = r7; 137 [p1] = r7;
138 138
139 r7 = [p0 + PDA_ICPLB]; 139 r7 = [p0 + PDA_DF_ICPLB];
140 p1.l = _init_saved_icplb_fault_addr_coreb; 140 p1.l = _init_saved_icplb_fault_addr_coreb;
141 p1.h = _init_saved_icplb_fault_addr_coreb; 141 p1.h = _init_saved_icplb_fault_addr_coreb;
142 [p1] = r7; 142 [p1] = r7;
143 143
144 r7 = [p0 + PDA_SEQSTAT]; 144 r7 = [p0 + PDA_DF_SEQSTAT];
145 p1.l = _init_saved_seqstat_coreb; 145 p1.l = _init_saved_seqstat_coreb;
146 p1.h = _init_saved_seqstat_coreb; 146 p1.h = _init_saved_seqstat_coreb;
147 [p1] = r7; 147 [p1] = r7;
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index cbc5b6d1ed06..4e8e3fe0ba1c 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -326,8 +326,6 @@ ENTRY(_ex_trap_c)
326 [p4] = r7; 326 [p4] = r7;
327 csync; 327 csync;
328 328
329#ifndef CONFIG_DEBUG_DOUBLEFAULT
330
331 /* 329 /*
332 * Save these registers, as they are only valid in exception context 330 * Save these registers, as they are only valid in exception context
333 * (where we are now - as soon as we defer to IRQ5, they can change) 331 * (where we are now - as soon as we defer to IRQ5, they can change)
@@ -347,7 +345,10 @@ ENTRY(_ex_trap_c)
347 345
348 r6 = retx; 346 r6 = retx;
349 [p5 + PDA_RETX] = r6; 347 [p5 + PDA_RETX] = r6;
350#endif 348
349 r6 = SEQSTAT;
350 [p5 + PDA_SEQSTAT] = r6;
351
351 /* Save the state of single stepping */ 352 /* Save the state of single stepping */
352 r6 = SYSCFG; 353 r6 = SYSCFG;
353 [p5 + PDA_SYSCFG] = r6; 354 [p5 + PDA_SYSCFG] = r6;
@@ -444,6 +445,9 @@ ENTRY(_exception_to_level5)
444 r6 = [p5 + PDA_SYSCFG]; 445 r6 = [p5 + PDA_SYSCFG];
445 [sp + PT_SYSCFG] = r6; 446 [sp + PT_SYSCFG] = r6;
446 447
448 r6 = [p5 + PDA_SEQSTAT]; /* Read back seqstat */
449 [sp + PT_SEQSTAT] = r6;
450
447 /* Restore the hardware error vector. */ 451 /* Restore the hardware error vector. */
448 r7.h = _evt_ivhw; 452 r7.h = _evt_ivhw;
449 r7.l = _evt_ivhw; 453 r7.l = _evt_ivhw;
@@ -496,7 +500,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
496 */ 500 */
497 EX_SCRATCH_REG = sp; 501 EX_SCRATCH_REG = sp;
498 GET_PDA_SAFE(sp); 502 GET_PDA_SAFE(sp);
499 sp = [sp + PDA_EXSTACK] 503 sp = [sp + PDA_EXSTACK];
500 /* Try to deal with syscalls quickly. */ 504 /* Try to deal with syscalls quickly. */
501 [--sp] = ASTAT; 505 [--sp] = ASTAT;
502 [--sp] = (R7:6,P5:4); 506 [--sp] = (R7:6,P5:4);
@@ -532,18 +536,18 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
532 p4.l = lo(DCPLB_FAULT_ADDR); 536 p4.l = lo(DCPLB_FAULT_ADDR);
533 p4.h = hi(DCPLB_FAULT_ADDR); 537 p4.h = hi(DCPLB_FAULT_ADDR);
534 r7 = [p4]; 538 r7 = [p4];
535 [p5 + PDA_DCPLB] = r7; 539 [p5 + PDA_DF_DCPLB] = r7;
536 540
537 p4.l = lo(ICPLB_FAULT_ADDR); 541 p4.l = lo(ICPLB_FAULT_ADDR);
538 p4.h = hi(ICPLB_FAULT_ADDR); 542 p4.h = hi(ICPLB_FAULT_ADDR);
539 r7 = [p4]; 543 r7 = [p4];
540 [p5 + PDA_ICPLB] = r7; 544 [p5 + PDA_DF_ICPLB] = r7;
541 545
542 r6 = retx; 546 r7 = retx;
543 [p5 + PDA_RETX] = r6; 547 [p5 + PDA_DF_RETX] = r7;
544 548
545 r7 = SEQSTAT; /* reason code is in bit 5:0 */ 549 r7 = SEQSTAT; /* reason code is in bit 5:0 */
546 [p5 + PDA_SEQSTAT] = r7; 550 [p5 + PDA_DF_SEQSTAT] = r7;
547#else 551#else
548 r7 = SEQSTAT; /* reason code is in bit 5:0 */ 552 r7 = SEQSTAT; /* reason code is in bit 5:0 */
549#endif 553#endif
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S
index 66910121fa6f..9c79dfea2a53 100644
--- a/arch/blackfin/mach-common/head.S
+++ b/arch/blackfin/mach-common/head.S
@@ -124,22 +124,22 @@ ENTRY(__start)
124 * below 124 * below
125 */ 125 */
126 GET_PDA(p0, r0); 126 GET_PDA(p0, r0);
127 r6 = [p0 + PDA_RETX]; 127 r6 = [p0 + PDA_DF_RETX];
128 p1.l = _init_saved_retx; 128 p1.l = _init_saved_retx;
129 p1.h = _init_saved_retx; 129 p1.h = _init_saved_retx;
130 [p1] = r6; 130 [p1] = r6;
131 131
132 r6 = [p0 + PDA_DCPLB]; 132 r6 = [p0 + PDA_DF_DCPLB];
133 p1.l = _init_saved_dcplb_fault_addr; 133 p1.l = _init_saved_dcplb_fault_addr;
134 p1.h = _init_saved_dcplb_fault_addr; 134 p1.h = _init_saved_dcplb_fault_addr;
135 [p1] = r6; 135 [p1] = r6;
136 136
137 r6 = [p0 + PDA_ICPLB]; 137 r6 = [p0 + PDA_DF_ICPLB];
138 p1.l = _init_saved_icplb_fault_addr; 138 p1.l = _init_saved_icplb_fault_addr;
139 p1.h = _init_saved_icplb_fault_addr; 139 p1.h = _init_saved_icplb_fault_addr;
140 [p1] = r6; 140 [p1] = r6;
141 141
142 r6 = [p0 + PDA_SEQSTAT]; 142 r6 = [p0 + PDA_DF_SEQSTAT];
143 p1.l = _init_saved_seqstat; 143 p1.l = _init_saved_seqstat;
144 p1.h = _init_saved_seqstat; 144 p1.h = _init_saved_seqstat;
145 [p1] = r6; 145 [p1] = r6;