diff options
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 59 |
1 files changed, 41 insertions, 18 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index f0636fdcb353..da0558ad1b1a 100644 --- a/arch/blackfin/mach-common/entry.S +++ b/arch/blackfin/mach-common/entry.S @@ -200,7 +200,18 @@ ENTRY(_ex_single_step) cc = r7 == 0; if !cc jump 1f; #endif - +#ifdef CONFIG_EXACT_HWERR + /* Read the ILAT, and to check to see if the process we are + * single stepping caused a previous hardware error + * If so, do not single step, (which lowers to IRQ5, and makes + * us miss the error). + */ + p5.l = lo(ILAT); + p5.h = hi(ILAT); + r7 = [p5]; + cc = bittst(r7, EVT_IVHW_P); + if cc jump 1f; +#endif /* Single stepping only a single instruction, so clear the trace * bit here. */ r7 = syscfg; @@ -262,15 +273,6 @@ ENTRY(_bfin_return_from_exception) r6 = 0x25; CC = R7 == R6; if CC JUMP _double_fault; - - /* Did we cause a HW error? */ - p5.l = lo(ILAT); - p5.h = hi(ILAT); - r6 = [p5]; - r7 = 0x20; /* Did I just cause anther HW error? */ - r6 = r7 & r6; - CC = R7 == R6; - if CC JUMP _double_fault; #endif (R7:6,P5:4) = [sp++]; @@ -472,6 +474,16 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/ [--sp] = ASTAT; [--sp] = (R7:6,P5:4); +#ifdef CONFIG_EXACT_HWERR + /* Make sure all pending read/writes complete. This will ensure any + * accesses which could cause hardware errors completes, and signal + * the the hardware before we do something silly, like crash the + * kernel. We don't need to work around anomaly 05000312, since + * we are already atomic + */ + ssync; +#endif + #if ANOMALY_05000283 || ANOMALY_05000315 cc = r7 == r7; p5.h = HI(CHIPID); @@ -854,7 +866,7 @@ ENTRY(_ret_from_exception) p1.h = _schedule_and_signal; [p0] = p1; csync; - raise 15; /* raise evt14 to do signal or reschedule */ + raise 15; /* raise evt15 to do signal or reschedule */ 4: r0 = syscfg; bitclr(r0, 0); @@ -915,7 +927,7 @@ ENTRY(_return_from_int) p1.h = _schedule_and_signal_from_int; [p0] = p1; csync; -#if ANOMALY_05000281 +#if ANOMALY_05000281 || ANOMALY_05000461 r0.l = lo(SAFE_USER_INSTRUCTION); r0.h = hi(SAFE_USER_INSTRUCTION); reti = r0; @@ -929,18 +941,27 @@ ENTRY(_return_from_int) ENDPROC(_return_from_int) ENTRY(_lower_to_irq14) -#if ANOMALY_05000281 +#if ANOMALY_05000281 || ANOMALY_05000461 r0.l = lo(SAFE_USER_INSTRUCTION); r0.h = hi(SAFE_USER_INSTRUCTION); reti = r0; #endif - r0 = 0x401f; + +#ifdef CONFIG_DEBUG_HWERR + /* enable irq14 & hwerr interrupt, until we transition to _evt14_softirq */ + r0 = (EVT_IVG14 | EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); +#else + /* Only enable irq14 interrupt, until we transition to _evt14_softirq */ + r0 = (EVT_IVG14 | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); +#endif sti r0; raise 14; rti; +ENDPROC(_lower_to_irq14) + ENTRY(_evt14_softirq) #ifdef CONFIG_DEBUG_HWERR - r0 = 0x3f; + r0 = (EVT_IVHW | EVT_IRPTEN | EVT_EVX | EVT_NMI | EVT_RST | EVT_EMU); sti r0; #else cli r0; @@ -948,8 +969,9 @@ ENTRY(_evt14_softirq) [--sp] = RETI; SP += 4; rts; +ENDPROC(_evt14_softirq) -_schedule_and_signal_from_int: +ENTRY(_schedule_and_signal_from_int) /* To end up here, vector 15 was changed - so we have to change it * back. */ @@ -982,8 +1004,9 @@ _schedule_and_signal_from_int: call _finish_atomic_sections; sp += 12; jump.s .Lresume_userspace; +ENDPROC(_schedule_and_signal_from_int) -_schedule_and_signal: +ENTRY(_schedule_and_signal) SAVE_CONTEXT_SYSCALL /* To end up here, vector 15 was changed - so we have to change it * back. @@ -1001,7 +1024,7 @@ _schedule_and_signal: 1: RESTORE_CONTEXT rti; -ENDPROC(_lower_to_irq14) +ENDPROC(_schedule_and_signal) /* We handle this 100% in exception space - to reduce overhead * Only potiential problem is if the software buffer gets swapped out of the |