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