aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common
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/mach-common
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/mach-common')
-rw-r--r--arch/blackfin/mach-common/entry.S121
-rw-r--r--arch/blackfin/mach-common/ints-priority.c2
2 files changed, 33 insertions, 90 deletions
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;