aboutsummaryrefslogtreecommitdiffstats
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 @@
29 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 29 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30 */ 30 */
31 31
32/* 32/* NOTE: This code handles signal-recognition, which happens every time
33 * 25-Dec-2004 - LG Soft India
34 * 1. Fix in return_from_int, to make sure any pending
35 * system call in ILAT for this process to get
36 * executed, otherwise in case context switch happens,
37 * system call of first process (i.e in ILAT) will be
38 * carried forward to the switched process.
39 * 2. Removed Constant references for the following
40 * a. IPEND
41 * b. EXCAUSE mask
42 * c. PAGE Mask
43 */
44
45/*
46 * NOTE: This code handles signal-recognition, which happens every time
47 * after a timer-interrupt and after each system call. 33 * after a timer-interrupt and after each system call.
48 */ 34 */
49 35
@@ -58,6 +44,23 @@
58 44
59#include <asm/mach-common/context.S> 45#include <asm/mach-common/context.S>
60 46
47#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
48# define EX_SCRATCH_REG RETN
49#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
50# define EX_SCRATCH_REG RETE
51#else
52# define EX_SCRATCH_REG CYCLES
53#endif
54
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
61#ifdef CONFIG_EXCPT_IRQ_SYSC_L1 64#ifdef CONFIG_EXCPT_IRQ_SYSC_L1
62.section .l1.text 65.section .l1.text
63#else 66#else
@@ -69,7 +72,7 @@
69 * patch up CPLB misses on the kernel stack. 72 * patch up CPLB misses on the kernel stack.
70 */ 73 */
71ENTRY(_ex_dcplb) 74ENTRY(_ex_dcplb)
72#if defined(ANOMALY_05000261) 75#if ANOMALY_05000261
73 /* 76 /*
74 * Work around an anomaly: if we see a new DCPLB fault, return 77 * Work around an anomaly: if we see a new DCPLB fault, return
75 * without doing anything. Then, if we get the same fault again, 78 * without doing anything. Then, if we get the same fault again,
@@ -93,7 +96,7 @@ ENTRY(_ex_icplb)
93 call __cplb_hdr; 96 call __cplb_hdr;
94 DEBUG_START_HWTRACE(p5, r7) 97 DEBUG_START_HWTRACE(p5, r7)
95 RESTORE_ALL_SYS 98 RESTORE_ALL_SYS
96 SP = RETN; 99 SP = EX_SCRATCH_REG;
97 rtx; 100 rtx;
98ENDPROC(_ex_icplb) 101ENDPROC(_ex_icplb)
99 102
@@ -102,7 +105,7 @@ ENTRY(_ex_syscall)
102 (R7:6,P5:4) = [sp++]; 105 (R7:6,P5:4) = [sp++];
103 ASTAT = [sp++]; 106 ASTAT = [sp++];
104 raise 15; /* invoked by TRAP #0, for sys call */ 107 raise 15; /* invoked by TRAP #0, for sys call */
105 sp = retn; 108 sp = EX_SCRATCH_REG;
106 rtx 109 rtx
107ENDPROC(_ex_syscall) 110ENDPROC(_ex_syscall)
108 111
@@ -135,9 +138,9 @@ ENTRY(_ex_single_step)
135 cc = r6 == r7; 138 cc = r6 == r7;
136 if !cc jump _ex_trap_c; 139 if !cc jump _ex_trap_c;
137 140
138_return_from_exception: 141ENTRY(_return_from_exception)
139 DEBUG_START_HWTRACE(p5, r7) 142 DEBUG_START_HWTRACE(p5, r7)
140#ifdef ANOMALY_05000257 143#if ANOMALY_05000257
141 R7=LC0; 144 R7=LC0;
142 LC0=R7; 145 LC0=R7;
143 R7=LC1; 146 R7=LC1;
@@ -145,7 +148,7 @@ _return_from_exception:
145#endif 148#endif
146 (R7:6,P5:4) = [sp++]; 149 (R7:6,P5:4) = [sp++];
147 ASTAT = [sp++]; 150 ASTAT = [sp++];
148 sp = retn; 151 sp = EX_SCRATCH_REG;
149 rtx; 152 rtx;
150ENDPROC(_ex_soft_bp) 153ENDPROC(_ex_soft_bp)
151 154
@@ -163,7 +166,17 @@ ENTRY(_handle_bad_cplb)
163 [--sp] = ASTAT; 166 [--sp] = ASTAT;
164 [--sp] = (R7:6, P5:4); 167 [--sp] = (R7:6, P5:4);
165 168
169ENTRY(_ex_replaceable)
170 nop;
171
166ENTRY(_ex_trap_c) 172ENTRY(_ex_trap_c)
173 /* Make sure we are not in a double fault */
174 p4.l = lo(IPEND);
175 p4.h = hi(IPEND);
176 r7 = [p4];
177 CC = BITTST (r7, 5);
178 if CC jump _double_fault;
179
167 /* Call C code (trap_c) to handle the exception, which most 180 /* Call C code (trap_c) to handle the exception, which most
168 * likely involves sending a signal to the current process. 181 * likely involves sending a signal to the current process.
169 * To avoid double faults, lower our priority to IRQ5 first. 182 * To avoid double faults, lower our priority to IRQ5 first.
@@ -204,11 +217,57 @@ ENTRY(_ex_trap_c)
204 DEBUG_START_HWTRACE(p5, r7) 217 DEBUG_START_HWTRACE(p5, r7)
205 (R7:6,P5:4) = [sp++]; 218 (R7:6,P5:4) = [sp++];
206 ASTAT = [sp++]; 219 ASTAT = [sp++];
207 SP = RETN; 220 SP = EX_SCRATCH_REG;
208 raise 5; 221 raise 5;
209 rtx; 222 rtx;
210ENDPROC(_ex_trap_c) 223ENDPROC(_ex_trap_c)
211 224
225/* We just realized we got an exception, while we were processing a different
226 * exception. This is a unrecoverable event, so crash
227 */
228ENTRY(_double_fault)
229 /* Turn caches & protection off, to ensure we don't get any more
230 * double exceptions
231 */
232
233 P4.L = LO(IMEM_CONTROL);
234 P4.H = HI(IMEM_CONTROL);
235
236 R5 = [P4]; /* Control Register*/
237 BITCLR(R5,ENICPLB_P);
238 SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
239 .align 8;
240 [P4] = R5;
241 SSYNC;
242
243 P4.L = LO(DMEM_CONTROL);
244 P4.H = HI(DMEM_CONTROL);
245 R5 = [P4];
246 BITCLR(R5,ENDCPLB_P);
247 SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
248 .align 8;
249 [P4] = R5;
250 SSYNC;
251
252 /* Fix up the stack */
253 (R7:6,P5:4) = [sp++];
254 ASTAT = [sp++];
255 SP = EX_SCRATCH_REG;
256
257 /* We should be out of the exception stack, and back down into
258 * kernel or user space stack
259 */
260 SAVE_ALL_SYS
261
262 r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
263 SP += -12;
264 call _double_fault_c;
265 SP += 12;
266.L_double_fault_panic:
267 JUMP .L_double_fault_panic
268
269ENDPROC(_double_fault)
270
212ENTRY(_exception_to_level5) 271ENTRY(_exception_to_level5)
213 SAVE_ALL_SYS 272 SAVE_ALL_SYS
214 273
@@ -279,7 +338,7 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
279 * covered by a CPLB. Switch to an exception stack; use RETN as a 338 * covered by a CPLB. Switch to an exception stack; use RETN as a
280 * scratch register (for want of a better option). 339 * scratch register (for want of a better option).
281 */ 340 */
282 retn = sp; 341 EX_SCRATCH_REG = sp;
283 sp.l = _exception_stack_top; 342 sp.l = _exception_stack_top;
284 sp.h = _exception_stack_top; 343 sp.h = _exception_stack_top;
285 /* Try to deal with syscalls quickly. */ 344 /* Try to deal with syscalls quickly. */
@@ -290,8 +349,8 @@ ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/
290 r6.l = lo(SEQSTAT_EXCAUSE); 349 r6.l = lo(SEQSTAT_EXCAUSE);
291 r6.h = hi(SEQSTAT_EXCAUSE); 350 r6.h = hi(SEQSTAT_EXCAUSE);
292 r7 = r7 & r6; 351 r7 = r7 & r6;
293 p5.h = _extable; 352 p5.h = _ex_table;
294 p5.l = _extable; 353 p5.l = _ex_table;
295 p4 = r7; 354 p4 = r7;
296 p5 = p5 + (p4 << 2); 355 p5 = p5 + (p4 << 2);
297 p4 = [p5]; 356 p4 = [p5];
@@ -634,9 +693,9 @@ ENTRY(_return_from_int)
634 p1.h = _schedule_and_signal_from_int; 693 p1.h = _schedule_and_signal_from_int;
635 [p0] = p1; 694 [p0] = p1;
636 csync; 695 csync;
637#if defined(ANOMALY_05000281) 696#if ANOMALY_05000281
638 r0.l = lo(CONFIG_BOOT_LOAD); 697 r0.l = _safe_speculative_execution;
639 r0.h = hi(CONFIG_BOOT_LOAD); 698 r0.h = _safe_speculative_execution;
640 reti = r0; 699 reti = r0;
641#endif 700#endif
642 r0 = 0x801f (z); 701 r0 = 0x801f (z);
@@ -648,9 +707,9 @@ ENTRY(_return_from_int)
648ENDPROC(_return_from_int) 707ENDPROC(_return_from_int)
649 708
650ENTRY(_lower_to_irq14) 709ENTRY(_lower_to_irq14)
651#if defined(ANOMALY_05000281) 710#if ANOMALY_05000281
652 r0.l = lo(CONFIG_BOOT_LOAD); 711 r0.l = _safe_speculative_execution;
653 r0.h = hi(CONFIG_BOOT_LOAD); 712 r0.h = _safe_speculative_execution;
654 reti = r0; 713 reti = r0;
655#endif 714#endif
656 r0 = 0x401f; 715 r0 = 0x401f;
@@ -731,6 +790,114 @@ ENTRY(_init_exception_buff)
731 rts; 790 rts;
732ENDPROC(_init_exception_buff) 791ENDPROC(_init_exception_buff)
733 792
793/* We handle this 100% in exception space - to reduce overhead
794 * Only potiential problem is if the software buffer gets swapped out of the
795 * CPLB table - then double fault. - so we don't let this happen in other places
796 */
797#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
798ENTRY(_ex_trace_buff_full)
799 [--sp] = P3;
800 [--sp] = P2;
801 [--sp] = LC0;
802 [--sp] = LT0;
803 [--sp] = LB0;
804 P5.L = _trace_buff_offset;
805 P5.H = _trace_buff_offset;
806 P3 = [P5]; /* trace_buff_offset */
807 P5.L = lo(TBUFSTAT);
808 P5.H = hi(TBUFSTAT);
809 R7 = [P5];
810 R7 <<= 1; /* double, since we need to read twice */
811 LC0 = R7;
812 R7 <<= 2; /* need to shift over again,
813 * to get the number of bytes */
814 P5.L = lo(TBUF);
815 P5.H = hi(TBUF);
816 R6 = ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*1024) - 1;
817
818 P2 = R7;
819 P3 = P3 + P2;
820 R7 = P3;
821 R7 = R7 & R6;
822 P3 = R7;
823 P2.L = _trace_buff_offset;
824 P2.H = _trace_buff_offset;
825 [P2] = P3;
826
827 P2.L = _software_trace_buff;
828 P2.H = _software_trace_buff;
829
830 LSETUP (.Lstart, .Lend) LC0;
831.Lstart:
832 R7 = [P5]; /* read TBUF */
833 P4 = P3 + P2;
834 [P4] = R7;
835 P3 += -4;
836 R7 = P3;
837 R7 = R7 & R6;
838.Lend:
839 P3 = R7;
840
841 LB0 = [sp++];
842 LT0 = [sp++];
843 LC0 = [sp++];
844 P2 = [sp++];
845 P3 = [sp++];
846 jump _return_from_exception;
847ENDPROC(_ex_trace_buff_full)
848
849#if CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN == 4
850.data
851#else
852.section .l1.data.B
853#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN */
854ENTRY(_trace_buff_offset)
855 .long 0;
856ALIGN
857ENTRY(_software_trace_buff)
858 .rept ((1 << CONFIG_DEBUG_BFIN_HWTRACE_EXPAND_LEN)*256);
859 .long 0
860 .endr
861#endif /* CONFIG_DEBUG_BFIN_HWTRACE_EXPAND */
862
863#if CONFIG_EARLY_PRINTK
864.section .init.text
865ENTRY(_early_trap)
866 SAVE_ALL_SYS
867 trace_buffer_stop(p0,r0);
868
869 /* Turn caches off, to ensure we don't get double exceptions */
870
871 P4.L = LO(IMEM_CONTROL);
872 P4.H = HI(IMEM_CONTROL);
873
874 R5 = [P4]; /* Control Register*/
875 BITCLR(R5,ENICPLB_P);
876 CLI R1;
877 SSYNC; /* SSYNC required before writing to IMEM_CONTROL. */
878 .align 8;
879 [P4] = R5;
880 SSYNC;
881
882 P4.L = LO(DMEM_CONTROL);
883 P4.H = HI(DMEM_CONTROL);
884 R5 = [P4];
885 BITCLR(R5,ENDCPLB_P);
886 SSYNC; /* SSYNC required before writing to DMEM_CONTROL. */
887 .align 8;
888 [P4] = R5;
889 SSYNC;
890 STI R1;
891
892 r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */
893 r1 = RETX;
894
895 SP += -12;
896 call _early_trap_c;
897 SP += 12;
898ENDPROC(_early_trap)
899#endif /* CONFIG_EARLY_PRINTK */
900
734/* 901/*
735 * Put these in the kernel data section - that should always be covered by 902 * Put these in the kernel data section - that should always be covered by
736 * a CPLB. This is needed to ensure we don't get double fault conditions 903 * a CPLB. This is needed to ensure we don't get double fault conditions
@@ -741,30 +908,33 @@ ENDPROC(_init_exception_buff)
741#else 908#else
742.data 909.data
743#endif 910#endif
744ALIGN 911ENTRY(_ex_table)
745_extable:
746 /* entry for each EXCAUSE[5:0] 912 /* entry for each EXCAUSE[5:0]
747 * This table must be in sync with the table in ./kernel/traps.c 913 * This table must be in sync with the table in ./kernel/traps.c
748 * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined 914 * EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined
749 */ 915 */
750 .long _ex_syscall; /* 0x00 - User Defined - Linux Syscall */ 916 .long _ex_syscall /* 0x00 - User Defined - Linux Syscall */
751 .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */ 917 .long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */
752 .long _ex_trap_c /* 0x02 - User Defined */ 918 .long _ex_replaceable /* 0x02 - User Defined */
753 .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */ 919 .long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */
754 .long _ex_trap_c /* 0x04 - User Defined */ 920 .long _ex_replaceable /* 0x04 - User Defined */
755 .long _ex_trap_c /* 0x05 - User Defined */ 921 .long _ex_replaceable /* 0x05 - User Defined */
756 .long _ex_trap_c /* 0x06 - User Defined */ 922 .long _ex_replaceable /* 0x06 - User Defined */
757 .long _ex_trap_c /* 0x07 - User Defined */ 923 .long _ex_replaceable /* 0x07 - User Defined */
758 .long _ex_trap_c /* 0x08 - User Defined */ 924 .long _ex_replaceable /* 0x08 - User Defined */
759 .long _ex_trap_c /* 0x09 - User Defined */ 925 .long _ex_replaceable /* 0x09 - User Defined */
760 .long _ex_trap_c /* 0x0A - User Defined */ 926 .long _ex_replaceable /* 0x0A - User Defined */
761 .long _ex_trap_c /* 0x0B - User Defined */ 927 .long _ex_replaceable /* 0x0B - User Defined */
762 .long _ex_trap_c /* 0x0C - User Defined */ 928 .long _ex_replaceable /* 0x0C - User Defined */
763 .long _ex_trap_c /* 0x0D - User Defined */ 929 .long _ex_replaceable /* 0x0D - User Defined */
764 .long _ex_trap_c /* 0x0E - User Defined */ 930 .long _ex_replaceable /* 0x0E - User Defined */
765 .long _ex_trap_c /* 0x0F - User Defined */ 931 .long _ex_replaceable /* 0x0F - User Defined */
766 .long _ex_single_step /* 0x10 - HW Single step */ 932 .long _ex_single_step /* 0x10 - HW Single step */
933#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND
934 .long _ex_trace_buff_full /* 0x11 - Trace Buffer Full */
935#else
767 .long _ex_trap_c /* 0x11 - Trace Buffer Full */ 936 .long _ex_trap_c /* 0x11 - Trace Buffer Full */
937#endif
768 .long _ex_trap_c /* 0x12 - Reserved */ 938 .long _ex_trap_c /* 0x12 - Reserved */
769 .long _ex_trap_c /* 0x13 - Reserved */ 939 .long _ex_trap_c /* 0x13 - Reserved */
770 .long _ex_trap_c /* 0x14 - Reserved */ 940 .long _ex_trap_c /* 0x14 - Reserved */
@@ -812,8 +982,8 @@ _extable:
812 .long _ex_trap_c /* 0x3D - Reserved */ 982 .long _ex_trap_c /* 0x3D - Reserved */
813 .long _ex_trap_c /* 0x3E - Reserved */ 983 .long _ex_trap_c /* 0x3E - Reserved */
814 .long _ex_trap_c /* 0x3F - Reserved */ 984 .long _ex_trap_c /* 0x3F - Reserved */
985END(_ex_table)
815 986
816ALIGN
817ENTRY(_sys_call_table) 987ENTRY(_sys_call_table)
818 .long _sys_restart_syscall /* 0 */ 988 .long _sys_restart_syscall /* 0 */
819 .long _sys_exit 989 .long _sys_exit
@@ -1184,7 +1354,7 @@ _exception_stack:
1184 .endr 1354 .endr
1185_exception_stack_top: 1355_exception_stack_top:
1186 1356
1187#if defined(ANOMALY_05000261) 1357#if ANOMALY_05000261
1188/* Used by the assembly entry point to work around an anomaly. */ 1358/* Used by the assembly entry point to work around an anomaly. */
1189_last_cplb_fault_retx: 1359_last_cplb_fault_retx:
1190 .long 0; 1360 .long 0;