summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 d0f67542207..5b847070dae 100644
--- a/arch/blackfin/kernel/traps.c
+++ b/arch/blackfin/kernel/traps.c
@@ -67,6 +67,8 @@ void __init trap_init(void)
CSYNC();
}
+void *saved_icplb_fault_addr, *saved_dcplb_fault_addr;
+
int kstack_depth_to_print = 48;
static void decode_address(char *buf, unsigned long address)
@@ -703,10 +705,7 @@ void dump_bfin_mem(struct pt_regs *fp)
unsigned short *addr, *erraddr, val = 0, err = 0;
char sti = 0, buf[6];
- if (unlikely((fp->seqstat & SEQSTAT_EXCAUSE) == VEC_HWERR))
- erraddr = (void *)fp->pc;
- else
- erraddr = (void *)fp->retx;
+ erraddr = (void *)fp->pc;
printk(KERN_NOTICE "return address: [0x%p]; contents of:", erraddr);
@@ -830,9 +829,9 @@ unlock:
if (((long)fp->seqstat & SEQSTAT_EXCAUSE) &&
(((long)fp->seqstat & SEQSTAT_EXCAUSE) != VEC_HWERR)) {
- decode_address(buf, bfin_read_DCPLB_FAULT_ADDR());
+ decode_address(buf, saved_dcplb_fault_addr);
printk(KERN_NOTICE "DCPLB_FAULT_ADDR: %s\n", buf);
- decode_address(buf, bfin_read_ICPLB_FAULT_ADDR());
+ decode_address(buf, saved_icplb_fault_addr);
printk(KERN_NOTICE "ICPLB_FAULT_ADDR: %s\n", buf);
}
@@ -940,8 +939,8 @@ void panic_cplb_error(int cplb_panic, struct pt_regs *fp)
oops_in_progress = 1;
- printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", (void *)bfin_read_DCPLB_FAULT_ADDR());
- printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", (void *)bfin_read_ICPLB_FAULT_ADDR());
+ printk(KERN_EMERG "DCPLB_FAULT_ADDR=%p\n", saved_dcplb_fault_addr);
+ printk(KERN_EMERG "ICPLB_FAULT_ADDR=%p\n", saved_icplb_fault_addr);
dump_bfin_process(fp);
dump_bfin_mem(fp);
show_regs(fp);
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index a504c65d999..f2fb87e9a46 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -38,6 +38,7 @@
#include <linux/unistd.h>
#include <asm/blackfin.h>
#include <asm/errno.h>
+#include <asm/fixed_code.h>
#include <asm/thread_info.h> /* TIF_NEED_RESCHED */
#include <asm/asm-offsets.h>
#include <asm/trace.h>
@@ -52,15 +53,6 @@
# define EX_SCRATCH_REG CYCLES
#endif
-#if ANOMALY_05000281
-ENTRY(_safe_speculative_execution)
- NOP;
- NOP;
- NOP;
- jump _safe_speculative_execution;
-ENDPROC(_safe_speculative_execution)
-#endif
-
#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
.section .l1.text
#else
@@ -230,6 +222,26 @@ ENTRY(_ex_trap_c)
[p4] = p5;
csync;
+ p4.l = lo(DCPLB_FAULT_ADDR);
+ p4.h = hi(DCPLB_FAULT_ADDR);
+ r7 = [p4];
+ p5.h = _saved_dcplb_fault_addr;
+ p5.l = _saved_dcplb_fault_addr;
+ [p5] = r7;
+
+ r7 = [p4 + (ICPLB_FAULT_ADDR - DCPLB_FAULT_ADDR)];
+ p5.h = _saved_icplb_fault_addr;
+ p5.l = _saved_icplb_fault_addr;
+ [p5] = r7;
+
+ p4.l = __retx;
+ p4.h = __retx;
+ r6 = retx;
+ [p4] = r6;
+ p4.l = lo(SAFE_USER_INSTRUCTION);
+ p4.h = hi(SAFE_USER_INSTRUCTION);
+ retx = p4;
+
/* Disable all interrupts, but make sure level 5 is enabled so
* we can switch to that level. Save the old mask. */
cli r6;
@@ -239,23 +251,6 @@ ENTRY(_ex_trap_c)
r6 = 0x3f;
sti r6;
- /* Save the excause into a circular buffer, in case the instruction
- * which caused this excecptions causes others.
- */
- P5.l = _in_ptr_excause;
- P5.h = _in_ptr_excause;
- R7 = [P5];
- R7 += 4;
- R6 = 0xF;
- R7 = R7 & R6;
- [P5] = R7;
- R6.l = _excause_circ_buf;
- R6.h = _excause_circ_buf;
- R7 = R7 + R6;
- p5 = R7;
- R6 = SEQSTAT;
- [P5] = R6;
-
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
SP = EX_SCRATCH_REG;
@@ -312,6 +307,11 @@ ENDPROC(_double_fault)
ENTRY(_exception_to_level5)
SAVE_ALL_SYS
+ p4.l = __retx;
+ p4.h = __retx;
+ r6 = [p4];
+ [sp + PT_PC] = r6;
+
/* Restore interrupt mask. We haven't pushed RETI, so this
* doesn't enable interrupts until we return from this handler. */
p4.l = _excpt_saved_imask;
@@ -333,42 +333,11 @@ ENTRY(_exception_to_level5)
r0 = [p2]; /* Read current IPEND */
[sp + PT_IPEND] = r0; /* Store IPEND */
- /* Pop the excause from the circular buffer and push it on the stack
- * (in the right place - if you change the location of SEQSTAT, you
- * must change this offset.
- */
-.L_excep_to_5_again:
- P5.l = _out_ptr_excause;
- P5.h = _out_ptr_excause;
- R7 = [P5];
- R7 += 4;
- R6 = 0xF;
- R7 = R7 & R6;
- [P5] = R7;
- R6.l = _excause_circ_buf;
- R6.h = _excause_circ_buf;
- R7 = R7 + R6;
- P5 = R7;
- R1 = [P5];
- [SP + PT_SEQSTAT] = r1;
-
r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
SP += -12;
call _trap_c;
SP += 12;
- /* See if anything else is in the exception buffer
- * if there is, process it
- */
- P5.l = _out_ptr_excause;
- P5.h = _out_ptr_excause;
- P4.l = _in_ptr_excause;
- P4.h = _in_ptr_excause;
- R6 = [P5];
- R7 = [P4];
- CC = R6 == R7;
- if ! CC JUMP .L_excep_to_5_again
-
call _ret_from_exception;
RESTORE_ALL_SYS
rti;
@@ -732,8 +701,8 @@ ENTRY(_return_from_int)
[p0] = p1;
csync;
#if ANOMALY_05000281
- r0.l = _safe_speculative_execution;
- r0.h = _safe_speculative_execution;
+ r0.l = lo(SAFE_USER_INSTRUCTION);
+ r0.h = hi(SAFE_USER_INSTRUCTION);
reti = r0;
#endif
r0 = 0x801f (z);
@@ -746,8 +715,8 @@ ENDPROC(_return_from_int)
ENTRY(_lower_to_irq14)
#if ANOMALY_05000281
- r0.l = _safe_speculative_execution;
- r0.h = _safe_speculative_execution;
+ r0.l = lo(SAFE_USER_INSTRUCTION);
+ r0.h = hi(SAFE_USER_INSTRUCTION);
reti = r0;
#endif
r0 = 0x401f;
@@ -814,20 +783,6 @@ _schedule_and_signal:
rti;
ENDPROC(_lower_to_irq14)
-/* Make sure when we start, that the circular buffer is initialized properly
- * R0 and P0 are call clobbered, so we can use them here.
- */
-ENTRY(_init_exception_buff)
- r0 = 0;
- p0.h = _in_ptr_excause;
- p0.l = _in_ptr_excause;
- [p0] = r0;
- p0.h = _out_ptr_excause;
- p0.l = _out_ptr_excause;
- [p0] = r0;
- rts;
-ENDPROC(_init_exception_buff)
-
/* We handle this 100% in exception space - to reduce overhead
* Only potiential problem is if the software buffer gets swapped out of the
* CPLB table - then double fault. - so we don't let this happen in other places
@@ -1403,17 +1358,7 @@ _exception_stack_top:
_last_cplb_fault_retx:
.long 0;
#endif
-/*
- * Single instructions can have multiple faults, which need to be
- * handled by traps.c, in irq5. We store the exception cause to ensure
- * we don't miss a double fault condition
- */
-ENTRY(_in_ptr_excause)
- .long 0;
-ENTRY(_out_ptr_excause)
+ /* Used to save the real RETX when temporarily storing a safe
+ * return address. */
+__retx:
.long 0;
-ALIGN
-ENTRY(_excause_circ_buf)
- .rept 4
- .long 0
- .endr
diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c
index 5448230c0e9..f5fd768022e 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)
local_irq_disable();
- init_exception_buff();
-
#ifdef CONFIG_BF54x
# ifdef CONFIG_PINTx_REASSIGN
pint[0]->assign = CONFIG_PINT0_ASSIGN;