diff options
Diffstat (limited to 'arch/mips/kernel/genex.S')
-rw-r--r-- | arch/mips/kernel/genex.S | 302 |
1 files changed, 302 insertions, 0 deletions
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S new file mode 100644 index 000000000000..a5b0a389b063 --- /dev/null +++ b/arch/mips/kernel/genex.S | |||
@@ -0,0 +1,302 @@ | |||
1 | /* | ||
2 | * This file is subject to the terms and conditions of the GNU General Public | ||
3 | * License. See the file "COPYING" in the main directory of this archive | ||
4 | * for more details. | ||
5 | * | ||
6 | * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle | ||
7 | * Copyright (C) 1999, 2000 Silicon Graphics, Inc. | ||
8 | * Copyright (C) 2001 MIPS Technologies, Inc. | ||
9 | * Copyright (C) 2002 Maciej W. Rozycki | ||
10 | */ | ||
11 | #include <linux/config.h> | ||
12 | #include <linux/init.h> | ||
13 | |||
14 | #include <asm/asm.h> | ||
15 | #include <asm/cacheops.h> | ||
16 | #include <asm/regdef.h> | ||
17 | #include <asm/fpregdef.h> | ||
18 | #include <asm/mipsregs.h> | ||
19 | #include <asm/stackframe.h> | ||
20 | #include <asm/war.h> | ||
21 | |||
22 | #define PANIC_PIC(msg) \ | ||
23 | .set push; \ | ||
24 | .set reorder; \ | ||
25 | PTR_LA a0,8f; \ | ||
26 | .set noat; \ | ||
27 | PTR_LA AT, panic; \ | ||
28 | jr AT; \ | ||
29 | 9: b 9b; \ | ||
30 | .set pop; \ | ||
31 | TEXT(msg) | ||
32 | |||
33 | __INIT | ||
34 | |||
35 | NESTED(except_vec0_generic, 0, sp) | ||
36 | PANIC_PIC("Exception vector 0 called") | ||
37 | END(except_vec0_generic) | ||
38 | |||
39 | NESTED(except_vec1_generic, 0, sp) | ||
40 | PANIC_PIC("Exception vector 1 called") | ||
41 | END(except_vec1_generic) | ||
42 | |||
43 | /* | ||
44 | * General exception vector for all other CPUs. | ||
45 | * | ||
46 | * Be careful when changing this, it has to be at most 128 bytes | ||
47 | * to fit into space reserved for the exception handler. | ||
48 | */ | ||
49 | NESTED(except_vec3_generic, 0, sp) | ||
50 | .set push | ||
51 | .set noat | ||
52 | #if R5432_CP0_INTERRUPT_WAR | ||
53 | mfc0 k0, CP0_INDEX | ||
54 | #endif | ||
55 | mfc0 k1, CP0_CAUSE | ||
56 | andi k1, k1, 0x7c | ||
57 | #ifdef CONFIG_MIPS64 | ||
58 | dsll k1, k1, 1 | ||
59 | #endif | ||
60 | PTR_L k0, exception_handlers(k1) | ||
61 | jr k0 | ||
62 | .set pop | ||
63 | END(except_vec3_generic) | ||
64 | |||
65 | /* | ||
66 | * General exception handler for CPUs with virtual coherency exception. | ||
67 | * | ||
68 | * Be careful when changing this, it has to be at most 256 (as a special | ||
69 | * exception) bytes to fit into space reserved for the exception handler. | ||
70 | */ | ||
71 | NESTED(except_vec3_r4000, 0, sp) | ||
72 | .set push | ||
73 | .set mips3 | ||
74 | .set noat | ||
75 | mfc0 k1, CP0_CAUSE | ||
76 | li k0, 31<<2 | ||
77 | andi k1, k1, 0x7c | ||
78 | .set push | ||
79 | .set noreorder | ||
80 | .set nomacro | ||
81 | beq k1, k0, handle_vced | ||
82 | li k0, 14<<2 | ||
83 | beq k1, k0, handle_vcei | ||
84 | #ifdef CONFIG_MIPS64 | ||
85 | dsll k1, k1, 1 | ||
86 | #endif | ||
87 | .set pop | ||
88 | PTR_L k0, exception_handlers(k1) | ||
89 | jr k0 | ||
90 | |||
91 | /* | ||
92 | * Big shit, we now may have two dirty primary cache lines for the same | ||
93 | * physical address. We can savely invalidate the line pointed to by | ||
94 | * c0_badvaddr because after return from this exception handler the | ||
95 | * load / store will be re-executed. | ||
96 | */ | ||
97 | handle_vced: | ||
98 | DMFC0 k0, CP0_BADVADDR | ||
99 | li k1, -4 # Is this ... | ||
100 | and k0, k1 # ... really needed? | ||
101 | mtc0 zero, CP0_TAGLO | ||
102 | cache Index_Store_Tag_D,(k0) | ||
103 | cache Hit_Writeback_Inv_SD,(k0) | ||
104 | #ifdef CONFIG_PROC_FS | ||
105 | PTR_LA k0, vced_count | ||
106 | lw k1, (k0) | ||
107 | addiu k1, 1 | ||
108 | sw k1, (k0) | ||
109 | #endif | ||
110 | eret | ||
111 | |||
112 | handle_vcei: | ||
113 | MFC0 k0, CP0_BADVADDR | ||
114 | cache Hit_Writeback_Inv_SD, (k0) # also cleans pi | ||
115 | #ifdef CONFIG_PROC_FS | ||
116 | PTR_LA k0, vcei_count | ||
117 | lw k1, (k0) | ||
118 | addiu k1, 1 | ||
119 | sw k1, (k0) | ||
120 | #endif | ||
121 | eret | ||
122 | .set pop | ||
123 | END(except_vec3_r4000) | ||
124 | |||
125 | /* | ||
126 | * Special interrupt vector for MIPS64 ISA & embedded MIPS processors. | ||
127 | * This is a dedicated interrupt exception vector which reduces the | ||
128 | * interrupt processing overhead. The jump instruction will be replaced | ||
129 | * at the initialization time. | ||
130 | * | ||
131 | * Be careful when changing this, it has to be at most 128 bytes | ||
132 | * to fit into space reserved for the exception handler. | ||
133 | */ | ||
134 | NESTED(except_vec4, 0, sp) | ||
135 | 1: j 1b /* Dummy, will be replaced */ | ||
136 | END(except_vec4) | ||
137 | |||
138 | /* | ||
139 | * EJTAG debug exception handler. | ||
140 | * The EJTAG debug exception entry point is 0xbfc00480, which | ||
141 | * normally is in the boot PROM, so the boot PROM must do a | ||
142 | * unconditional jump to this vector. | ||
143 | */ | ||
144 | NESTED(except_vec_ejtag_debug, 0, sp) | ||
145 | j ejtag_debug_handler | ||
146 | END(except_vec_ejtag_debug) | ||
147 | |||
148 | __FINIT | ||
149 | |||
150 | /* | ||
151 | * EJTAG debug exception handler. | ||
152 | */ | ||
153 | NESTED(ejtag_debug_handler, PT_SIZE, sp) | ||
154 | .set push | ||
155 | .set noat | ||
156 | MTC0 k0, CP0_DESAVE | ||
157 | mfc0 k0, CP0_DEBUG | ||
158 | |||
159 | sll k0, k0, 30 # Check for SDBBP. | ||
160 | bgez k0, ejtag_return | ||
161 | |||
162 | PTR_LA k0, ejtag_debug_buffer | ||
163 | LONG_S k1, 0(k0) | ||
164 | SAVE_ALL | ||
165 | move a0, sp | ||
166 | jal ejtag_exception_handler | ||
167 | RESTORE_ALL | ||
168 | PTR_LA k0, ejtag_debug_buffer | ||
169 | LONG_L k1, 0(k0) | ||
170 | |||
171 | ejtag_return: | ||
172 | MFC0 k0, CP0_DESAVE | ||
173 | .set mips32 | ||
174 | deret | ||
175 | .set pop | ||
176 | END(ejtag_debug_handler) | ||
177 | |||
178 | /* | ||
179 | * This buffer is reserved for the use of the EJTAG debug | ||
180 | * handler. | ||
181 | */ | ||
182 | .data | ||
183 | EXPORT(ejtag_debug_buffer) | ||
184 | .fill LONGSIZE | ||
185 | .previous | ||
186 | |||
187 | __INIT | ||
188 | |||
189 | /* | ||
190 | * NMI debug exception handler for MIPS reference boards. | ||
191 | * The NMI debug exception entry point is 0xbfc00000, which | ||
192 | * normally is in the boot PROM, so the boot PROM must do a | ||
193 | * unconditional jump to this vector. | ||
194 | */ | ||
195 | NESTED(except_vec_nmi, 0, sp) | ||
196 | j nmi_handler | ||
197 | END(except_vec_nmi) | ||
198 | |||
199 | __FINIT | ||
200 | |||
201 | NESTED(nmi_handler, PT_SIZE, sp) | ||
202 | .set push | ||
203 | .set noat | ||
204 | .set mips3 | ||
205 | SAVE_ALL | ||
206 | move a0, sp | ||
207 | jal nmi_exception_handler | ||
208 | RESTORE_ALL | ||
209 | eret | ||
210 | .set pop | ||
211 | END(nmi_handler) | ||
212 | |||
213 | .macro __build_clear_none | ||
214 | .endm | ||
215 | |||
216 | .macro __build_clear_sti | ||
217 | STI | ||
218 | .endm | ||
219 | |||
220 | .macro __build_clear_cli | ||
221 | CLI | ||
222 | .endm | ||
223 | |||
224 | .macro __build_clear_fpe | ||
225 | cfc1 a1, fcr31 | ||
226 | li a2, ~(0x3f << 12) | ||
227 | and a2, a1 | ||
228 | ctc1 a2, fcr31 | ||
229 | STI | ||
230 | .endm | ||
231 | |||
232 | .macro __build_clear_ade | ||
233 | MFC0 t0, CP0_BADVADDR | ||
234 | PTR_S t0, PT_BVADDR(sp) | ||
235 | KMODE | ||
236 | .endm | ||
237 | |||
238 | .macro __BUILD_silent exception | ||
239 | .endm | ||
240 | |||
241 | /* Gas tries to parse the PRINT argument as a string containing | ||
242 | string escapes and emits bogus warnings if it believes to | ||
243 | recognize an unknown escape code. So make the arguments | ||
244 | start with an n and gas will believe \n is ok ... */ | ||
245 | .macro __BUILD_verbose nexception | ||
246 | LONG_L a1, PT_EPC(sp) | ||
247 | #if CONFIG_MIPS32 | ||
248 | PRINT("Got \nexception at %08lx\012") | ||
249 | #endif | ||
250 | #if CONFIG_MIPS64 | ||
251 | PRINT("Got \nexception at %016lx\012") | ||
252 | #endif | ||
253 | .endm | ||
254 | |||
255 | .macro __BUILD_count exception | ||
256 | LONG_L t0,exception_count_\exception | ||
257 | LONG_ADDIU t0, 1 | ||
258 | LONG_S t0,exception_count_\exception | ||
259 | .comm exception_count\exception, 8, 8 | ||
260 | .endm | ||
261 | |||
262 | .macro __BUILD_HANDLER exception handler clear verbose ext | ||
263 | .align 5 | ||
264 | NESTED(handle_\exception, PT_SIZE, sp) | ||
265 | .set noat | ||
266 | SAVE_ALL | ||
267 | FEXPORT(handle_\exception\ext) | ||
268 | __BUILD_clear_\clear | ||
269 | .set at | ||
270 | __BUILD_\verbose \exception | ||
271 | move a0, sp | ||
272 | jal do_\handler | ||
273 | j ret_from_exception | ||
274 | END(handle_\exception) | ||
275 | .endm | ||
276 | |||
277 | .macro BUILD_HANDLER exception handler clear verbose | ||
278 | __BUILD_HANDLER \exception \handler \clear \verbose _int | ||
279 | .endm | ||
280 | |||
281 | BUILD_HANDLER adel ade ade silent /* #4 */ | ||
282 | BUILD_HANDLER ades ade ade silent /* #5 */ | ||
283 | BUILD_HANDLER ibe be cli silent /* #6 */ | ||
284 | BUILD_HANDLER dbe be cli silent /* #7 */ | ||
285 | BUILD_HANDLER bp bp sti silent /* #9 */ | ||
286 | BUILD_HANDLER ri ri sti silent /* #10 */ | ||
287 | BUILD_HANDLER cpu cpu sti silent /* #11 */ | ||
288 | BUILD_HANDLER ov ov sti silent /* #12 */ | ||
289 | BUILD_HANDLER tr tr sti silent /* #13 */ | ||
290 | BUILD_HANDLER fpe fpe fpe silent /* #15 */ | ||
291 | BUILD_HANDLER mdmx mdmx sti silent /* #22 */ | ||
292 | BUILD_HANDLER watch watch sti verbose /* #23 */ | ||
293 | BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ | ||
294 | BUILD_HANDLER reserved reserved sti verbose /* others */ | ||
295 | |||
296 | #ifdef CONFIG_MIPS64 | ||
297 | /* A temporary overflow handler used by check_daddi(). */ | ||
298 | |||
299 | __INIT | ||
300 | |||
301 | BUILD_HANDLER daddi_ov daddi_ov none silent /* #12 */ | ||
302 | #endif | ||