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 | |
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')
-rw-r--r-- | arch/blackfin/Kconfig.debug | 38 | ||||
-rw-r--r-- | arch/blackfin/kernel/setup.c | 30 | ||||
-rw-r--r-- | arch/blackfin/kernel/traps.c | 34 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 189 | ||||
-rw-r--r-- | arch/blackfin/mach-common/head.S | 40 |
5 files changed, 255 insertions, 76 deletions
diff --git a/arch/blackfin/Kconfig.debug b/arch/blackfin/Kconfig.debug index c468624d55f0..0afa89818722 100644 --- a/arch/blackfin/Kconfig.debug +++ b/arch/blackfin/Kconfig.debug | |||
@@ -22,6 +22,44 @@ config DEBUG_HWERR | |||
22 | hardware error interrupts and need to know where they are coming | 22 | hardware error interrupts and need to know where they are coming |
23 | from. | 23 | from. |
24 | 24 | ||
25 | config DEBUG_DOUBLEFAULT | ||
26 | bool "Debug Double Faults" | ||
27 | default n | ||
28 | help | ||
29 | If an exception is caused while executing code within the exception | ||
30 | handler, the NMI handler, the reset vector, or in emulator mode, | ||
31 | a double fault occurs. On the Blackfin, this is a unrecoverable | ||
32 | event. You have two options: | ||
33 | - RESET exactly when double fault occurs. The excepting | ||
34 | instruction address is stored in RETX, where the next kernel | ||
35 | boot will print it out. | ||
36 | - Print debug message. This is much more error prone, although | ||
37 | easier to handle. It is error prone since: | ||
38 | - The excepting instruction is not committed. | ||
39 | - All writebacks from the instruction are prevented. | ||
40 | - The generated exception is not taken. | ||
41 | - The EXCAUSE field is updated with an unrecoverable event | ||
42 | The only way to check this is to see if EXCAUSE contains the | ||
43 | unrecoverable event value at every exception return. By selecting | ||
44 | this option, you are skipping over the faulting instruction, and | ||
45 | hoping things stay together enough to print out a debug message. | ||
46 | |||
47 | This does add a little kernel code, but is the only method to debug | ||
48 | double faults - if unsure say "Y" | ||
49 | |||
50 | choice | ||
51 | prompt "Double Fault Failure Method" | ||
52 | default DEBUG_DOUBLEFAULT_PRINT | ||
53 | depends on DEBUG_DOUBLEFAULT | ||
54 | |||
55 | config DEBUG_DOUBLEFAULT_PRINT | ||
56 | bool "Print" | ||
57 | |||
58 | config DEBUG_DOUBLEFAULT_RESET | ||
59 | bool "Reset" | ||
60 | |||
61 | endchoice | ||
62 | |||
25 | config DEBUG_ICACHE_CHECK | 63 | config DEBUG_ICACHE_CHECK |
26 | bool "Check Instruction cache coherency" | 64 | bool "Check Instruction cache coherency" |
27 | depends on DEBUG_KERNEL | 65 | depends on DEBUG_KERNEL |
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 | } |
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 847c172a99eb..90c7397036ed 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S | |||
@@ -129,6 +129,18 @@ ENTRY(_ex_icplb_miss) | |||
129 | #else | 129 | #else |
130 | call __cplb_hdr; | 130 | call __cplb_hdr; |
131 | #endif | 131 | #endif |
132 | |||
133 | #ifdef CONFIG_DEBUG_DOUBLEFAULT | ||
134 | /* While we were processing this, did we double fault? */ | ||
135 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | ||
136 | r6.l = lo(SEQSTAT_EXCAUSE); | ||
137 | r6.h = hi(SEQSTAT_EXCAUSE); | ||
138 | r7 = r7 & r6; | ||
139 | r6 = 0x25; | ||
140 | CC = R7 == R6; | ||
141 | if CC JUMP _double_fault; | ||
142 | #endif | ||
143 | |||
132 | DEBUG_HWTRACE_RESTORE(p5, r7) | 144 | DEBUG_HWTRACE_RESTORE(p5, r7) |
133 | RESTORE_ALL_SYS | 145 | RESTORE_ALL_SYS |
134 | SP = EX_SCRATCH_REG; | 146 | SP = EX_SCRATCH_REG; |
@@ -136,11 +148,8 @@ ENTRY(_ex_icplb_miss) | |||
136 | ENDPROC(_ex_icplb_miss) | 148 | ENDPROC(_ex_icplb_miss) |
137 | 149 | ||
138 | ENTRY(_ex_syscall) | 150 | ENTRY(_ex_syscall) |
139 | (R7:6,P5:4) = [sp++]; | ||
140 | ASTAT = [sp++]; | ||
141 | raise 15; /* invoked by TRAP #0, for sys call */ | 151 | raise 15; /* invoked by TRAP #0, for sys call */ |
142 | sp = EX_SCRATCH_REG; | 152 | jump.s _bfin_return_from_exception; |
143 | rtx | ||
144 | ENDPROC(_ex_syscall) | 153 | ENDPROC(_ex_syscall) |
145 | 154 | ||
146 | ENTRY(_ex_soft_bp) | 155 | ENTRY(_ex_soft_bp) |
@@ -250,6 +259,29 @@ ENTRY(_bfin_return_from_exception) | |||
250 | R7=LC1; | 259 | R7=LC1; |
251 | LC1=R7; | 260 | LC1=R7; |
252 | #endif | 261 | #endif |
262 | |||
263 | #ifdef CONFIG_DEBUG_DOUBLEFAULT | ||
264 | /* While we were processing the current exception, | ||
265 | * did we cause another, and double fault? | ||
266 | */ | ||
267 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | ||
268 | r6.l = lo(SEQSTAT_EXCAUSE); | ||
269 | r6.h = hi(SEQSTAT_EXCAUSE); | ||
270 | r7 = r7 & r6; | ||
271 | r6 = 0x25; | ||
272 | CC = R7 == R6; | ||
273 | if CC JUMP _double_fault; | ||
274 | |||
275 | /* Did we cause a HW error? */ | ||
276 | p5.l = lo(ILAT); | ||
277 | p5.h = hi(ILAT); | ||
278 | r6 = [p5]; | ||
279 | r7 = 0x20; /* Did I just cause anther HW error? */ | ||
280 | r7 = r7 & r1; | ||
281 | CC = R7 == R6; | ||
282 | if CC JUMP _double_fault; | ||
283 | #endif | ||
284 | |||
253 | (R7:6,P5:4) = [sp++]; | 285 | (R7:6,P5:4) = [sp++]; |
254 | ASTAT = [sp++]; | 286 | ASTAT = [sp++]; |
255 | sp = EX_SCRATCH_REG; | 287 | sp = EX_SCRATCH_REG; |
@@ -292,6 +324,14 @@ ENTRY(_ex_trap_c) | |||
292 | [p4] = p5; | 324 | [p4] = p5; |
293 | csync; | 325 | csync; |
294 | 326 | ||
327 | #ifndef CONFIG_DEBUG_DOUBLEFAULT | ||
328 | /* | ||
329 | * Save these registers, as they are only valid in exception context | ||
330 | * (where we are now - as soon as we defer to IRQ5, they can change) | ||
331 | * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3, | ||
332 | * but they are not very interesting, so don't save them | ||
333 | */ | ||
334 | |||
295 | p4.l = lo(DCPLB_FAULT_ADDR); | 335 | p4.l = lo(DCPLB_FAULT_ADDR); |
296 | p4.h = hi(DCPLB_FAULT_ADDR); | 336 | p4.h = hi(DCPLB_FAULT_ADDR); |
297 | r7 = [p4]; | 337 | r7 = [p4]; |
@@ -304,12 +344,11 @@ ENTRY(_ex_trap_c) | |||
304 | p5.l = _saved_icplb_fault_addr; | 344 | p5.l = _saved_icplb_fault_addr; |
305 | [p5] = r7; | 345 | [p5] = r7; |
306 | 346 | ||
307 | p4.l = _excpt_saved_stuff; | ||
308 | p4.h = _excpt_saved_stuff; | ||
309 | |||
310 | r6 = retx; | 347 | r6 = retx; |
348 | p4.l = _saved_retx; | ||
349 | p4.h = _saved_retx; | ||
311 | [p4] = r6; | 350 | [p4] = r6; |
312 | 351 | #endif | |
313 | r6 = SYSCFG; | 352 | r6 = SYSCFG; |
314 | [p4 + 4] = r6; | 353 | [p4 + 4] = r6; |
315 | BITCLR(r6, 0); | 354 | BITCLR(r6, 0); |
@@ -327,59 +366,56 @@ ENTRY(_ex_trap_c) | |||
327 | r6 = 0x3f; | 366 | r6 = 0x3f; |
328 | sti r6; | 367 | sti r6; |
329 | 368 | ||
330 | (R7:6,P5:4) = [sp++]; | ||
331 | ASTAT = [sp++]; | ||
332 | SP = EX_SCRATCH_REG; | ||
333 | raise 5; | 369 | raise 5; |
334 | rtx; | 370 | jump.s _bfin_return_from_exception; |
335 | ENDPROC(_ex_trap_c) | 371 | ENDPROC(_ex_trap_c) |
336 | 372 | ||
337 | /* We just realized we got an exception, while we were processing a different | 373 | /* We just realized we got an exception, while we were processing a different |
338 | * exception. This is a unrecoverable event, so crash | 374 | * exception. This is a unrecoverable event, so crash |
339 | */ | 375 | */ |
340 | ENTRY(_double_fault) | 376 | ENTRY(_double_fault) |
341 | /* Turn caches & protection off, to ensure we don't get any more | 377 | /* Turn caches & protection off, to ensure we don't get any more |
342 | * double exceptions | 378 | * double exceptions |
343 | */ | 379 | */ |
344 | 380 | ||
345 | P4.L = LO(IMEM_CONTROL); | 381 | P4.L = LO(IMEM_CONTROL); |
346 | P4.H = HI(IMEM_CONTROL); | 382 | P4.H = HI(IMEM_CONTROL); |
347 | 383 | ||
348 | R5 = [P4]; /* Control Register*/ | 384 | R5 = [P4]; /* Control Register*/ |
349 | BITCLR(R5,ENICPLB_P); | 385 | BITCLR(R5,ENICPLB_P); |
350 | SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ | 386 | SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */ |
351 | .align 8; | 387 | .align 8; |
352 | [P4] = R5; | 388 | [P4] = R5; |
353 | SSYNC; | 389 | SSYNC; |
354 | 390 | ||
355 | P4.L = LO(DMEM_CONTROL); | 391 | P4.L = LO(DMEM_CONTROL); |
356 | P4.H = HI(DMEM_CONTROL); | 392 | P4.H = HI(DMEM_CONTROL); |
357 | R5 = [P4]; | 393 | R5 = [P4]; |
358 | BITCLR(R5,ENDCPLB_P); | 394 | BITCLR(R5,ENDCPLB_P); |
359 | SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ | 395 | SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */ |
360 | .align 8; | 396 | .align 8; |
361 | [P4] = R5; | 397 | [P4] = R5; |
362 | SSYNC; | 398 | SSYNC; |
363 | 399 | ||
364 | /* Fix up the stack */ | 400 | /* Fix up the stack */ |
365 | (R7:6,P5:4) = [sp++]; | 401 | (R7:6,P5:4) = [sp++]; |
366 | ASTAT = [sp++]; | 402 | ASTAT = [sp++]; |
367 | SP = EX_SCRATCH_REG; | 403 | SP = EX_SCRATCH_REG; |
368 | 404 | ||
369 | /* We should be out of the exception stack, and back down into | 405 | /* We should be out of the exception stack, and back down into |
370 | * kernel or user space stack | 406 | * kernel or user space stack |
371 | */ | 407 | */ |
372 | SAVE_ALL_SYS | 408 | SAVE_ALL_SYS |
373 | 409 | ||
374 | /* The dumping functions expect the return address in the RETI | 410 | /* The dumping functions expect the return address in the RETI |
375 | * slot. */ | 411 | * slot. */ |
376 | r6 = retx; | 412 | r6 = retx; |
377 | [sp + PT_PC] = r6; | 413 | [sp + PT_PC] = r6; |
378 | 414 | ||
379 | r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ | 415 | r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ |
380 | SP += -12; | 416 | SP += -12; |
381 | call _double_fault_c; | 417 | call _double_fault_c; |
382 | SP += 12; | 418 | SP += 12; |
383 | .L_double_fault_panic: | 419 | .L_double_fault_panic: |
384 | JUMP .L_double_fault_panic | 420 | JUMP .L_double_fault_panic |
385 | 421 | ||
@@ -388,8 +424,8 @@ ENDPROC(_double_fault) | |||
388 | ENTRY(_exception_to_level5) | 424 | ENTRY(_exception_to_level5) |
389 | SAVE_ALL_SYS | 425 | SAVE_ALL_SYS |
390 | 426 | ||
391 | p4.l = _excpt_saved_stuff; | 427 | p4.l = _saved_retx; |
392 | p4.h = _excpt_saved_stuff; | 428 | p4.h = _saved_retx; |
393 | r6 = [p4]; | 429 | r6 = [p4]; |
394 | [sp + PT_PC] = r6; | 430 | [sp + PT_PC] = r6; |
395 | 431 | ||
@@ -420,6 +456,17 @@ ENTRY(_exception_to_level5) | |||
420 | call _trap_c; | 456 | call _trap_c; |
421 | SP += 12; | 457 | SP += 12; |
422 | 458 | ||
459 | #ifdef CONFIG_DEBUG_DOUBLEFAULT | ||
460 | /* Grab ILAT */ | ||
461 | p2.l = lo(ILAT); | ||
462 | p2.h = hi(ILAT); | ||
463 | r0 = [p2]; | ||
464 | r1 = 0x20; /* Did I just cause anther HW error? */ | ||
465 | r0 = r0 & r1; | ||
466 | CC = R0 == R1; | ||
467 | if CC JUMP _double_fault; | ||
468 | #endif | ||
469 | |||
423 | call _ret_from_exception; | 470 | call _ret_from_exception; |
424 | RESTORE_ALL_SYS | 471 | RESTORE_ALL_SYS |
425 | rti; | 472 | rti; |
@@ -436,7 +483,39 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ | |||
436 | /* Try to deal with syscalls quickly. */ | 483 | /* Try to deal with syscalls quickly. */ |
437 | [--sp] = ASTAT; | 484 | [--sp] = ASTAT; |
438 | [--sp] = (R7:6,P5:4); | 485 | [--sp] = (R7:6,P5:4); |
486 | |||
487 | #ifdef CONFIG_DEBUG_DOUBLEFAULT | ||
488 | /* | ||
489 | * Save these registers, as they are only valid in exception context | ||
490 | * (where we are now - as soon as we defer to IRQ5, they can change) | ||
491 | * DCPLB_STATUS and ICPLB_STATUS are also only valid in EVT3, | ||
492 | * but they are not very interesting, so don't save them | ||
493 | */ | ||
494 | |||
495 | p4.l = lo(DCPLB_FAULT_ADDR); | ||
496 | p4.h = hi(DCPLB_FAULT_ADDR); | ||
497 | r7 = [p4]; | ||
498 | p5.h = _saved_dcplb_fault_addr; | ||
499 | p5.l = _saved_dcplb_fault_addr; | ||
500 | [p5] = r7; | ||
501 | |||
502 | r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; | ||
503 | p5.h = _saved_icplb_fault_addr; | ||
504 | p5.l = _saved_icplb_fault_addr; | ||
505 | [p5] = r7; | ||
506 | |||
507 | p4.l = _saved_retx; | ||
508 | p4.h = _saved_retx; | ||
509 | r6 = retx; | ||
510 | [p4] = r6; | ||
511 | |||
439 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | 512 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ |
513 | p4.l = _saved_seqstat; | ||
514 | p4.h = _saved_seqstat; | ||
515 | [p4] = r7; | ||
516 | #else | ||
517 | r7 = SEQSTAT; /* reason code is in bit 5:0 */ | ||
518 | #endif | ||
440 | r6.l = lo(SEQSTAT_EXCAUSE); | 519 | r6.l = lo(SEQSTAT_EXCAUSE); |
441 | r6.h = hi(SEQSTAT_EXCAUSE); | 520 | r6.h = hi(SEQSTAT_EXCAUSE); |
442 | r7 = r7 & r6; | 521 | r7 = r7 & r6; |
@@ -1432,15 +1511,7 @@ ENTRY(_sys_call_table) | |||
1432 | .rept NR_syscalls-(.-_sys_call_table)/4 | 1511 | .rept NR_syscalls-(.-_sys_call_table)/4 |
1433 | .long _sys_ni_syscall | 1512 | .long _sys_ni_syscall |
1434 | .endr | 1513 | .endr |
1435 | 1514 | END(_sys_call_table) | |
1436 | /* | ||
1437 | * Used to save the real RETX, IMASK and SYSCFG when temporarily | ||
1438 | * storing safe values across the transition from exception to IRQ5. | ||
1439 | */ | ||
1440 | _excpt_saved_stuff: | ||
1441 | .long 0; | ||
1442 | .long 0; | ||
1443 | .long 0; | ||
1444 | 1515 | ||
1445 | _exception_stack: | 1516 | _exception_stack: |
1446 | .rept 1024 | 1517 | .rept 1024 |
diff --git a/arch/blackfin/mach-common/head.S b/arch/blackfin/mach-common/head.S index 191b4e974c4b..7cb21cfcbf28 100644 --- a/arch/blackfin/mach-common/head.S +++ b/arch/blackfin/mach-common/head.S | |||
@@ -90,12 +90,46 @@ ENTRY(__start) | |||
90 | [p0] = R0; | 90 | [p0] = R0; |
91 | SSYNC; | 91 | SSYNC; |
92 | 92 | ||
93 | /* Save RETX, in case of doublefault */ | 93 | /* in case of double faults, save a few things */ |
94 | p0.l = ___retx; | 94 | p0.l = _init_retx; |
95 | p0.h = ___retx; | 95 | p0.h = _init_retx; |
96 | R0 = RETX; | 96 | R0 = RETX; |
97 | [P0] = R0; | 97 | [P0] = R0; |
98 | 98 | ||
99 | #ifdef CONFIG_DEBUG_DOUBLEFAULT | ||
100 | /* Only save these if we are storing them, | ||
101 | * This happens here, since L1 gets clobbered | ||
102 | * below | ||
103 | */ | ||
104 | p0.l = _saved_retx; | ||
105 | p0.h = _saved_retx; | ||
106 | p1.l = _init_saved_retx; | ||
107 | p1.h = _init_saved_retx; | ||
108 | r0 = [p0]; | ||
109 | [p1] = r0; | ||
110 | |||
111 | p0.l = _saved_dcplb_fault_addr; | ||
112 | p0.h = _saved_dcplb_fault_addr; | ||
113 | p1.l = _init_saved_dcplb_fault_addr; | ||
114 | p1.h = _init_saved_dcplb_fault_addr; | ||
115 | r0 = [p0]; | ||
116 | [p1] = r0; | ||
117 | |||
118 | p0.l = _saved_icplb_fault_addr; | ||
119 | p0.h = _saved_icplb_fault_addr; | ||
120 | p1.l = _init_saved_icplb_fault_addr; | ||
121 | p1.h = _init_saved_icplb_fault_addr; | ||
122 | r0 = [p0]; | ||
123 | [p1] = r0; | ||
124 | |||
125 | p0.l = _saved_seqstat; | ||
126 | p0.h = _saved_seqstat; | ||
127 | p1.l = _init_saved_seqstat; | ||
128 | p1.h = _init_saved_seqstat; | ||
129 | r0 = [p0]; | ||
130 | [p1] = r0; | ||
131 | #endif | ||
132 | |||
99 | /* Initialize stack pointer */ | 133 | /* Initialize stack pointer */ |
100 | sp.l = lo(INITIAL_STACK); | 134 | sp.l = lo(INITIAL_STACK); |
101 | sp.h = hi(INITIAL_STACK); | 135 | sp.h = hi(INITIAL_STACK); |