summaryrefslogtreecommitdiffstats
path: root/arch/blackfin/mach-common/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
-rw-r--r--arch/blackfin/mach-common/entry.S268
1 files changed, 219 insertions, 49 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S
index 960458808344..e3ad5802868a 100644
--- a/arch/blackfin/mach-common/entry.S
+++ b/arch/blackfin/mach-common/entry.S
@@ -29,21 +29,7 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/*
- * 25-Dec-2004 - LG Soft India
- * 1. Fix in return_from_int, to make sure any pending
- * system call in ILAT for this process to get
- * executed, otherwise in case context switch happens,
- * system call of first process (i.e in ILAT) will be
- * carried forward to the switched process.
- * 2. Removed Constant references for the following
- * a. IPEND
- * b. EXCAUSE mask
- * c. PAGE Mask
- */
-
-/*
- * NOTE: This code handles signal-recognition, which happens every time
+/* NOTE: This code handles signal-recognition, which happens every time
* after a timer-interrupt and after each system call.
*/
@@ -58,6 +44,23 @@
#include <asm/mach-common/context.S>
+#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
+# define EX_SCRATCH_REG RETN
+#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
+# define EX_SCRATCH_REG RETE
+#else
+# 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
@@ -69,7 +72,7 @@
* patch up CPLB misses on the kernel stack.
*/
ENTRY(_ex_dcplb)
-#if defined(ANOMALY_05000261)
+#if ANOMALY_05000261
/*
* Work around an anomaly: if we see a new DCPLB fault, return
* without doing anything. Then, if we get the same fault again,
@@ -93,7 +96,7 @@ ENTRY(_ex_icplb)
call __cplb_hdr;
DEBUG_START_HWTRACE(p5, r7)
RESTORE_ALL_SYS
- SP = RETN;
+ SP = EX_SCRATCH_REG;
rtx;
ENDPROC(_ex_icplb)
@@ -102,7 +105,7 @@ ENTRY(_ex_syscall)
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
raise 15; /* invoked by TRAP #0, for sys call */
- sp = retn;
+ sp = EX_SCRATCH_REG;
rtx
ENDPROC(_ex_syscall)
@@ -135,9 +138,9 @@ ENTRY(_ex_single_step)
cc = r6 == r7;
if !cc jump _ex_trap_c;
-_return_from_exception:
+ENTRY(_return_from_exception)
DEBUG_START_HWTRACE(p5, r7)
-#ifdef ANOMALY_05000257
+#if ANOMALY_05000257
R7=LC0;
LC0=R7;
R7=LC1;
@@ -145,7 +148,7 @@ _return_from_exception:
#endif
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
- sp = retn;
+ sp = EX_SCRATCH_REG;
rtx;
ENDPROC(_ex_soft_bp)
@@ -163,7 +166,17 @@ ENTRY(_handle_bad_cplb)
[--sp] = ASTAT;
[--sp] = (R7:6, P5:4);
+ENTRY(_ex_replaceable)
+ nop;
+
ENTRY(_ex_trap_c)
+ /* Make sure we are not in a double fault */
+ p4.l = lo(IPEND);
+ p4.h = hi(IPEND);
+ r7 = [p4];
+ CC = BITTST (r7, 5);
+ if CC jump _double_fault;
+
/* Call C code (trap_c) to handle the exception, which most
* likely involves sending a signal to the current process.
* To avoid double faults, lower our priority to IRQ5 first.
@@ -204,11 +217,57 @@ ENTRY(_ex_trap_c)
DEBUG_START_HWTRACE(p5, r7)
(R7:6,P5:4) = [sp++];
ASTAT = [sp++];
- SP = RETN;
+ SP = EX_SCRATCH_REG;
raise 5;
rtx;
ENDPROC(_ex_trap_c)
+/* We just realized we got an exception, while we were processing a different
+ * exception. This is a unrecoverable event, so crash
+ */
+ENTRY(_double_fault)
+ /* Turn caches & protection off, to ensure we don't get any more
+ * double exceptions
+ */
+
+ P4.L = LO(IMEM_CONTROL);
+ P4.H = HI(IMEM_CONTROL);
+
+ R5 = [P4]; /* Control Register*/
+ BITCLR(R5,ENICPLB_P);
+ SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
+ .align 8;
+ [P4] = R5;
+ SSYNC;
+
+ P4.L = LO(DMEM_CONTROL);
+ P4.H = HI(DMEM_CONTROL);
+ R5 = [P4];
+ BITCLR(R5,ENDCPLB_P);
+ SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
+ .align 8;
+ [P4] = R5;
+ SSYNC;
+
+ /* Fix up the stack */
+ (R7:6,P5:4) = [sp++];
+ ASTAT = [sp++];
+ SP = EX_SCRATCH_REG;
+
+ /* We should be out of the exception stack, and back down into
+ * kernel or user space stack
+ */
+ SAVE_ALL_SYS
+
+ r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
+ SP += -12;
+ call _double_fault_c;
+ SP += 12;
+.L_double_fault_panic:
+ JUMP .L_double_fault_panic
+
+ENDPROC(_double_fault)
+
ENTRY(_exception_to_level5)
SAVE_ALL_SYS
@@ -279,7 +338,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
* covered by a CPLB. Switch to an exception stack; use RETN as a
* scratch register (for want of a better option).
*/
- retn = sp;
+ EX_SCRATCH_REG = sp;
sp.l = _exception_stack_top;
sp.h = _exception_stack_top;
/* Try to deal with syscalls quickly. */
@@ -290,8 +349,8 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
r6.l = lo(SEQSTAT_EXCAUSE);
r6.h = hi(SEQSTAT_EXCAUSE);
r7 = r7 & r6;
- p5.h = _extable;
- p5.l = _extable;
+ p5.h = _ex_table;
+ p5.l = _ex_table;
p4 = r7;
p5 = p5 + (p4 << 2);
p4 = [p5];
@@ -634,9 +693,9 @@ ENTRY(_return_from_int)
p1.h = _schedule_and_signal_from_int;
[p0] = p1;
csync;
-#if defined(ANOMALY_05000281)
- r0.l = lo(CONFIG_BOOT_LOAD);
- r0.h = hi(CONFIG_BOOT_LOAD);
+#if ANOMALY_05000281
+ r0.l = _safe_speculative_execution;
+ r0.h = _safe_speculative_execution;
reti = r0;
#endif
r0 = 0x801f (z);
@@ -648,9 +707,9 @@ ENTRY(_return_from_int)
ENDPROC(_return_from_int)
ENTRY(_lower_to_irq14)
-#if defined(ANOMALY_05000281)
- r0.l = lo(CONFIG_BOOT_LOAD);
- r0.h = hi(CONFIG_BOOT_LOAD);
+#if ANOMALY_05000281
+ r0.l = _safe_speculative_execution;
+ r0.h = _safe_speculative_execution;
reti = r0;
#endif
r0 = 0x401f;
@@ -731,6 +790,114 @@ ENTRY(_init_exception_buff)
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
+ */
+#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
+ENTRY(_ex_trace_buff_full)
+ [--sp] = P3;
+ [--sp] = P2;
+ [--sp] = LC0;
+ [--sp] = LT0;
+ [--sp] = LB0;
+ P5.L = _trace_buff_offset;
+ P5.H = _trace_buff_offset;
+ P3 = [P5]; /* trace_buff_offset */
+ P5.L = lo(TBUFSTAT);
+ P5.H = hi(TBUFSTAT);
+ R7 = [P5];
+ R7 <<= 1; /* double, since we need to read twice */
+ LC0 = R7;
+ R7 <<= 2; /* need to shift over again,
+ * to get the number of bytes */
+ P5.L = lo(TBUF);
+ P5.H = hi(TBUF);
+ R6 = ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*1024) - 1;
+
+ P2 = R7;
+ P3 = P3 + P2;
+ R7 = P3;
+ R7 = R7 & R6;
+ P3 = R7;
+ P2.L = _trace_buff_offset;
+ P2.H = _trace_buff_offset;
+ [P2] = P3;
+
+ P2.L = _software_trace_buff;
+ P2.H = _software_trace_buff;
+
+ LSETUP (.Lstart, .Lend) LC0;
+.Lstart:
+ R7 = [P5]; /* read TBUF */
+ P4 = P3 + P2;
+ [P4] = R7;
+ P3 += -4;
+ R7 = P3;
+ R7 = R7 & R6;
+.Lend:
+ P3 = R7;
+
+ LB0 = [sp++];
+ LT0 = [sp++];
+ LC0 = [sp++];
+ P2 = [sp++];
+ P3 = [sp++];
+ jump _return_from_exception;
+ENDPROC(_ex_trace_buff_full)
+
+#if CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN == 4
+.data
+#else
+.section .l1.data.B
+#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN */
+ENTRY(_trace_buff_offset)
+ .long 0;
+ALIGN
+ENTRY(_software_trace_buff)
+ .rept ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*256);
+ .long 0
+ .endr
+#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND */
+
+#if CONFIG_EARLY_PRINTK
+.section .init.text
+ENTRY(_early_trap)
+ SAVE_ALL_SYS
+ trace_buffer_stop(p0,r0);
+
+ /* Turn caches off, to ensure we don't get double exceptions */
+
+ P4.L = LO(IMEM_CONTROL);
+ P4.H = HI(IMEM_CONTROL);
+
+ R5 = [P4]; /* Control Register*/
+ BITCLR(R5,ENICPLB_P);
+ CLI R1;
+ SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
+ .align 8;
+ [P4] = R5;
+ SSYNC;
+
+ P4.L = LO(DMEM_CONTROL);
+ P4.H = HI(DMEM_CONTROL);
+ R5 = [P4];
+ BITCLR(R5,ENDCPLB_P);
+ SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
+ .align 8;
+ [P4] = R5;
+ SSYNC;
+ STI R1;
+
+ r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
+ r1 = RETX;
+
+ SP += -12;
+ call _early_trap_c;
+ SP += 12;
+ENDPROC(_early_trap)
+#endif /* CONFIG_EARLY_PRINTK */
+
/*
* Put these in the kernel data section - that should always be covered by
* a CPLB. This is needed to ensure we don't get double fault conditions
@@ -741,30 +908,33 @@ ENDPROC(_init_exception_buff)
#else
.data
#endif
-ALIGN
-_extable:
+ENTRY(_ex_table)
/* entry for each EXCAUSE[5:0]
* This table must be in sync with the table in ./kernel/traps.c
* EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
*/
- .long _ex_syscall; /* 0x00 - User Defined - Linux Syscall */
+ .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */
.long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */
- .long _ex_trap_c /* 0x02 - User Defined */
+ .long _ex_replaceable /* 0x02 - User Defined */
.long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */
- .long _ex_trap_c /* 0x04 - User Defined */
- .long _ex_trap_c /* 0x05 - User Defined */
- .long _ex_trap_c /* 0x06 - User Defined */
- .long _ex_trap_c /* 0x07 - User Defined */
- .long _ex_trap_c /* 0x08 - User Defined */
- .long _ex_trap_c /* 0x09 - User Defined */
- .long _ex_trap_c /* 0x0A - User Defined */
- .long _ex_trap_c /* 0x0B - User Defined */
- .long _ex_trap_c /* 0x0C - User Defined */
- .long _ex_trap_c /* 0x0D - User Defined */
- .long _ex_trap_c /* 0x0E - User Defined */
- .long _ex_trap_c /* 0x0F - User Defined */
+ .long _ex_replaceable /* 0x04 - User Defined */
+ .long _ex_replaceable /* 0x05 - User Defined */
+ .long _ex_replaceable /* 0x06 - User Defined */
+ .long _ex_replaceable /* 0x07 - User Defined */
+ .long _ex_replaceable /* 0x08 - User Defined */
+ .long _ex_replaceable /* 0x09 - User Defined */
+ .long _ex_replaceable /* 0x0A - User Defined */
+ .long _ex_replaceable /* 0x0B - User Defined */
+ .long _ex_replaceable /* 0x0C - User Defined */
+ .long _ex_replaceable /* 0x0D - User Defined */
+ .long _ex_replaceable /* 0x0E - User Defined */
+ .long _ex_replaceable /* 0x0F - User Defined */
.long _ex_single_step /* 0x10 - HW Single step */
+#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
+ .long _ex_trace_buff_full /* 0x11 - Trace Buffer Full */
+#else
.long _ex_trap_c /* 0x11 - Trace Buffer Full */
+#endif
.long _ex_trap_c /* 0x12 - Reserved */
.long _ex_trap_c /* 0x13 - Reserved */
.long _ex_trap_c /* 0x14 - Reserved */
@@ -812,8 +982,8 @@ _extable:
.long _ex_trap_c /* 0x3D - Reserved */
.long _ex_trap_c /* 0x3E - Reserved */
.long _ex_trap_c /* 0x3F - Reserved */
+END(_ex_table)
-ALIGN
ENTRY(_sys_call_table)
.long _sys_restart_syscall /* 0 */
.long _sys_exit
@@ -1184,7 +1354,7 @@ _exception_stack:
.endr
_exception_stack_top:
-#if defined(ANOMALY_05000261)
+#if ANOMALY_05000261
/* Used by the assembly entry point to work around an anomaly. */
_last_cplb_fault_retx:
.long 0;