aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin
diff options
context:
space:
mode:
authorBernd Schmidt <bernds_cb1@t-online.de>2008-04-24 17:02:33 -0400
committerBryan Wu <cooloney@kernel.org>2008-04-24 17:02:33 -0400
commit5d750b9e4f6ca7d366b4954517ff8be9ee07e1bf (patch)
tree39d05886fdb19f87e77b371688c133b67106931a /arch/blackfin
parent00d205a1ce1a24a1a9d9ebfbddbae56021cba826 (diff)
[Blackfin] arch: Remove the circular buffering mechanism for exceptions
Remove the circular buffering mechanism for exceptions. Instead, point RETX at a safe location from which to fetch three NOPs. This safe location is now in the fixed code area, and also used for certain anomaly workarounds, to ensure that user space can find a valid ICPLB when things are built with CONFIG_MPU. Also, save I/DCPLB_FAULT_ADDRESS when lowering to level 5, since the hardware reg is valid only at exception level. Signed-off-by: Bernd Schmidt <bernds_cb1@t-online.de> Signed-off-by: Bryan Wu <cooloney@kernel.org>
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;