Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | * | |
98de920a | 6 | * Copyright (C) 2003, 04, 07 Ralf Baechle <ralf@linux-mips.org> |
a3c4946d RB |
7 | * Copyright (C) MIPS Technologies, Inc. |
8 | * written by Ralf Baechle <ralf@linux-mips.org> | |
1da177e4 LT |
9 | */ |
10 | #ifndef _ASM_HAZARDS_H | |
11 | #define _ASM_HAZARDS_H | |
12 | ||
02b849f7 | 13 | #include <linux/stringify.h> |
f52fca97 | 14 | #include <asm/compiler.h> |
1da177e4 | 15 | |
02b849f7 RB |
16 | #define ___ssnop \ |
17 | sll $0, $0, 1 | |
d7d86aa8 | 18 | |
02b849f7 RB |
19 | #define ___ehb \ |
20 | sll $0, $0, 3 | |
d7d86aa8 | 21 | |
1da177e4 | 22 | /* |
d7d86aa8 | 23 | * TLB hazards |
1da177e4 | 24 | */ |
ab7c01fd SS |
25 | #if (defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \ |
26 | defined(CONFIG_CPU_MIPSR6)) && \ | |
27 | !defined(CONFIG_CPU_CAVIUM_OCTEON) && !defined(CONFIG_CPU_LOONGSON64) | |
1da177e4 | 28 | |
1da177e4 | 29 | /* |
d7d86aa8 | 30 | * MIPSR2 defines ehb for hazard avoidance |
1da177e4 LT |
31 | */ |
32 | ||
02b849f7 RB |
33 | #define __mtc0_tlbw_hazard \ |
34 | ___ehb | |
35 | ||
e50f0e31 JH |
36 | #define __mtc0_tlbr_hazard \ |
37 | ___ehb | |
38 | ||
02b849f7 RB |
39 | #define __tlbw_use_hazard \ |
40 | ___ehb | |
41 | ||
e50f0e31 JH |
42 | #define __tlb_read_hazard \ |
43 | ___ehb | |
44 | ||
02b849f7 RB |
45 | #define __tlb_probe_hazard \ |
46 | ___ehb | |
47 | ||
48 | #define __irq_enable_hazard \ | |
49 | ___ehb | |
50 | ||
51 | #define __irq_disable_hazard \ | |
52 | ___ehb | |
53 | ||
54 | #define __back_to_back_c0_hazard \ | |
55 | ___ehb | |
56 | ||
1da177e4 | 57 | /* |
d7d86aa8 | 58 | * gcc has a tradition of misscompiling the previous construct using the |
70342287 | 59 | * address of a label as argument to inline assembler. Gas otoh has the |
d7d86aa8 RB |
60 | * annoying difference between la and dla which are only usable for 32-bit |
61 | * rsp. 64-bit code, so can't be used without conditional compilation. | |
20430e76 AG |
62 | * The alternative is switching the assembler to 64-bit code which happens |
63 | * to work right even for 32-bit code... | |
1da177e4 | 64 | */ |
d7d86aa8 RB |
65 | #define instruction_hazard() \ |
66 | do { \ | |
67 | unsigned long tmp; \ | |
68 | \ | |
69 | __asm__ __volatile__( \ | |
378ed6f0 | 70 | " .set push \n" \ |
f52fca97 | 71 | " .set "MIPS_ISA_LEVEL" \n" \ |
d7d86aa8 RB |
72 | " dla %0, 1f \n" \ |
73 | " jr.hb %0 \n" \ | |
378ed6f0 | 74 | " .set pop \n" \ |
d7d86aa8 RB |
75 | "1: \n" \ |
76 | : "=r" (tmp)); \ | |
77 | } while (0) | |
1da177e4 | 78 | |
1c7c4451 KC |
79 | #elif (defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MIPS_ALCHEMY)) || \ |
80 | defined(CONFIG_CPU_BMIPS) | |
572afc24 RB |
81 | |
82 | /* | |
83 | * These are slightly complicated by the fact that we guarantee R1 kernels to | |
84 | * run fine on R2 processors. | |
85 | */ | |
02b849f7 RB |
86 | |
87 | #define __mtc0_tlbw_hazard \ | |
88 | ___ssnop; \ | |
89 | ___ssnop; \ | |
90 | ___ehb | |
91 | ||
e50f0e31 JH |
92 | #define __mtc0_tlbr_hazard \ |
93 | ___ssnop; \ | |
94 | ___ssnop; \ | |
95 | ___ehb | |
96 | ||
02b849f7 RB |
97 | #define __tlbw_use_hazard \ |
98 | ___ssnop; \ | |
99 | ___ssnop; \ | |
100 | ___ssnop; \ | |
101 | ___ehb | |
102 | ||
e50f0e31 JH |
103 | #define __tlb_read_hazard \ |
104 | ___ssnop; \ | |
105 | ___ssnop; \ | |
106 | ___ssnop; \ | |
107 | ___ehb | |
108 | ||
02b849f7 RB |
109 | #define __tlb_probe_hazard \ |
110 | ___ssnop; \ | |
111 | ___ssnop; \ | |
112 | ___ssnop; \ | |
113 | ___ehb | |
114 | ||
115 | #define __irq_enable_hazard \ | |
116 | ___ssnop; \ | |
117 | ___ssnop; \ | |
118 | ___ssnop; \ | |
119 | ___ehb | |
120 | ||
121 | #define __irq_disable_hazard \ | |
122 | ___ssnop; \ | |
123 | ___ssnop; \ | |
124 | ___ssnop; \ | |
125 | ___ehb | |
126 | ||
127 | #define __back_to_back_c0_hazard \ | |
128 | ___ssnop; \ | |
129 | ___ssnop; \ | |
130 | ___ssnop; \ | |
131 | ___ehb | |
132 | ||
572afc24 RB |
133 | /* |
134 | * gcc has a tradition of misscompiling the previous construct using the | |
70342287 | 135 | * address of a label as argument to inline assembler. Gas otoh has the |
572afc24 RB |
136 | * annoying difference between la and dla which are only usable for 32-bit |
137 | * rsp. 64-bit code, so can't be used without conditional compilation. | |
20430e76 AG |
138 | * The alternative is switching the assembler to 64-bit code which happens |
139 | * to work right even for 32-bit code... | |
572afc24 RB |
140 | */ |
141 | #define __instruction_hazard() \ | |
142 | do { \ | |
143 | unsigned long tmp; \ | |
144 | \ | |
145 | __asm__ __volatile__( \ | |
378ed6f0 | 146 | " .set push \n" \ |
572afc24 RB |
147 | " .set mips64r2 \n" \ |
148 | " dla %0, 1f \n" \ | |
149 | " jr.hb %0 \n" \ | |
378ed6f0 | 150 | " .set pop \n" \ |
572afc24 RB |
151 | "1: \n" \ |
152 | : "=r" (tmp)); \ | |
153 | } while (0) | |
154 | ||
155 | #define instruction_hazard() \ | |
156 | do { \ | |
f52fca97 | 157 | if (cpu_has_mips_r2_r6) \ |
572afc24 RB |
158 | __instruction_hazard(); \ |
159 | } while (0) | |
160 | ||
42a4f17d | 161 | #elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \ |
51522217 | 162 | defined(CONFIG_CPU_LOONGSON2EF) || defined(CONFIG_CPU_LOONGSON64) || \ |
95b8a5e0 | 163 | defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_R5500) |
1da177e4 LT |
164 | |
165 | /* | |
d7d86aa8 | 166 | * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. |
1da177e4 | 167 | */ |
1da177e4 | 168 | |
02b849f7 RB |
169 | #define __mtc0_tlbw_hazard |
170 | ||
e50f0e31 JH |
171 | #define __mtc0_tlbr_hazard |
172 | ||
02b849f7 RB |
173 | #define __tlbw_use_hazard |
174 | ||
e50f0e31 JH |
175 | #define __tlb_read_hazard |
176 | ||
02b849f7 RB |
177 | #define __tlb_probe_hazard |
178 | ||
179 | #define __irq_enable_hazard | |
180 | ||
181 | #define __irq_disable_hazard | |
182 | ||
183 | #define __back_to_back_c0_hazard | |
184 | ||
d7d86aa8 | 185 | #define instruction_hazard() do { } while (0) |
1da177e4 | 186 | |
d7d86aa8 | 187 | #elif defined(CONFIG_CPU_SB1) |
1da177e4 LT |
188 | |
189 | /* | |
d7d86aa8 | 190 | * Mostly like R4000 for historic reasons |
1da177e4 | 191 | */ |
02b849f7 RB |
192 | #define __mtc0_tlbw_hazard |
193 | ||
e50f0e31 JH |
194 | #define __mtc0_tlbr_hazard |
195 | ||
02b849f7 RB |
196 | #define __tlbw_use_hazard |
197 | ||
e50f0e31 JH |
198 | #define __tlb_read_hazard |
199 | ||
02b849f7 RB |
200 | #define __tlb_probe_hazard |
201 | ||
202 | #define __irq_enable_hazard | |
203 | ||
204 | #define __irq_disable_hazard \ | |
205 | ___ssnop; \ | |
206 | ___ssnop; \ | |
207 | ___ssnop | |
208 | ||
209 | #define __back_to_back_c0_hazard | |
210 | ||
d7d86aa8 | 211 | #define instruction_hazard() do { } while (0) |
5068debf | 212 | |
1da177e4 LT |
213 | #else |
214 | ||
215 | /* | |
d7d86aa8 RB |
216 | * Finally the catchall case for all other processors including R4000, R4400, |
217 | * R4600, R4700, R5000, RM7000, NEC VR41xx etc. | |
a3c4946d | 218 | * |
d7d86aa8 RB |
219 | * The taken branch will result in a two cycle penalty for the two killed |
220 | * instructions on R4000 / R4400. Other processors only have a single cycle | |
221 | * hazard so this is nice trick to have an optimal code for a range of | |
222 | * processors. | |
7043ad4f | 223 | */ |
02b849f7 RB |
224 | #define __mtc0_tlbw_hazard \ |
225 | nop; \ | |
226 | nop | |
227 | ||
e50f0e31 JH |
228 | #define __mtc0_tlbr_hazard \ |
229 | nop; \ | |
230 | nop | |
231 | ||
02b849f7 RB |
232 | #define __tlbw_use_hazard \ |
233 | nop; \ | |
234 | nop; \ | |
235 | nop | |
236 | ||
e50f0e31 JH |
237 | #define __tlb_read_hazard \ |
238 | nop; \ | |
239 | nop; \ | |
240 | nop | |
241 | ||
02b849f7 RB |
242 | #define __tlb_probe_hazard \ |
243 | nop; \ | |
244 | nop; \ | |
245 | nop | |
246 | ||
247 | #define __irq_enable_hazard \ | |
248 | ___ssnop; \ | |
249 | ___ssnop; \ | |
250 | ___ssnop | |
251 | ||
252 | #define __irq_disable_hazard \ | |
253 | nop; \ | |
254 | nop; \ | |
255 | nop | |
256 | ||
257 | #define __back_to_back_c0_hazard \ | |
258 | ___ssnop; \ | |
259 | ___ssnop; \ | |
260 | ___ssnop | |
261 | ||
cc61c1fe | 262 | #define instruction_hazard() do { } while (0) |
41c594ab | 263 | |
d7d86aa8 | 264 | #endif |
1da177e4 | 265 | |
0b624956 CD |
266 | |
267 | /* FPU hazards */ | |
268 | ||
269 | #if defined(CONFIG_CPU_SB1) | |
02b849f7 RB |
270 | |
271 | #define __enable_fpu_hazard \ | |
272 | .set push; \ | |
273 | .set mips64; \ | |
274 | .set noreorder; \ | |
275 | ___ssnop; \ | |
276 | bnezl $0, .+4; \ | |
277 | ___ssnop; \ | |
278 | .set pop | |
279 | ||
280 | #define __disable_fpu_hazard | |
0b624956 | 281 | |
ab7c01fd SS |
282 | #elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \ |
283 | defined(CONFIG_CPU_MIPSR6) | |
02b849f7 RB |
284 | |
285 | #define __enable_fpu_hazard \ | |
286 | ___ehb | |
287 | ||
288 | #define __disable_fpu_hazard \ | |
289 | ___ehb | |
290 | ||
0b624956 | 291 | #else |
02b849f7 RB |
292 | |
293 | #define __enable_fpu_hazard \ | |
294 | nop; \ | |
295 | nop; \ | |
296 | nop; \ | |
297 | nop | |
298 | ||
299 | #define __disable_fpu_hazard \ | |
300 | ___ehb | |
301 | ||
0b624956 CD |
302 | #endif |
303 | ||
02b849f7 RB |
304 | #ifdef __ASSEMBLY__ |
305 | ||
306 | #define _ssnop ___ssnop | |
307 | #define _ehb ___ehb | |
308 | #define mtc0_tlbw_hazard __mtc0_tlbw_hazard | |
e50f0e31 | 309 | #define mtc0_tlbr_hazard __mtc0_tlbr_hazard |
02b849f7 | 310 | #define tlbw_use_hazard __tlbw_use_hazard |
e50f0e31 | 311 | #define tlb_read_hazard __tlb_read_hazard |
02b849f7 RB |
312 | #define tlb_probe_hazard __tlb_probe_hazard |
313 | #define irq_enable_hazard __irq_enable_hazard | |
314 | #define irq_disable_hazard __irq_disable_hazard | |
315 | #define back_to_back_c0_hazard __back_to_back_c0_hazard | |
316 | #define enable_fpu_hazard __enable_fpu_hazard | |
317 | #define disable_fpu_hazard __disable_fpu_hazard | |
318 | ||
319 | #else | |
320 | ||
321 | #define _ssnop() \ | |
322 | do { \ | |
323 | __asm__ __volatile__( \ | |
324 | __stringify(___ssnop) \ | |
325 | ); \ | |
326 | } while (0) | |
327 | ||
328 | #define _ehb() \ | |
329 | do { \ | |
330 | __asm__ __volatile__( \ | |
331 | __stringify(___ehb) \ | |
332 | ); \ | |
333 | } while (0) | |
334 | ||
335 | ||
336 | #define mtc0_tlbw_hazard() \ | |
337 | do { \ | |
338 | __asm__ __volatile__( \ | |
339 | __stringify(__mtc0_tlbw_hazard) \ | |
340 | ); \ | |
341 | } while (0) | |
342 | ||
343 | ||
e50f0e31 JH |
344 | #define mtc0_tlbr_hazard() \ |
345 | do { \ | |
346 | __asm__ __volatile__( \ | |
347 | __stringify(__mtc0_tlbr_hazard) \ | |
348 | ); \ | |
349 | } while (0) | |
350 | ||
351 | ||
02b849f7 RB |
352 | #define tlbw_use_hazard() \ |
353 | do { \ | |
354 | __asm__ __volatile__( \ | |
355 | __stringify(__tlbw_use_hazard) \ | |
356 | ); \ | |
357 | } while (0) | |
358 | ||
359 | ||
e50f0e31 JH |
360 | #define tlb_read_hazard() \ |
361 | do { \ | |
362 | __asm__ __volatile__( \ | |
363 | __stringify(__tlb_read_hazard) \ | |
364 | ); \ | |
365 | } while (0) | |
366 | ||
367 | ||
02b849f7 RB |
368 | #define tlb_probe_hazard() \ |
369 | do { \ | |
370 | __asm__ __volatile__( \ | |
371 | __stringify(__tlb_probe_hazard) \ | |
372 | ); \ | |
373 | } while (0) | |
374 | ||
375 | ||
376 | #define irq_enable_hazard() \ | |
377 | do { \ | |
378 | __asm__ __volatile__( \ | |
379 | __stringify(__irq_enable_hazard) \ | |
380 | ); \ | |
381 | } while (0) | |
382 | ||
383 | ||
384 | #define irq_disable_hazard() \ | |
385 | do { \ | |
386 | __asm__ __volatile__( \ | |
387 | __stringify(__irq_disable_hazard) \ | |
388 | ); \ | |
389 | } while (0) | |
390 | ||
391 | ||
392 | #define back_to_back_c0_hazard() \ | |
393 | do { \ | |
394 | __asm__ __volatile__( \ | |
395 | __stringify(__back_to_back_c0_hazard) \ | |
396 | ); \ | |
397 | } while (0) | |
398 | ||
399 | ||
400 | #define enable_fpu_hazard() \ | |
401 | do { \ | |
402 | __asm__ __volatile__( \ | |
403 | __stringify(__enable_fpu_hazard) \ | |
404 | ); \ | |
405 | } while (0) | |
406 | ||
407 | ||
408 | #define disable_fpu_hazard() \ | |
409 | do { \ | |
410 | __asm__ __volatile__( \ | |
411 | __stringify(__disable_fpu_hazard) \ | |
412 | ); \ | |
413 | } while (0) | |
414 | ||
415 | /* | |
416 | * MIPS R2 instruction hazard barrier. Needs to be called as a subroutine. | |
417 | */ | |
418 | extern void mips_ihb(void); | |
419 | ||
420 | #endif /* __ASSEMBLY__ */ | |
421 | ||
1da177e4 | 422 | #endif /* _ASM_HAZARDS_H */ |