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