diff options
-rw-r--r-- | arch/blackfin/kernel/traps.c | 15 | ||||
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 121 | ||||
-rw-r--r-- | arch/blackfin/mach-common/ints-priority.c | 2 |
3 files changed, 40 insertions, 98 deletions
diff --git a/arch/blackfin/kernel/traps.c b/arch/blackfin/kernel/traps.c index d0f675422074..5b847070dae5 100644 --- a/arch/blackfin/kernel/traps.c +++ b/arch/blackfin/kernel/traps.c | |||
@@ -67,6 +67,8 @@ void __init trap_init(void) | |||
67 | CSYNC(); | 67 | CSYNC(); |
68 | } | 68 | } |
69 | 69 | ||
70 | void *saved_icplb_fault_addr, *saved_dcplb_fault_addr; | ||
71 | |||
70 | int kstack_depth_to_print = 48; | 72 | int kstack_depth_to_print = 48; |
71 | 73 | ||
72 | static void decode_address(char *buf, unsigned long address) | 74 | static void decode_address(char *buf, unsigned long address) |
@@ -703,10 +705,7 @@ void dump_bfin_mem(struct pt_regs *fp) | |||
703 | unsigned short *addr, *erraddr, val = 0, err = 0; | 705 | unsigned short *addr, *erraddr, val = 0, err = 0; |
704 | char sti = 0, buf[6]; | 706 | char sti = 0, buf[6]; |
705 | 707 | ||
706 | if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR)) | 708 | erraddr = (void *)fp->pc; |
707 | erraddr = (void *)fp->pc; | ||
708 | else | ||
709 | erraddr = (void *)fp->retx; | ||
710 | 709 | ||
711 | printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); | 710 | printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr); |
712 | 711 | ||
@@ -830,9 +829,9 @@ unlock: | |||
830 | 829 | ||
831 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && | 830 | if (((long)fp->seqstat & SEQSTAT_EXCAUSE) && |
832 | (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { | 831 | (((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) { |
833 | decode_address(buf, bfin_read_DCPLB_FAULT_ADDR()); | 832 | decode_address(buf, saved_dcplb_fault_addr); |
834 | printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); | 833 | printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf); |
835 | decode_address(buf, bfin_read_ICPLB_FAULT_ADDR()); | 834 | decode_address(buf, saved_icplb_fault_addr); |
836 | printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); | 835 | printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf); |
837 | } | 836 | } |
838 | 837 | ||
@@ -940,8 +939,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp) | |||
940 | 939 | ||
941 | oops_in_progress = 1; | 940 | oops_in_progress = 1; |
942 | 941 | ||
943 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR()); | 942 | printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", saved_dcplb_fault_addr); |
944 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR()); | 943 | printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", saved_icplb_fault_addr); |
945 | dump_bfin_process(fp); | 944 | dump_bfin_process(fp); |
946 | dump_bfin_mem(fp); | 945 | dump_bfin_mem(fp); |
947 | show_regs(fp); | 946 | show_regs(fp); |
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index a504c65d9990..f2fb87e9a46e 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/unistd.h> | 38 | #include <linux/unistd.h> |
39 | #include <asm/blackfin.h> | 39 | #include <asm/blackfin.h> |
40 | #include <asm/errno.h> | 40 | #include <asm/errno.h> |
41 | #include <asm/fixed_code.h> | ||
41 | #include <asm/thread_info.h> /* TIF_NEED_RESCHED */ | 42 | #include <asm/thread_info.h> /* TIF_NEED_RESCHED */ |
42 | #include <asm/asm-offsets.h> | 43 | #include <asm/asm-offsets.h> |
43 | #include <asm/trace.h> | 44 | #include <asm/trace.h> |
@@ -52,15 +53,6 @@ | |||
52 | # define EX_SCRATCH_REG CYCLES | 53 | # define EX_SCRATCH_REG CYCLES |
53 | #endif | 54 | #endif |
54 | 55 | ||
55 | #if ANOMALY_05000281 | ||
56 | ENTRY(_safe_speculative_execution) | ||
57 | NOP; | ||
58 | NOP; | ||
59 | NOP; | ||
60 | jump _safe_speculative_execution; | ||
61 | ENDPROC(_safe_speculative_execution) | ||
62 | #endif | ||
63 | |||
64 | #ifdef CONFIG_EXCPT_IRQ_SYSC_L1 | 56 | #ifdef CONFIG_EXCPT_IRQ_SYSC_L1 |
65 | .section .l1.text | 57 | .section .l1.text |
66 | #else | 58 | #else |
@@ -230,6 +222,26 @@ ENTRY(_ex_trap_c) | |||
230 | [p4] = p5; | 222 | [p4] = p5; |
231 | csync; | 223 | csync; |
232 | 224 | ||
225 | p4.l = lo(DCPLB_FAULT_ADDR); | ||
226 | p4.h = hi(DCPLB_FAULT_ADDR); | ||
227 | r7 = [p4]; | ||
228 | p5.h = _saved_dcplb_fault_addr; | ||
229 | p5.l = _saved_dcplb_fault_addr; | ||
230 | [p5] = r7; | ||
231 | |||
232 | r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)]; | ||
233 | p5.h = _saved_icplb_fault_addr; | ||
234 | p5.l = _saved_icplb_fault_addr; | ||
235 | [p5] = r7; | ||
236 | |||
237 | p4.l = __retx; | ||
238 | p4.h = __retx; | ||
239 | r6 = retx; | ||
240 | [p4] = r6; | ||
241 | p4.l = lo(SAFE_USER_INSTRUCTION); | ||
242 | p4.h = hi(SAFE_USER_INSTRUCTION); | ||
243 | retx = p4; | ||
244 | |||
233 | /* Disable all interrupts, but make sure level 5 is enabled so | 245 | /* Disable all interrupts, but make sure level 5 is enabled so |
234 | * we can switch to that level. Save the old mask. */ | 246 | * we can switch to that level. Save the old mask. */ |
235 | cli r6; | 247 | cli r6; |
@@ -239,23 +251,6 @@ ENTRY(_ex_trap_c) | |||
239 | r6 = 0x3f; | 251 | r6 = 0x3f; |
240 | sti r6; | 252 | sti r6; |
241 | 253 | ||
242 | /* Save the excause into a circular buffer, in case the instruction | ||
243 | * which caused this excecptions causes others. | ||
244 | */ | ||
245 | P5.l = _in_ptr_excause; | ||
246 | P5.h = _in_ptr_excause; | ||
247 | R7 = [P5]; | ||
248 | R7 += 4; | ||
249 | R6 = 0xF; | ||
250 | R7 = R7 & R6; | ||
251 | [P5] = R7; | ||
252 | R6.l = _excause_circ_buf; | ||
253 | R6.h = _excause_circ_buf; | ||
254 | R7 = R7 + R6; | ||
255 | p5 = R7; | ||
256 | R6 = SEQSTAT; | ||
257 | [P5] = R6; | ||
258 | |||
259 | (R7:6,P5:4) = [sp++]; | 254 | (R7:6,P5:4) = [sp++]; |
260 | ASTAT = [sp++]; | 255 | ASTAT = [sp++]; |
261 | SP = EX_SCRATCH_REG; | 256 | SP = EX_SCRATCH_REG; |
@@ -312,6 +307,11 @@ ENDPROC(_double_fault) | |||
312 | ENTRY(_exception_to_level5) | 307 | ENTRY(_exception_to_level5) |
313 | SAVE_ALL_SYS | 308 | SAVE_ALL_SYS |
314 | 309 | ||
310 | p4.l = __retx; | ||
311 | p4.h = __retx; | ||
312 | r6 = [p4]; | ||
313 | [sp + PT_PC] = r6; | ||
314 | |||
315 | /* Restore interrupt mask. We haven't pushed RETI, so this | 315 | /* Restore interrupt mask. We haven't pushed RETI, so this |
316 | * doesn't enable interrupts until we return from this handler. */ | 316 | * doesn't enable interrupts until we return from this handler. */ |
317 | p4.l = _excpt_saved_imask; | 317 | p4.l = _excpt_saved_imask; |
@@ -333,42 +333,11 @@ ENTRY(_exception_to_level5) | |||
333 | r0 = [p2]; /* Read current IPEND */ | 333 | r0 = [p2]; /* Read current IPEND */ |
334 | [sp + PT_IPEND] = r0; /* Store IPEND */ | 334 | [sp + PT_IPEND] = r0; /* Store IPEND */ |
335 | 335 | ||
336 | /* Pop the excause from the circular buffer and push it on the stack | ||
337 | * (in the right place - if you change the location of SEQSTAT, you | ||
338 | * must change this offset. | ||
339 | */ | ||
340 | .L_excep_to_5_again: | ||
341 | P5.l = _out_ptr_excause; | ||
342 | P5.h = _out_ptr_excause; | ||
343 | R7 = [P5]; | ||
344 | R7 += 4; | ||
345 | R6 = 0xF; | ||
346 | R7 = R7 & R6; | ||
347 | [P5] = R7; | ||
348 | R6.l = _excause_circ_buf; | ||
349 | R6.h = _excause_circ_buf; | ||
350 | R7 = R7 + R6; | ||
351 | P5 = R7; | ||
352 | R1 = [P5]; | ||
353 | [SP + PT_SEQSTAT] = r1; | ||
354 | |||
355 | r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ | 336 | r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */ |
356 | SP += -12; | 337 | SP += -12; |
357 | call _trap_c; | 338 | call _trap_c; |
358 | SP += 12; | 339 | SP += 12; |
359 | 340 | ||
360 | /* See if anything else is in the exception buffer | ||
361 | * if there is, process it | ||
362 | */ | ||
363 | P5.l = _out_ptr_excause; | ||
364 | P5.h = _out_ptr_excause; | ||
365 | P4.l = _in_ptr_excause; | ||
366 | P4.h = _in_ptr_excause; | ||
367 | R6 = [P5]; | ||
368 | R7 = [P4]; | ||
369 | CC = R6 == R7; | ||
370 | if ! CC JUMP .L_excep_to_5_again | ||
371 | |||
372 | call _ret_from_exception; | 341 | call _ret_from_exception; |
373 | RESTORE_ALL_SYS | 342 | RESTORE_ALL_SYS |
374 | rti; | 343 | rti; |
@@ -732,8 +701,8 @@ ENTRY(_return_from_int) | |||
732 | [p0] = p1; | 701 | [p0] = p1; |
733 | csync; | 702 | csync; |
734 | #if ANOMALY_05000281 | 703 | #if ANOMALY_05000281 |
735 | r0.l = _safe_speculative_execution; | 704 | r0.l = lo(SAFE_USER_INSTRUCTION); |
736 | r0.h = _safe_speculative_execution; | 705 | r0.h = hi(SAFE_USER_INSTRUCTION); |
737 | reti = r0; | 706 | reti = r0; |
738 | #endif | 707 | #endif |
739 | r0 = 0x801f (z); | 708 | r0 = 0x801f (z); |
@@ -746,8 +715,8 @@ ENDPROC(_return_from_int) | |||
746 | 715 | ||
747 | ENTRY(_lower_to_irq14) | 716 | ENTRY(_lower_to_irq14) |
748 | #if ANOMALY_05000281 | 717 | #if ANOMALY_05000281 |
749 | r0.l = _safe_speculative_execution; | 718 | r0.l = lo(SAFE_USER_INSTRUCTION); |
750 | r0.h = _safe_speculative_execution; | 719 | r0.h = hi(SAFE_USER_INSTRUCTION); |
751 | reti = r0; | 720 | reti = r0; |
752 | #endif | 721 | #endif |
753 | r0 = 0x401f; | 722 | r0 = 0x401f; |
@@ -814,20 +783,6 @@ _schedule_and_signal: | |||
814 | rti; | 783 | rti; |
815 | ENDPROC(_lower_to_irq14) | 784 | ENDPROC(_lower_to_irq14) |
816 | 785 | ||
817 | /* Make sure when we start, that the circular buffer is initialized properly | ||
818 | * R0 and P0 are call clobbered, so we can use them here. | ||
819 | */ | ||
820 | ENTRY(_init_exception_buff) | ||
821 | r0 = 0; | ||
822 | p0.h = _in_ptr_excause; | ||
823 | p0.l = _in_ptr_excause; | ||
824 | [p0] = r0; | ||
825 | p0.h = _out_ptr_excause; | ||
826 | p0.l = _out_ptr_excause; | ||
827 | [p0] = r0; | ||
828 | rts; | ||
829 | ENDPROC(_init_exception_buff) | ||
830 | |||
831 | /* We handle this 100% in exception space - to reduce overhead | 786 | /* We handle this 100% in exception space - to reduce overhead |
832 | * Only potiential problem is if the software buffer gets swapped out of the | 787 | * Only potiential problem is if the software buffer gets swapped out of the |
833 | * CPLB table - then double fault. - so we don't let this happen in other places | 788 | * CPLB table - then double fault. - so we don't let this happen in other places |
@@ -1403,17 +1358,7 @@ _exception_stack_top: | |||
1403 | _last_cplb_fault_retx: | 1358 | _last_cplb_fault_retx: |
1404 | .long 0; | 1359 | .long 0; |
1405 | #endif | 1360 | #endif |
1406 | /* | 1361 | /* Used to save the real RETX when temporarily storing a safe |
1407 | * Single instructions can have multiple faults, which need to be | 1362 | * return address. */ |
1408 | * handled by traps.c, in irq5. We store the exception cause to ensure | 1363 | __retx: |
1409 | * we don't miss a double fault condition | ||
1410 | */ | ||
1411 | ENTRY(_in_ptr_excause) | ||
1412 | .long 0; | ||
1413 | ENTRY(_out_ptr_excause) | ||
1414 | .long 0; | 1364 | .long 0; |
1415 | ALIGN | ||
1416 | ENTRY(_excause_circ_buf) | ||
1417 | .rept 4 | ||
1418 | .long 0 | ||
1419 | .endr | ||
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 5448230c0e95..f5fd768022ea 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c | |||
@@ -939,8 +939,6 @@ int __init init_arch_irq(void) | |||
939 | 939 | ||
940 | local_irq_disable(); | 940 | local_irq_disable(); |
941 | 941 | ||
942 | init_exception_buff(); | ||
943 | |||
944 | #ifdef CONFIG_BF54x | 942 | #ifdef CONFIG_BF54x |
945 | # ifdef CONFIG_PINTx_REASSIGN | 943 | # ifdef CONFIG_PINTx_REASSIGN |
946 | pint[0]->assign = CONFIG_PINT0_ASSIGN; | 944 | pint[0]->assign = CONFIG_PINT0_ASSIGN; |