aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2006-09-07 22:13:49 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-09-27 08:37:53 -0400
commitd7d86aa88a1f3922b85e39edd8a6d6c01e939842 (patch)
tree88fb6fabb51ac122c1b069aa194773de5b5821e1
parentda79e827d4164ba1b961b62774800a8a52a3b6e4 (diff)
[MIPS] Cleanup hazard handling.
Mostly based on patch by Chris Dearman and cleanups from Yoichi. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--include/asm-mips/hazards.h362
1 files changed, 126 insertions, 236 deletions
diff --git a/include/asm-mips/hazards.h b/include/asm-mips/hazards.h
index 25f5e8a4177d..bf0b80404946 100644
--- a/include/asm-mips/hazards.h
+++ b/include/asm-mips/hazards.h
@@ -11,103 +11,96 @@
11#define _ASM_HAZARDS_H 11#define _ASM_HAZARDS_H
12 12
13 13
14#ifdef __ASSEMBLY__ 14#ifdef __ASSEMBLER__
15 15#define ASMMACRO(name, code...) .macro name; code; .endm
16 .macro _ssnop
17 sll $0, $0, 1
18 .endm
19
20 .macro _ehb
21 sll $0, $0, 3
22 .endm
23
24/*
25 * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent
26 * use of the JTLB for instructions should not occur for 4 cpu cycles and use
27 * for data translations should not occur for 3 cpu cycles.
28 */
29#ifdef CONFIG_CPU_RM9000
30
31 .macro mtc0_tlbw_hazard
32 .set push
33 .set mips32
34 _ssnop; _ssnop; _ssnop; _ssnop
35 .set pop
36 .endm
37
38 .macro tlbw_eret_hazard
39 .set push
40 .set mips32
41 _ssnop; _ssnop; _ssnop; _ssnop
42 .set pop
43 .endm
44
45#else 16#else
46 17
47/* 18#define ASMMACRO(name, code...) \
48 * The taken branch will result in a two cycle penalty for the two killed 19__asm__(".macro " #name "; " #code "; .endm"); \
49 * instructions on R4000 / R4400. Other processors only have a single cycle 20 \
50 * hazard so this is nice trick to have an optimal code for a range of 21static inline void name(void) \
51 * processors. 22{ \
52 */ 23 __asm__ __volatile__ (#name); \
53 .macro mtc0_tlbw_hazard 24}
54 b . + 8
55 .endm
56 25
57 .macro tlbw_eret_hazard
58 .endm
59#endif 26#endif
60 27
28ASMMACRO(_ssnop,
29 sll $0, $0, 1
30 )
31
32ASMMACRO(_ehb,
33 sll $0, $0, 3
34 )
35
61/* 36/*
62 * mtc0->mfc0 hazard 37 * TLB hazards
63 * The 24K has a 2 cycle mtc0/mfc0 execution hazard.
64 * It is a MIPS32R2 processor so ehb will clear the hazard.
65 */ 38 */
39#if defined(CONFIG_CPU_MIPSR2)
66 40
67#ifdef CONFIG_CPU_MIPSR2
68/* 41/*
69 * Use a macro for ehb unless explicit support for MIPSR2 is enabled 42 * MIPSR2 defines ehb for hazard avoidance
70 */ 43 */
71 44
72#define irq_enable_hazard \ 45ASMMACRO(mtc0_tlbw_hazard,
46 _ehb
47 )
48ASMMACRO(tlbw_use_hazard,
49 _ehb
50 )
51ASMMACRO(tlb_probe_hazard,
52 _ehb
53 )
54ASMMACRO(irq_enable_hazard,
55 )
56ASMMACRO(irq_disable_hazard,
73 _ehb 57 _ehb
74 58 )
75#define irq_disable_hazard \ 59ASMMACRO(back_to_back_c0_hazard,
76 _ehb 60 _ehb
77 61 )
78#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000)
79
80/* 62/*
81 * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. 63 * gcc has a tradition of misscompiling the previous construct using the
64 * address of a label as argument to inline assembler. Gas otoh has the
65 * annoying difference between la and dla which are only usable for 32-bit
66 * rsp. 64-bit code, so can't be used without conditional compilation.
67 * The alterantive is switching the assembler to 64-bit code which happens
68 * to work right even for 32-bit code ...
82 */ 69 */
70#define instruction_hazard() \
71do { \
72 unsigned long tmp; \
73 \
74 __asm__ __volatile__( \
75 " .set mips64r2 \n" \
76 " dla %0, 1f \n" \
77 " jr.hb %0 \n" \
78 " .set mips0 \n" \
79 "1: \n" \
80 : "=r" (tmp)); \
81} while (0)
83 82
84#define irq_enable_hazard 83#elif defined(CONFIG_CPU_R10000)
85
86#define irq_disable_hazard
87
88#else
89 84
90/* 85/*
91 * Classic MIPS needs 1 - 3 nops or ssnops 86 * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
92 */ 87 */
93#define irq_enable_hazard
94#define irq_disable_hazard \
95 _ssnop; _ssnop; _ssnop
96 88
97#endif 89ASMMACRO(mtc0_tlbw_hazard,
98 90 )
99#else /* __ASSEMBLY__ */ 91ASMMACRO(tlbw_use_hazard,
100 92 )
101__asm__( 93ASMMACRO(tlb_probe_hazard,
102 " .macro _ssnop \n" 94 )
103 " sll $0, $0, 1 \n" 95ASMMACRO(irq_enable_hazard,
104 " .endm \n" 96 )
105 " \n" 97ASMMACRO(irq_disable_hazard,
106 " .macro _ehb \n" 98 )
107 " sll $0, $0, 3 \n" 99ASMMACRO(back_to_back_c0_hazard,
108 " .endm \n"); 100 )
101#define instruction_hazard() do { } while (0)
109 102
110#ifdef CONFIG_CPU_RM9000 103#elif defined(CONFIG_CPU_RM9000)
111 104
112/* 105/*
113 * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent 106 * RM9000 hazards. When the JTLB is updated by tlbwi or tlbwr, a subsequent
@@ -115,176 +108,73 @@ __asm__(
115 * for data translations should not occur for 3 cpu cycles. 108 * for data translations should not occur for 3 cpu cycles.
116 */ 109 */
117 110
118#define mtc0_tlbw_hazard() \ 111ASMMACRO(mtc0_tlbw_hazard,
119 __asm__ __volatile__( \ 112 _ssnop; _ssnop; _ssnop; _ssnop
120 " .set mips32 \n" \ 113 )
121 " _ssnop \n" \ 114ASMMACRO(tlbw_use_hazard,
122 " _ssnop \n" \ 115 _ssnop; _ssnop; _ssnop; _ssnop
123 " _ssnop \n" \ 116 )
124 " _ssnop \n" \ 117ASMMACRO(tlb_probe_hazard,
125 " .set mips0 \n") 118 _ssnop; _ssnop; _ssnop; _ssnop
126 119 )
127#define tlbw_use_hazard() \ 120ASMMACRO(irq_enable_hazard,
128 __asm__ __volatile__( \ 121 )
129 " .set mips32 \n" \ 122ASMMACRO(irq_disable_hazard,
130 " _ssnop \n" \ 123 )
131 " _ssnop \n" \ 124ASMMACRO(back_to_back_c0_hazard,
132 " _ssnop \n" \ 125 )
133 " _ssnop \n" \ 126#define instruction_hazard() do { } while (0)
134 " .set mips0 \n")
135
136#else
137
138/*
139 * Overkill warning ...
140 */
141#define mtc0_tlbw_hazard() \
142 __asm__ __volatile__( \
143 " .set noreorder \n" \
144 " nop \n" \
145 " nop \n" \
146 " nop \n" \
147 " nop \n" \
148 " nop \n" \
149 " nop \n" \
150 " .set reorder \n")
151
152#define tlbw_use_hazard() \
153 __asm__ __volatile__( \
154 " .set noreorder \n" \
155 " nop \n" \
156 " nop \n" \
157 " nop \n" \
158 " nop \n" \
159 " nop \n" \
160 " nop \n" \
161 " .set reorder \n")
162
163#endif
164
165/*
166 * Interrupt enable/disable hazards
167 * Some processors have hazards when modifying
168 * the status register to change the interrupt state
169 */
170
171#ifdef CONFIG_CPU_MIPSR2
172
173__asm__(" .macro irq_enable_hazard \n"
174 " _ehb \n"
175 " .endm \n"
176 " \n"
177 " .macro irq_disable_hazard \n"
178 " _ehb \n"
179 " .endm \n");
180 127
181#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) 128#elif defined(CONFIG_CPU_SB1)
182 129
183/* 130/*
184 * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer. 131 * Mostly like R4000 for historic reasons
185 */ 132 */
186 133ASMMACRO(mtc0_tlbw_hazard,
187__asm__( 134 )
188 " .macro irq_enable_hazard \n" 135ASMMACRO(tlbw_use_hazard,
189 " .endm \n" 136 )
190 " \n" 137ASMMACRO(tlb_probe_hazard,
191 " .macro irq_disable_hazard \n" 138 )
192 " .endm \n"); 139ASMMACRO(irq_enable_hazard,
140 )
141ASMMACRO(irq_disable_hazard,
142 _ssnop; _ssnop; _ssnop
143 )
144ASMMACRO(back_to_back_c0_hazard,
145 )
146#define instruction_hazard() do { } while (0)
193 147
194#else 148#else
195 149
196/* 150/*
197 * Default for classic MIPS processors. Assume worst case hazards but don't 151 * Finally the catchall case for all other processors including R4000, R4400,
198 * care about the irq_enable_hazard - sooner or later the hardware will 152 * R4600, R4700, R5000, RM7000, NEC VR41xx etc.
199 * enable it and we don't care when exactly.
200 */
201
202__asm__(
203 " # \n"
204 " # There is a hazard but we do not care \n"
205 " # \n"
206 " .macro\tirq_enable_hazard \n"
207 " .endm \n"
208 " \n"
209 " .macro\tirq_disable_hazard \n"
210 " _ssnop \n"
211 " _ssnop \n"
212 " _ssnop \n"
213 " .endm \n");
214
215#endif
216
217#define irq_enable_hazard() \
218 __asm__ __volatile__("irq_enable_hazard")
219#define irq_disable_hazard() \
220 __asm__ __volatile__("irq_disable_hazard")
221
222
223/*
224 * Back-to-back hazards -
225 * 153 *
226 * What is needed to separate a move to cp0 from a subsequent read from the 154 * The taken branch will result in a two cycle penalty for the two killed
227 * same cp0 register? 155 * instructions on R4000 / R4400. Other processors only have a single cycle
228 */ 156 * hazard so this is nice trick to have an optimal code for a range of
229#ifdef CONFIG_CPU_MIPSR2 157 * processors.
230
231__asm__(" .macro back_to_back_c0_hazard \n"
232 " _ehb \n"
233 " .endm \n");
234
235#elif defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_RM9000) || \
236 defined(CONFIG_CPU_SB1)
237
238__asm__(" .macro back_to_back_c0_hazard \n"
239 " .endm \n");
240
241#else
242
243__asm__(" .macro back_to_back_c0_hazard \n"
244 " .set noreorder \n"
245 " _ssnop \n"
246 " _ssnop \n"
247 " _ssnop \n"
248 " .set reorder \n"
249 " .endm");
250
251#endif
252
253#define back_to_back_c0_hazard() \
254 __asm__ __volatile__("back_to_back_c0_hazard")
255
256
257/*
258 * Instruction execution hazard
259 */
260#ifdef CONFIG_CPU_MIPSR2
261/*
262 * gcc has a tradition of misscompiling the previous construct using the
263 * address of a label as argument to inline assembler. Gas otoh has the
264 * annoying difference between la and dla which are only usable for 32-bit
265 * rsp. 64-bit code, so can't be used without conditional compilation.
266 * The alterantive is switching the assembler to 64-bit code which happens
267 * to work right even for 32-bit code ...
268 */ 158 */
269#define instruction_hazard() \ 159ASMMACRO(mtc0_tlbw_hazard,
270do { \ 160 nop
271 unsigned long tmp; \ 161 )
272 \ 162ASMMACRO(tlbw_use_hazard,
273 __asm__ __volatile__( \ 163 nop; nop; nop
274 " .set mips64r2 \n" \ 164 )
275 " dla %0, 1f \n" \ 165ASMMACRO(tlb_probe_hazard,
276 " jr.hb %0 \n" \ 166 nop; nop; nop
277 " .set mips0 \n" \ 167 )
278 "1: \n" \ 168ASMMACRO(irq_enable_hazard,
279 : "=r" (tmp)); \ 169 )
280} while (0) 170ASMMACRO(irq_disable_hazard,
281 171 nop; nop; nop
282#else 172 )
173ASMMACRO(back_to_back_c0_hazard,
174 _ssnop; _ssnop; _ssnop;
175 )
283#define instruction_hazard() do { } while (0) 176#define instruction_hazard() do { } while (0)
284#endif
285
286extern void mips_ihb(void);
287 177
288#endif /* __ASSEMBLY__ */ 178#endif
289 179
290#endif /* _ASM_HAZARDS_H */ 180#endif /* _ASM_HAZARDS_H */