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 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 | ||
56 | ENTRY(_safe_speculative_execution) | ||
57 | NOP; | ||
58 | NOP; | ||
59 | NOP; | ||
60 | jump _safe_speculative_execution; | ||
61 | ENDPROC(_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 | */ |
71 | ENTRY(_ex_dcplb) | 74 | ENTRY(_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; |
98 | ENDPROC(_ex_icplb) | 101 | ENDPROC(_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 |
107 | ENDPROC(_ex_syscall) | 110 | ENDPROC(_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: | 141 | ENTRY(_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; |
150 | ENDPROC(_ex_soft_bp) | 153 | ENDPROC(_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 | ||
169 | ENTRY(_ex_replaceable) | ||
170 | nop; | ||
171 | |||
166 | ENTRY(_ex_trap_c) | 172 | ENTRY(_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; |
210 | ENDPROC(_ex_trap_c) | 223 | ENDPROC(_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 | */ | ||
228 | ENTRY(_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 | |||
269 | ENDPROC(_double_fault) | ||
270 | |||
212 | ENTRY(_exception_to_level5) | 271 | ENTRY(_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) | |||
648 | ENDPROC(_return_from_int) | 707 | ENDPROC(_return_from_int) |
649 | 708 | ||
650 | ENTRY(_lower_to_irq14) | 709 | ENTRY(_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; |
732 | ENDPROC(_init_exception_buff) | 791 | ENDPROC(_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 | ||
798 | ENTRY(_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; | ||
847 | ENDPROC(_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 */ | ||
854 | ENTRY(_trace_buff_offset) | ||
855 | .long 0; | ||
856 | ALIGN | ||
857 | ENTRY(_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 | ||
865 | ENTRY(_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; | ||
898 | ENDPROC(_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 |
744 | ALIGN | 911 | ENTRY(_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 */ |
985 | END(_ex_table) | ||
815 | 986 | ||
816 | ALIGN | ||
817 | ENTRY(_sys_call_table) | 987 | ENTRY(_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; |