Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Copyright (C) 2003, 04, 07 Ralf Baechle <ralf@linux-mips.org>
0007  * Copyright (C) MIPS Technologies, Inc.
0008  *   written by Ralf Baechle <ralf@linux-mips.org>
0009  */
0010 #ifndef _ASM_HAZARDS_H
0011 #define _ASM_HAZARDS_H
0012 
0013 #include <linux/stringify.h>
0014 #include <asm/compiler.h>
0015 
0016 #define ___ssnop                            \
0017     sll $0, $0, 1
0018 
0019 #define ___ehb                              \
0020     sll $0, $0, 3
0021 
0022 /*
0023  * TLB hazards
0024  */
0025 #if (defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \
0026      defined(CONFIG_CPU_MIPSR6)) && \
0027     !defined(CONFIG_CPU_CAVIUM_OCTEON) && !defined(CONFIG_CPU_LOONGSON64)
0028 
0029 /*
0030  * MIPSR2 defines ehb for hazard avoidance
0031  */
0032 
0033 #define __mtc0_tlbw_hazard                      \
0034     ___ehb
0035 
0036 #define __mtc0_tlbr_hazard                      \
0037     ___ehb
0038 
0039 #define __tlbw_use_hazard                       \
0040     ___ehb
0041 
0042 #define __tlb_read_hazard                       \
0043     ___ehb
0044 
0045 #define __tlb_probe_hazard                      \
0046     ___ehb
0047 
0048 #define __irq_enable_hazard                     \
0049     ___ehb
0050 
0051 #define __irq_disable_hazard                        \
0052     ___ehb
0053 
0054 #define __back_to_back_c0_hazard                    \
0055     ___ehb
0056 
0057 /*
0058  * gcc has a tradition of misscompiling the previous construct using the
0059  * address of a label as argument to inline assembler.  Gas otoh has the
0060  * annoying difference between la and dla which are only usable for 32-bit
0061  * rsp. 64-bit code, so can't be used without conditional compilation.
0062  * The alternative is switching the assembler to 64-bit code which happens
0063  * to work right even for 32-bit code...
0064  */
0065 #define instruction_hazard()                        \
0066 do {                                    \
0067     unsigned long tmp;                      \
0068                                     \
0069     __asm__ __volatile__(                       \
0070     "   .set    push                    \n" \
0071     "   .set "MIPS_ISA_LEVEL"               \n" \
0072     "   dla %0, 1f                  \n" \
0073     "   jr.hb   %0                  \n" \
0074     "   .set    pop                 \n" \
0075     "1:                         \n" \
0076     : "=r" (tmp));                          \
0077 } while (0)
0078 
0079 #elif (defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MIPS_ALCHEMY)) || \
0080     defined(CONFIG_CPU_BMIPS)
0081 
0082 /*
0083  * These are slightly complicated by the fact that we guarantee R1 kernels to
0084  * run fine on R2 processors.
0085  */
0086 
0087 #define __mtc0_tlbw_hazard                      \
0088     ___ssnop;                           \
0089     ___ssnop;                           \
0090     ___ehb
0091 
0092 #define __mtc0_tlbr_hazard                      \
0093     ___ssnop;                           \
0094     ___ssnop;                           \
0095     ___ehb
0096 
0097 #define __tlbw_use_hazard                       \
0098     ___ssnop;                           \
0099     ___ssnop;                           \
0100     ___ssnop;                           \
0101     ___ehb
0102 
0103 #define __tlb_read_hazard                       \
0104     ___ssnop;                           \
0105     ___ssnop;                           \
0106     ___ssnop;                           \
0107     ___ehb
0108 
0109 #define __tlb_probe_hazard                      \
0110     ___ssnop;                           \
0111     ___ssnop;                           \
0112     ___ssnop;                           \
0113     ___ehb
0114 
0115 #define __irq_enable_hazard                     \
0116     ___ssnop;                           \
0117     ___ssnop;                           \
0118     ___ssnop;                           \
0119     ___ehb
0120 
0121 #define __irq_disable_hazard                        \
0122     ___ssnop;                           \
0123     ___ssnop;                           \
0124     ___ssnop;                           \
0125     ___ehb
0126 
0127 #define __back_to_back_c0_hazard                    \
0128     ___ssnop;                           \
0129     ___ssnop;                           \
0130     ___ssnop;                           \
0131     ___ehb
0132 
0133 /*
0134  * gcc has a tradition of misscompiling the previous construct using the
0135  * address of a label as argument to inline assembler.  Gas otoh has the
0136  * annoying difference between la and dla which are only usable for 32-bit
0137  * rsp. 64-bit code, so can't be used without conditional compilation.
0138  * The alternative is switching the assembler to 64-bit code which happens
0139  * to work right even for 32-bit code...
0140  */
0141 #define __instruction_hazard()                      \
0142 do {                                    \
0143     unsigned long tmp;                      \
0144                                     \
0145     __asm__ __volatile__(                       \
0146     "   .set    push                    \n" \
0147     "   .set    mips64r2                \n" \
0148     "   dla %0, 1f                  \n" \
0149     "   jr.hb   %0                  \n" \
0150     "   .set    pop                 \n" \
0151     "1:                         \n" \
0152     : "=r" (tmp));                          \
0153 } while (0)
0154 
0155 #define instruction_hazard()                        \
0156 do {                                    \
0157     if (cpu_has_mips_r2_r6)                     \
0158         __instruction_hazard();                 \
0159 } while (0)
0160 
0161 #elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \
0162     defined(CONFIG_CPU_LOONGSON2EF) || defined(CONFIG_CPU_LOONGSON64) || \
0163     defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_R5500)
0164 
0165 /*
0166  * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
0167  */
0168 
0169 #define __mtc0_tlbw_hazard
0170 
0171 #define __mtc0_tlbr_hazard
0172 
0173 #define __tlbw_use_hazard
0174 
0175 #define __tlb_read_hazard
0176 
0177 #define __tlb_probe_hazard
0178 
0179 #define __irq_enable_hazard
0180 
0181 #define __irq_disable_hazard
0182 
0183 #define __back_to_back_c0_hazard
0184 
0185 #define instruction_hazard() do { } while (0)
0186 
0187 #elif defined(CONFIG_CPU_SB1)
0188 
0189 /*
0190  * Mostly like R4000 for historic reasons
0191  */
0192 #define __mtc0_tlbw_hazard
0193 
0194 #define __mtc0_tlbr_hazard
0195 
0196 #define __tlbw_use_hazard
0197 
0198 #define __tlb_read_hazard
0199 
0200 #define __tlb_probe_hazard
0201 
0202 #define __irq_enable_hazard
0203 
0204 #define __irq_disable_hazard                        \
0205     ___ssnop;                           \
0206     ___ssnop;                           \
0207     ___ssnop
0208 
0209 #define __back_to_back_c0_hazard
0210 
0211 #define instruction_hazard() do { } while (0)
0212 
0213 #else
0214 
0215 /*
0216  * Finally the catchall case for all other processors including R4000, R4400,
0217  * R4600, R4700, R5000, RM7000, NEC VR41xx etc.
0218  *
0219  * The taken branch will result in a two cycle penalty for the two killed
0220  * instructions on R4000 / R4400.  Other processors only have a single cycle
0221  * hazard so this is nice trick to have an optimal code for a range of
0222  * processors.
0223  */
0224 #define __mtc0_tlbw_hazard                      \
0225     nop;                                \
0226     nop
0227 
0228 #define __mtc0_tlbr_hazard                      \
0229     nop;                                \
0230     nop
0231 
0232 #define __tlbw_use_hazard                       \
0233     nop;                                \
0234     nop;                                \
0235     nop
0236 
0237 #define __tlb_read_hazard                       \
0238     nop;                                \
0239     nop;                                \
0240     nop
0241 
0242 #define __tlb_probe_hazard                      \
0243     nop;                                \
0244     nop;                                \
0245     nop
0246 
0247 #define __irq_enable_hazard                     \
0248     ___ssnop;                           \
0249     ___ssnop;                           \
0250     ___ssnop
0251 
0252 #define __irq_disable_hazard                        \
0253     nop;                                \
0254     nop;                                \
0255     nop
0256 
0257 #define __back_to_back_c0_hazard                    \
0258     ___ssnop;                           \
0259     ___ssnop;                           \
0260     ___ssnop
0261 
0262 #define instruction_hazard() do { } while (0)
0263 
0264 #endif
0265 
0266 
0267 /* FPU hazards */
0268 
0269 #if defined(CONFIG_CPU_SB1)
0270 
0271 #define __enable_fpu_hazard                     \
0272     .set    push;                           \
0273     .set    mips64;                         \
0274     .set    noreorder;                      \
0275     ___ssnop;                           \
0276     bnezl   $0, .+4;                        \
0277     ___ssnop;                           \
0278     .set    pop
0279 
0280 #define __disable_fpu_hazard
0281 
0282 #elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR5) || \
0283       defined(CONFIG_CPU_MIPSR6)
0284 
0285 #define __enable_fpu_hazard                     \
0286     ___ehb
0287 
0288 #define __disable_fpu_hazard                        \
0289     ___ehb
0290 
0291 #else
0292 
0293 #define __enable_fpu_hazard                     \
0294     nop;                                \
0295     nop;                                \
0296     nop;                                \
0297     nop
0298 
0299 #define __disable_fpu_hazard                        \
0300     ___ehb
0301 
0302 #endif
0303 
0304 #ifdef __ASSEMBLY__
0305 
0306 #define _ssnop ___ssnop
0307 #define _ehb ___ehb
0308 #define mtc0_tlbw_hazard __mtc0_tlbw_hazard
0309 #define mtc0_tlbr_hazard __mtc0_tlbr_hazard
0310 #define tlbw_use_hazard __tlbw_use_hazard
0311 #define tlb_read_hazard __tlb_read_hazard
0312 #define tlb_probe_hazard __tlb_probe_hazard
0313 #define irq_enable_hazard __irq_enable_hazard
0314 #define irq_disable_hazard __irq_disable_hazard
0315 #define back_to_back_c0_hazard __back_to_back_c0_hazard
0316 #define enable_fpu_hazard __enable_fpu_hazard
0317 #define disable_fpu_hazard __disable_fpu_hazard
0318 
0319 #else
0320 
0321 #define _ssnop()                            \
0322 do {                                    \
0323     __asm__ __volatile__(                       \
0324     __stringify(___ssnop)                       \
0325     );                              \
0326 } while (0)
0327 
0328 #define _ehb()                              \
0329 do {                                    \
0330     __asm__ __volatile__(                       \
0331     __stringify(___ehb)                     \
0332     );                              \
0333 } while (0)
0334 
0335 
0336 #define mtc0_tlbw_hazard()                      \
0337 do {                                    \
0338     __asm__ __volatile__(                       \
0339     __stringify(__mtc0_tlbw_hazard)                 \
0340     );                              \
0341 } while (0)
0342 
0343 
0344 #define mtc0_tlbr_hazard()                      \
0345 do {                                    \
0346     __asm__ __volatile__(                       \
0347     __stringify(__mtc0_tlbr_hazard)                 \
0348     );                              \
0349 } while (0)
0350 
0351 
0352 #define tlbw_use_hazard()                       \
0353 do {                                    \
0354     __asm__ __volatile__(                       \
0355     __stringify(__tlbw_use_hazard)                  \
0356     );                              \
0357 } while (0)
0358 
0359 
0360 #define tlb_read_hazard()                       \
0361 do {                                    \
0362     __asm__ __volatile__(                       \
0363     __stringify(__tlb_read_hazard)                  \
0364     );                              \
0365 } while (0)
0366 
0367 
0368 #define tlb_probe_hazard()                      \
0369 do {                                    \
0370     __asm__ __volatile__(                       \
0371     __stringify(__tlb_probe_hazard)                 \
0372     );                              \
0373 } while (0)
0374 
0375 
0376 #define irq_enable_hazard()                     \
0377 do {                                    \
0378     __asm__ __volatile__(                       \
0379     __stringify(__irq_enable_hazard)                \
0380     );                              \
0381 } while (0)
0382 
0383 
0384 #define irq_disable_hazard()                        \
0385 do {                                    \
0386     __asm__ __volatile__(                       \
0387     __stringify(__irq_disable_hazard)               \
0388     );                              \
0389 } while (0)
0390 
0391 
0392 #define back_to_back_c0_hazard()                    \
0393 do {                                    \
0394     __asm__ __volatile__(                       \
0395     __stringify(__back_to_back_c0_hazard)               \
0396     );                              \
0397 } while (0)
0398 
0399 
0400 #define enable_fpu_hazard()                     \
0401 do {                                    \
0402     __asm__ __volatile__(                       \
0403     __stringify(__enable_fpu_hazard)                \
0404     );                              \
0405 } while (0)
0406 
0407 
0408 #define disable_fpu_hazard()                        \
0409 do {                                    \
0410     __asm__ __volatile__(                       \
0411     __stringify(__disable_fpu_hazard)               \
0412     );                              \
0413 } while (0)
0414 
0415 /*
0416  * MIPS R2 instruction hazard barrier.   Needs to be called as a subroutine.
0417  */
0418 extern void mips_ihb(void);
0419 
0420 #endif /* __ASSEMBLY__  */
0421 
0422 #endif /* _ASM_HAZARDS_H */