aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin')
-rw-r--r--arch/blackfin/kernel/traps.c15
-rw-r--r--arch/blackfin/mach-common/entry.S121
-rw-r--r--arch/blackfin/mach-common/ints-priority.c2
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
70void *saved_icplb_fault_addr, *saved_dcplb_fault_addr;
71
70int kstack_depth_to_print = 48; 72int kstack_depth_to_print = 48;
71 73
72static void decode_address(char *buf, unsigned long address) 74static 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
56ENTRY(_safe_speculative_execution)
57 NOP;
58 NOP;
59 NOP;
60 jump _safe_speculative_execution;
61ENDPROC(_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)
312ENTRY(_exception_to_level5) 307ENTRY(_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
747ENTRY(_lower_to_irq14) 716ENTRY(_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;
815ENDPROC(_lower_to_irq14) 784ENDPROC(_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 */
820ENTRY(_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;
829ENDPROC(_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 */
1411ENTRY(_in_ptr_excause)
1412 .long 0;
1413ENTRY(_out_ptr_excause)
1414 .long 0; 1364 .long 0;
1415ALIGN
1416ENTRY(_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;