hazards.h 7.4 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 *
6
 * Copyright (C) 2003, 04, 07 Ralf Baechle <ralf@linux-mips.org>
7 8
 * Copyright (C) MIPS Technologies, Inc.
 *   written by Ralf Baechle <ralf@linux-mips.org>
L
Linus Torvalds 已提交
9 10 11 12
 */
#ifndef _ASM_HAZARDS_H
#define _ASM_HAZARDS_H

13
#include <linux/stringify.h>
14
#include <asm/compiler.h>
L
Linus Torvalds 已提交
15

16 17
#define ___ssnop							\
	sll	$0, $0, 1
R
Ralf Baechle 已提交
18

19 20
#define ___ehb								\
	sll	$0, $0, 3
R
Ralf Baechle 已提交
21

L
Linus Torvalds 已提交
22
/*
R
Ralf Baechle 已提交
23
 * TLB hazards
L
Linus Torvalds 已提交
24
 */
25
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6) && !defined(CONFIG_CPU_CAVIUM_OCTEON)
L
Linus Torvalds 已提交
26 27

/*
R
Ralf Baechle 已提交
28
 * MIPSR2 defines ehb for hazard avoidance
L
Linus Torvalds 已提交
29 30
 */

31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
#define __mtc0_tlbw_hazard						\
	___ehb

#define __tlbw_use_hazard						\
	___ehb

#define __tlb_probe_hazard						\
	___ehb

#define __irq_enable_hazard						\
	___ehb

#define __irq_disable_hazard						\
	___ehb

#define __back_to_back_c0_hazard					\
	___ehb

L
Linus Torvalds 已提交
49
/*
R
Ralf Baechle 已提交
50
 * gcc has a tradition of misscompiling the previous construct using the
R
Ralf Baechle 已提交
51
 * address of a label as argument to inline assembler.	Gas otoh has the
R
Ralf Baechle 已提交
52 53 54 55
 * annoying difference between la and dla which are only usable for 32-bit
 * rsp. 64-bit code, so can't be used without conditional compilation.
 * The alterantive is switching the assembler to 64-bit code which happens
 * to work right even for 32-bit code ...
L
Linus Torvalds 已提交
56
 */
R
Ralf Baechle 已提交
57 58 59 60 61
#define instruction_hazard()						\
do {									\
	unsigned long tmp;						\
									\
	__asm__ __volatile__(						\
62
	"	.set "MIPS_ISA_LEVEL"				\n"	\
R
Ralf Baechle 已提交
63 64 65 66 67 68
	"	dla	%0, 1f					\n"	\
	"	jr.hb	%0					\n"	\
	"	.set	mips0					\n"	\
	"1:							\n"	\
	: "=r" (tmp));							\
} while (0)
L
Linus Torvalds 已提交
69

70 71
#elif (defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MIPS_ALCHEMY)) || \
	defined(CONFIG_CPU_BMIPS)
72 73 74 75 76

/*
 * These are slightly complicated by the fact that we guarantee R1 kernels to
 * run fine on R2 processors.
 */
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

#define __mtc0_tlbw_hazard						\
	___ssnop;							\
	___ssnop;							\
	___ehb

#define __tlbw_use_hazard						\
	___ssnop;							\
	___ssnop;							\
	___ssnop;							\
	___ehb

#define __tlb_probe_hazard						\
	___ssnop;							\
	___ssnop;							\
	___ssnop;							\
	___ehb

#define __irq_enable_hazard						\
	___ssnop;							\
	___ssnop;							\
	___ssnop;							\
	___ehb

#define __irq_disable_hazard						\
	___ssnop;							\
	___ssnop;							\
	___ssnop;							\
	___ehb

#define __back_to_back_c0_hazard					\
	___ssnop;							\
	___ssnop;							\
	___ssnop;							\
	___ehb

113 114
/*
 * gcc has a tradition of misscompiling the previous construct using the
R
Ralf Baechle 已提交
115
 * address of a label as argument to inline assembler.	Gas otoh has the
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
 * annoying difference between la and dla which are only usable for 32-bit
 * rsp. 64-bit code, so can't be used without conditional compilation.
 * The alterantive is switching the assembler to 64-bit code which happens
 * to work right even for 32-bit code ...
 */
#define __instruction_hazard()						\
do {									\
	unsigned long tmp;						\
									\
	__asm__ __volatile__(						\
	"	.set	mips64r2				\n"	\
	"	dla	%0, 1f					\n"	\
	"	jr.hb	%0					\n"	\
	"	.set	mips0					\n"	\
	"1:							\n"	\
	: "=r" (tmp));							\
} while (0)

#define instruction_hazard()						\
do {									\
136
	if (cpu_has_mips_r2_r6)						\
137 138 139
		__instruction_hazard();					\
} while (0)

140
#elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \
141
	defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_CPU_R10000) || \
142
	defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR)
L
Linus Torvalds 已提交
143 144

/*
R
Ralf Baechle 已提交
145
 * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
L
Linus Torvalds 已提交
146 147
 */

148 149 150 151 152 153 154 155 156 157 158 159
#define __mtc0_tlbw_hazard

#define __tlbw_use_hazard

#define __tlb_probe_hazard

#define __irq_enable_hazard

#define __irq_disable_hazard

#define __back_to_back_c0_hazard

R
Ralf Baechle 已提交
160
#define instruction_hazard() do { } while (0)
L
Linus Torvalds 已提交
161

R
Ralf Baechle 已提交
162
#elif defined(CONFIG_CPU_SB1)
L
Linus Torvalds 已提交
163 164

/*
R
Ralf Baechle 已提交
165
 * Mostly like R4000 for historic reasons
L
Linus Torvalds 已提交
166
 */
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
#define __mtc0_tlbw_hazard

#define __tlbw_use_hazard

#define __tlb_probe_hazard

#define __irq_enable_hazard

#define __irq_disable_hazard						\
	___ssnop;							\
	___ssnop;							\
	___ssnop

#define __back_to_back_c0_hazard

R
Ralf Baechle 已提交
182
#define instruction_hazard() do { } while (0)
183

L
Linus Torvalds 已提交
184 185 186
#else

/*
R
Ralf Baechle 已提交
187 188
 * Finally the catchall case for all other processors including R4000, R4400,
 * R4600, R4700, R5000, RM7000, NEC VR41xx etc.
189
 *
R
Ralf Baechle 已提交
190 191 192 193
 * The taken branch will result in a two cycle penalty for the two killed
 * instructions on R4000 / R4400.  Other processors only have a single cycle
 * hazard so this is nice trick to have an optimal code for a range of
 * processors.
194
 */
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
#define __mtc0_tlbw_hazard						\
	nop;								\
	nop

#define __tlbw_use_hazard						\
	nop;								\
	nop;								\
	nop

#define __tlb_probe_hazard						\
	nop;								\
	nop;								\
	nop

#define __irq_enable_hazard						\
	___ssnop;							\
	___ssnop;							\
	___ssnop

#define __irq_disable_hazard						\
	nop;								\
	nop;								\
	nop

#define __back_to_back_c0_hazard					\
	___ssnop;							\
	___ssnop;							\
	___ssnop

224
#define instruction_hazard() do { } while (0)
225

R
Ralf Baechle 已提交
226
#endif
L
Linus Torvalds 已提交
227

C
Chris Dearman 已提交
228 229 230 231

/* FPU hazards */

#if defined(CONFIG_CPU_SB1)
232 233 234 235 236 237 238 239 240 241 242

#define __enable_fpu_hazard						\
	.set	push;							\
	.set	mips64;							\
	.set	noreorder;						\
	___ssnop;							\
	bnezl	$0, .+4;						\
	___ssnop;							\
	.set	pop

#define __disable_fpu_hazard
C
Chris Dearman 已提交
243

244
#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
245 246 247 248 249 250 251

#define __enable_fpu_hazard						\
	___ehb

#define __disable_fpu_hazard						\
	___ehb

C
Chris Dearman 已提交
252
#else
253 254 255 256 257 258 259 260 261 262

#define __enable_fpu_hazard						\
	nop;								\
	nop;								\
	nop;								\
	nop

#define __disable_fpu_hazard						\
	___ehb

C
Chris Dearman 已提交
263 264
#endif

265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
#ifdef __ASSEMBLY__

#define _ssnop ___ssnop
#define	_ehb ___ehb
#define mtc0_tlbw_hazard __mtc0_tlbw_hazard
#define tlbw_use_hazard __tlbw_use_hazard
#define tlb_probe_hazard __tlb_probe_hazard
#define irq_enable_hazard __irq_enable_hazard
#define irq_disable_hazard __irq_disable_hazard
#define back_to_back_c0_hazard __back_to_back_c0_hazard
#define enable_fpu_hazard __enable_fpu_hazard
#define disable_fpu_hazard __disable_fpu_hazard

#else

#define _ssnop()							\
do {									\
	__asm__ __volatile__(						\
	__stringify(___ssnop)						\
	);								\
} while (0)

#define	_ehb()								\
do {									\
	__asm__ __volatile__(						\
	__stringify(___ehb)						\
	);								\
} while (0)


#define mtc0_tlbw_hazard()						\
do {									\
	__asm__ __volatile__(						\
	__stringify(__mtc0_tlbw_hazard)					\
	);								\
} while (0)


#define tlbw_use_hazard()						\
do {									\
	__asm__ __volatile__(						\
	__stringify(__tlbw_use_hazard)					\
	);								\
} while (0)


#define tlb_probe_hazard()						\
do {									\
	__asm__ __volatile__(						\
	__stringify(__tlb_probe_hazard)					\
	);								\
} while (0)


#define irq_enable_hazard()						\
do {									\
	__asm__ __volatile__(						\
	__stringify(__irq_enable_hazard)				\
	);								\
} while (0)


#define irq_disable_hazard()						\
do {									\
	__asm__ __volatile__(						\
	__stringify(__irq_disable_hazard)				\
	);								\
} while (0)


#define back_to_back_c0_hazard() 					\
do {									\
	__asm__ __volatile__(						\
	__stringify(__back_to_back_c0_hazard)				\
	);								\
} while (0)


#define enable_fpu_hazard()						\
do {									\
	__asm__ __volatile__(						\
	__stringify(__enable_fpu_hazard)				\
	);								\
} while (0)


#define disable_fpu_hazard()						\
do {									\
	__asm__ __volatile__(						\
	__stringify(__disable_fpu_hazard)				\
	);								\
} while (0)

/*
 * MIPS R2 instruction hazard barrier.   Needs to be called as a subroutine.
 */
extern void mips_ihb(void);

#endif /* __ASSEMBLY__  */

L
Linus Torvalds 已提交
365
#endif /* _ASM_HAZARDS_H */