diff options
Diffstat (limited to 'arch/blackfin/mach-common/entry.S')
-rw-r--r-- | arch/blackfin/mach-common/entry.S | 268 |
1 files changed, 219 insertions, 49 deletions
diff --git a/arch/blackfin/mach-common/entry.S b/arch/blackfin/mach-common/entry.S index 9604588..e3ad580 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; |