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