1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun #ifndef __SPARC64_BARRIER_H 3*4882a593Smuzhiyun #define __SPARC64_BARRIER_H 4*4882a593Smuzhiyun 5*4882a593Smuzhiyun /* These are here in an effort to more fully work around Spitfire Errata 6*4882a593Smuzhiyun * #51. Essentially, if a memory barrier occurs soon after a mispredicted 7*4882a593Smuzhiyun * branch, the chip can stop executing instructions until a trap occurs. 8*4882a593Smuzhiyun * Therefore, if interrupts are disabled, the chip can hang forever. 9*4882a593Smuzhiyun * 10*4882a593Smuzhiyun * It used to be believed that the memory barrier had to be right in the 11*4882a593Smuzhiyun * delay slot, but a case has been traced recently wherein the memory barrier 12*4882a593Smuzhiyun * was one instruction after the branch delay slot and the chip still hung. 13*4882a593Smuzhiyun * The offending sequence was the following in sym_wakeup_done() of the 14*4882a593Smuzhiyun * sym53c8xx_2 driver: 15*4882a593Smuzhiyun * 16*4882a593Smuzhiyun * call sym_ccb_from_dsa, 0 17*4882a593Smuzhiyun * movge %icc, 0, %l0 18*4882a593Smuzhiyun * brz,pn %o0, .LL1303 19*4882a593Smuzhiyun * mov %o0, %l2 20*4882a593Smuzhiyun * membar #LoadLoad 21*4882a593Smuzhiyun * 22*4882a593Smuzhiyun * The branch has to be mispredicted for the bug to occur. Therefore, we put 23*4882a593Smuzhiyun * the memory barrier explicitly into a "branch always, predicted taken" 24*4882a593Smuzhiyun * delay slot to avoid the problem case. 25*4882a593Smuzhiyun */ 26*4882a593Smuzhiyun #define membar_safe(type) \ 27*4882a593Smuzhiyun do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ 28*4882a593Smuzhiyun " membar " type "\n" \ 29*4882a593Smuzhiyun "1:\n" \ 30*4882a593Smuzhiyun : : : "memory"); \ 31*4882a593Smuzhiyun } while (0) 32*4882a593Smuzhiyun 33*4882a593Smuzhiyun /* The kernel always executes in TSO memory model these days, 34*4882a593Smuzhiyun * and furthermore most sparc64 chips implement more stringent 35*4882a593Smuzhiyun * memory ordering than required by the specifications. 36*4882a593Smuzhiyun */ 37*4882a593Smuzhiyun #define mb() membar_safe("#StoreLoad") 38*4882a593Smuzhiyun #define rmb() __asm__ __volatile__("":::"memory") 39*4882a593Smuzhiyun #define wmb() __asm__ __volatile__("":::"memory") 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun #define __smp_store_release(p, v) \ 42*4882a593Smuzhiyun do { \ 43*4882a593Smuzhiyun compiletime_assert_atomic_type(*p); \ 44*4882a593Smuzhiyun barrier(); \ 45*4882a593Smuzhiyun WRITE_ONCE(*p, v); \ 46*4882a593Smuzhiyun } while (0) 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun #define __smp_load_acquire(p) \ 49*4882a593Smuzhiyun ({ \ 50*4882a593Smuzhiyun typeof(*p) ___p1 = READ_ONCE(*p); \ 51*4882a593Smuzhiyun compiletime_assert_atomic_type(*p); \ 52*4882a593Smuzhiyun barrier(); \ 53*4882a593Smuzhiyun ___p1; \ 54*4882a593Smuzhiyun }) 55*4882a593Smuzhiyun 56*4882a593Smuzhiyun #define __smp_mb__before_atomic() barrier() 57*4882a593Smuzhiyun #define __smp_mb__after_atomic() barrier() 58*4882a593Smuzhiyun 59*4882a593Smuzhiyun #include <asm-generic/barrier.h> 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun #endif /* !(__SPARC64_BARRIER_H) */ 62