linux/arch/mips/include/asm/hazards.h
<<
>>
Prefs
   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 *
   6 * Copyright (C) 2003, 04, 07 Ralf Baechle <ralf@linux-mips.org>
   7 * Copyright (C) MIPS Technologies, Inc.
   8 *   written by Ralf Baechle <ralf@linux-mips.org>
   9 */
  10#ifndef _ASM_HAZARDS_H
  11#define _ASM_HAZARDS_H
  12
  13#include <linux/stringify.h>
  14#include <asm/compiler.h>
  15
  16#define ___ssnop                                                        \
  17        sll     $0, $0, 1
  18
  19#define ___ehb                                                          \
  20        sll     $0, $0, 3
  21
  22/*
  23 * TLB hazards
  24 */
  25#if (defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)) && \
  26        !defined(CONFIG_CPU_CAVIUM_OCTEON) && !defined(CONFIG_LOONGSON3_ENHANCEMENT)
  27
  28/*
  29 * MIPSR2 defines ehb for hazard avoidance
  30 */
  31
  32#define __mtc0_tlbw_hazard                                              \
  33        ___ehb
  34
  35#define __mtc0_tlbr_hazard                                              \
  36        ___ehb
  37
  38#define __tlbw_use_hazard                                               \
  39        ___ehb
  40
  41#define __tlb_read_hazard                                               \
  42        ___ehb
  43
  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
  56/*
  57 * gcc has a tradition of misscompiling the previous construct using the
  58 * address of a label as argument to inline assembler.  Gas otoh has the
  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.
  61 * The alternative is switching the assembler to 64-bit code which happens
  62 * to work right even for 32-bit code...
  63 */
  64#define instruction_hazard()                                            \
  65do {                                                                    \
  66        unsigned long tmp;                                              \
  67                                                                        \
  68        __asm__ __volatile__(                                           \
  69        "       .set "MIPS_ISA_LEVEL"                           \n"     \
  70        "       dla     %0, 1f                                  \n"     \
  71        "       jr.hb   %0                                      \n"     \
  72        "       .set    mips0                                   \n"     \
  73        "1:                                                     \n"     \
  74        : "=r" (tmp));                                                  \
  75} while (0)
  76
  77#elif (defined(CONFIG_CPU_MIPSR1) && !defined(CONFIG_MIPS_ALCHEMY)) || \
  78        defined(CONFIG_CPU_BMIPS)
  79
  80/*
  81 * These are slightly complicated by the fact that we guarantee R1 kernels to
  82 * run fine on R2 processors.
  83 */
  84
  85#define __mtc0_tlbw_hazard                                              \
  86        ___ssnop;                                                       \
  87        ___ssnop;                                                       \
  88        ___ehb
  89
  90#define __mtc0_tlbr_hazard                                              \
  91        ___ssnop;                                                       \
  92        ___ssnop;                                                       \
  93        ___ehb
  94
  95#define __tlbw_use_hazard                                               \
  96        ___ssnop;                                                       \
  97        ___ssnop;                                                       \
  98        ___ssnop;                                                       \
  99        ___ehb
 100
 101#define __tlb_read_hazard                                               \
 102        ___ssnop;                                                       \
 103        ___ssnop;                                                       \
 104        ___ssnop;                                                       \
 105        ___ehb
 106
 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
 131/*
 132 * gcc has a tradition of misscompiling the previous construct using the
 133 * address of a label as argument to inline assembler.  Gas otoh has the
 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.
 136 * The alternative is switching the assembler to 64-bit code which happens
 137 * to work right even for 32-bit code...
 138 */
 139#define __instruction_hazard()                                          \
 140do {                                                                    \
 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()                                            \
 153do {                                                                    \
 154        if (cpu_has_mips_r2_r6)                                         \
 155                __instruction_hazard();                                 \
 156} while (0)
 157
 158#elif defined(CONFIG_MIPS_ALCHEMY) || defined(CONFIG_CPU_CAVIUM_OCTEON) || \
 159        defined(CONFIG_CPU_LOONGSON2) || defined(CONFIG_LOONGSON3_ENHANCEMENT) || \
 160        defined(CONFIG_CPU_R10000) || defined(CONFIG_CPU_R5500) || defined(CONFIG_CPU_XLR)
 161
 162/*
 163 * R10000 rocks - all hazards handled in hardware, so this becomes a nobrainer.
 164 */
 165
 166#define __mtc0_tlbw_hazard
 167
 168#define __mtc0_tlbr_hazard
 169
 170#define __tlbw_use_hazard
 171
 172#define __tlb_read_hazard
 173
 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
 182#define instruction_hazard() do { } while (0)
 183
 184#elif defined(CONFIG_CPU_SB1)
 185
 186/*
 187 * Mostly like R4000 for historic reasons
 188 */
 189#define __mtc0_tlbw_hazard
 190
 191#define __mtc0_tlbr_hazard
 192
 193#define __tlbw_use_hazard
 194
 195#define __tlb_read_hazard
 196
 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
 208#define instruction_hazard() do { } while (0)
 209
 210#else
 211
 212/*
 213 * Finally the catchall case for all other processors including R4000, R4400,
 214 * R4600, R4700, R5000, RM7000, NEC VR41xx etc.
 215 *
 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.
 220 */
 221#define __mtc0_tlbw_hazard                                              \
 222        nop;                                                            \
 223        nop
 224
 225#define __mtc0_tlbr_hazard                                              \
 226        nop;                                                            \
 227        nop
 228
 229#define __tlbw_use_hazard                                               \
 230        nop;                                                            \
 231        nop;                                                            \
 232        nop
 233
 234#define __tlb_read_hazard                                               \
 235        nop;                                                            \
 236        nop;                                                            \
 237        nop
 238
 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
 259#define instruction_hazard() do { } while (0)
 260
 261#endif
 262
 263
 264/* FPU hazards */
 265
 266#if defined(CONFIG_CPU_SB1)
 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
 278
 279#elif defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
 280
 281#define __enable_fpu_hazard                                             \
 282        ___ehb
 283
 284#define __disable_fpu_hazard                                            \
 285        ___ehb
 286
 287#else
 288
 289#define __enable_fpu_hazard                                             \
 290        nop;                                                            \
 291        nop;                                                            \
 292        nop;                                                            \
 293        nop
 294
 295#define __disable_fpu_hazard                                            \
 296        ___ehb
 297
 298#endif
 299
 300#ifdef __ASSEMBLY__
 301
 302#define _ssnop ___ssnop
 303#define _ehb ___ehb
 304#define mtc0_tlbw_hazard __mtc0_tlbw_hazard
 305#define mtc0_tlbr_hazard __mtc0_tlbr_hazard
 306#define tlbw_use_hazard __tlbw_use_hazard
 307#define tlb_read_hazard __tlb_read_hazard
 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()                                                        \
 318do {                                                                    \
 319        __asm__ __volatile__(                                           \
 320        __stringify(___ssnop)                                           \
 321        );                                                              \
 322} while (0)
 323
 324#define _ehb()                                                          \
 325do {                                                                    \
 326        __asm__ __volatile__(                                           \
 327        __stringify(___ehb)                                             \
 328        );                                                              \
 329} while (0)
 330
 331
 332#define mtc0_tlbw_hazard()                                              \
 333do {                                                                    \
 334        __asm__ __volatile__(                                           \
 335        __stringify(__mtc0_tlbw_hazard)                                 \
 336        );                                                              \
 337} while (0)
 338
 339
 340#define mtc0_tlbr_hazard()                                              \
 341do {                                                                    \
 342        __asm__ __volatile__(                                           \
 343        __stringify(__mtc0_tlbr_hazard)                                 \
 344        );                                                              \
 345} while (0)
 346
 347
 348#define tlbw_use_hazard()                                               \
 349do {                                                                    \
 350        __asm__ __volatile__(                                           \
 351        __stringify(__tlbw_use_hazard)                                  \
 352        );                                                              \
 353} while (0)
 354
 355
 356#define tlb_read_hazard()                                               \
 357do {                                                                    \
 358        __asm__ __volatile__(                                           \
 359        __stringify(__tlb_read_hazard)                                  \
 360        );                                                              \
 361} while (0)
 362
 363
 364#define tlb_probe_hazard()                                              \
 365do {                                                                    \
 366        __asm__ __volatile__(                                           \
 367        __stringify(__tlb_probe_hazard)                                 \
 368        );                                                              \
 369} while (0)
 370
 371
 372#define irq_enable_hazard()                                             \
 373do {                                                                    \
 374        __asm__ __volatile__(                                           \
 375        __stringify(__irq_enable_hazard)                                \
 376        );                                                              \
 377} while (0)
 378
 379
 380#define irq_disable_hazard()                                            \
 381do {                                                                    \
 382        __asm__ __volatile__(                                           \
 383        __stringify(__irq_disable_hazard)                               \
 384        );                                                              \
 385} while (0)
 386
 387
 388#define back_to_back_c0_hazard()                                        \
 389do {                                                                    \
 390        __asm__ __volatile__(                                           \
 391        __stringify(__back_to_back_c0_hazard)                           \
 392        );                                                              \
 393} while (0)
 394
 395
 396#define enable_fpu_hazard()                                             \
 397do {                                                                    \
 398        __asm__ __volatile__(                                           \
 399        __stringify(__enable_fpu_hazard)                                \
 400        );                                                              \
 401} while (0)
 402
 403
 404#define disable_fpu_hazard()                                            \
 405do {                                                                    \
 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 */
 414extern void mips_ihb(void);
 415
 416#endif /* __ASSEMBLY__  */
 417
 418#endif /* _ASM_HAZARDS_H */
 419