162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Generic barrier definitions. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * It should be possible to use these on really simple architectures, 662306a36Sopenharmony_ci * but it serves more as a starting point for new ports. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 962306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci#ifndef __ASM_GENERIC_BARRIER_H 1262306a36Sopenharmony_ci#define __ASM_GENERIC_BARRIER_H 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#ifndef __ASSEMBLY__ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/compiler.h> 1762306a36Sopenharmony_ci#include <linux/kcsan-checks.h> 1862306a36Sopenharmony_ci#include <asm/rwonce.h> 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#ifndef nop 2162306a36Sopenharmony_ci#define nop() asm volatile ("nop") 2262306a36Sopenharmony_ci#endif 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* 2562306a36Sopenharmony_ci * Architectures that want generic instrumentation can define __ prefixed 2662306a36Sopenharmony_ci * variants of all barriers. 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#ifdef __mb 3062306a36Sopenharmony_ci#define mb() do { kcsan_mb(); __mb(); } while (0) 3162306a36Sopenharmony_ci#endif 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#ifdef __rmb 3462306a36Sopenharmony_ci#define rmb() do { kcsan_rmb(); __rmb(); } while (0) 3562306a36Sopenharmony_ci#endif 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#ifdef __wmb 3862306a36Sopenharmony_ci#define wmb() do { kcsan_wmb(); __wmb(); } while (0) 3962306a36Sopenharmony_ci#endif 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#ifdef __dma_mb 4262306a36Sopenharmony_ci#define dma_mb() do { kcsan_mb(); __dma_mb(); } while (0) 4362306a36Sopenharmony_ci#endif 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#ifdef __dma_rmb 4662306a36Sopenharmony_ci#define dma_rmb() do { kcsan_rmb(); __dma_rmb(); } while (0) 4762306a36Sopenharmony_ci#endif 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#ifdef __dma_wmb 5062306a36Sopenharmony_ci#define dma_wmb() do { kcsan_wmb(); __dma_wmb(); } while (0) 5162306a36Sopenharmony_ci#endif 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci/* 5462306a36Sopenharmony_ci * Force strict CPU ordering. And yes, this is required on UP too when we're 5562306a36Sopenharmony_ci * talking to devices. 5662306a36Sopenharmony_ci * 5762306a36Sopenharmony_ci * Fall back to compiler barriers if nothing better is provided. 5862306a36Sopenharmony_ci */ 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci#ifndef mb 6162306a36Sopenharmony_ci#define mb() barrier() 6262306a36Sopenharmony_ci#endif 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#ifndef rmb 6562306a36Sopenharmony_ci#define rmb() mb() 6662306a36Sopenharmony_ci#endif 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci#ifndef wmb 6962306a36Sopenharmony_ci#define wmb() mb() 7062306a36Sopenharmony_ci#endif 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#ifndef dma_mb 7362306a36Sopenharmony_ci#define dma_mb() mb() 7462306a36Sopenharmony_ci#endif 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#ifndef dma_rmb 7762306a36Sopenharmony_ci#define dma_rmb() rmb() 7862306a36Sopenharmony_ci#endif 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#ifndef dma_wmb 8162306a36Sopenharmony_ci#define dma_wmb() wmb() 8262306a36Sopenharmony_ci#endif 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci#ifndef __smp_mb 8562306a36Sopenharmony_ci#define __smp_mb() mb() 8662306a36Sopenharmony_ci#endif 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#ifndef __smp_rmb 8962306a36Sopenharmony_ci#define __smp_rmb() rmb() 9062306a36Sopenharmony_ci#endif 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci#ifndef __smp_wmb 9362306a36Sopenharmony_ci#define __smp_wmb() wmb() 9462306a36Sopenharmony_ci#endif 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci#ifdef CONFIG_SMP 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci#ifndef smp_mb 9962306a36Sopenharmony_ci#define smp_mb() do { kcsan_mb(); __smp_mb(); } while (0) 10062306a36Sopenharmony_ci#endif 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci#ifndef smp_rmb 10362306a36Sopenharmony_ci#define smp_rmb() do { kcsan_rmb(); __smp_rmb(); } while (0) 10462306a36Sopenharmony_ci#endif 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#ifndef smp_wmb 10762306a36Sopenharmony_ci#define smp_wmb() do { kcsan_wmb(); __smp_wmb(); } while (0) 10862306a36Sopenharmony_ci#endif 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci#else /* !CONFIG_SMP */ 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#ifndef smp_mb 11362306a36Sopenharmony_ci#define smp_mb() barrier() 11462306a36Sopenharmony_ci#endif 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci#ifndef smp_rmb 11762306a36Sopenharmony_ci#define smp_rmb() barrier() 11862306a36Sopenharmony_ci#endif 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci#ifndef smp_wmb 12162306a36Sopenharmony_ci#define smp_wmb() barrier() 12262306a36Sopenharmony_ci#endif 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci#ifndef __smp_store_mb 12762306a36Sopenharmony_ci#define __smp_store_mb(var, value) do { WRITE_ONCE(var, value); __smp_mb(); } while (0) 12862306a36Sopenharmony_ci#endif 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci#ifndef __smp_mb__before_atomic 13162306a36Sopenharmony_ci#define __smp_mb__before_atomic() __smp_mb() 13262306a36Sopenharmony_ci#endif 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci#ifndef __smp_mb__after_atomic 13562306a36Sopenharmony_ci#define __smp_mb__after_atomic() __smp_mb() 13662306a36Sopenharmony_ci#endif 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci#ifndef __smp_store_release 13962306a36Sopenharmony_ci#define __smp_store_release(p, v) \ 14062306a36Sopenharmony_cido { \ 14162306a36Sopenharmony_ci compiletime_assert_atomic_type(*p); \ 14262306a36Sopenharmony_ci __smp_mb(); \ 14362306a36Sopenharmony_ci WRITE_ONCE(*p, v); \ 14462306a36Sopenharmony_ci} while (0) 14562306a36Sopenharmony_ci#endif 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci#ifndef __smp_load_acquire 14862306a36Sopenharmony_ci#define __smp_load_acquire(p) \ 14962306a36Sopenharmony_ci({ \ 15062306a36Sopenharmony_ci __unqual_scalar_typeof(*p) ___p1 = READ_ONCE(*p); \ 15162306a36Sopenharmony_ci compiletime_assert_atomic_type(*p); \ 15262306a36Sopenharmony_ci __smp_mb(); \ 15362306a36Sopenharmony_ci (typeof(*p))___p1; \ 15462306a36Sopenharmony_ci}) 15562306a36Sopenharmony_ci#endif 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci#ifdef CONFIG_SMP 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci#ifndef smp_store_mb 16062306a36Sopenharmony_ci#define smp_store_mb(var, value) do { kcsan_mb(); __smp_store_mb(var, value); } while (0) 16162306a36Sopenharmony_ci#endif 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci#ifndef smp_mb__before_atomic 16462306a36Sopenharmony_ci#define smp_mb__before_atomic() do { kcsan_mb(); __smp_mb__before_atomic(); } while (0) 16562306a36Sopenharmony_ci#endif 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#ifndef smp_mb__after_atomic 16862306a36Sopenharmony_ci#define smp_mb__after_atomic() do { kcsan_mb(); __smp_mb__after_atomic(); } while (0) 16962306a36Sopenharmony_ci#endif 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci#ifndef smp_store_release 17262306a36Sopenharmony_ci#define smp_store_release(p, v) do { kcsan_release(); __smp_store_release(p, v); } while (0) 17362306a36Sopenharmony_ci#endif 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci#ifndef smp_load_acquire 17662306a36Sopenharmony_ci#define smp_load_acquire(p) __smp_load_acquire(p) 17762306a36Sopenharmony_ci#endif 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci#else /* !CONFIG_SMP */ 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci#ifndef smp_store_mb 18262306a36Sopenharmony_ci#define smp_store_mb(var, value) do { WRITE_ONCE(var, value); barrier(); } while (0) 18362306a36Sopenharmony_ci#endif 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#ifndef smp_mb__before_atomic 18662306a36Sopenharmony_ci#define smp_mb__before_atomic() barrier() 18762306a36Sopenharmony_ci#endif 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci#ifndef smp_mb__after_atomic 19062306a36Sopenharmony_ci#define smp_mb__after_atomic() barrier() 19162306a36Sopenharmony_ci#endif 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci#ifndef smp_store_release 19462306a36Sopenharmony_ci#define smp_store_release(p, v) \ 19562306a36Sopenharmony_cido { \ 19662306a36Sopenharmony_ci compiletime_assert_atomic_type(*p); \ 19762306a36Sopenharmony_ci barrier(); \ 19862306a36Sopenharmony_ci WRITE_ONCE(*p, v); \ 19962306a36Sopenharmony_ci} while (0) 20062306a36Sopenharmony_ci#endif 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci#ifndef smp_load_acquire 20362306a36Sopenharmony_ci#define smp_load_acquire(p) \ 20462306a36Sopenharmony_ci({ \ 20562306a36Sopenharmony_ci __unqual_scalar_typeof(*p) ___p1 = READ_ONCE(*p); \ 20662306a36Sopenharmony_ci compiletime_assert_atomic_type(*p); \ 20762306a36Sopenharmony_ci barrier(); \ 20862306a36Sopenharmony_ci (typeof(*p))___p1; \ 20962306a36Sopenharmony_ci}) 21062306a36Sopenharmony_ci#endif 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci#endif /* CONFIG_SMP */ 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci/* Barriers for virtual machine guests when talking to an SMP host */ 21562306a36Sopenharmony_ci#define virt_mb() do { kcsan_mb(); __smp_mb(); } while (0) 21662306a36Sopenharmony_ci#define virt_rmb() do { kcsan_rmb(); __smp_rmb(); } while (0) 21762306a36Sopenharmony_ci#define virt_wmb() do { kcsan_wmb(); __smp_wmb(); } while (0) 21862306a36Sopenharmony_ci#define virt_store_mb(var, value) do { kcsan_mb(); __smp_store_mb(var, value); } while (0) 21962306a36Sopenharmony_ci#define virt_mb__before_atomic() do { kcsan_mb(); __smp_mb__before_atomic(); } while (0) 22062306a36Sopenharmony_ci#define virt_mb__after_atomic() do { kcsan_mb(); __smp_mb__after_atomic(); } while (0) 22162306a36Sopenharmony_ci#define virt_store_release(p, v) do { kcsan_release(); __smp_store_release(p, v); } while (0) 22262306a36Sopenharmony_ci#define virt_load_acquire(p) __smp_load_acquire(p) 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci/** 22562306a36Sopenharmony_ci * smp_acquire__after_ctrl_dep() - Provide ACQUIRE ordering after a control dependency 22662306a36Sopenharmony_ci * 22762306a36Sopenharmony_ci * A control dependency provides a LOAD->STORE order, the additional RMB 22862306a36Sopenharmony_ci * provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order, 22962306a36Sopenharmony_ci * aka. (load)-ACQUIRE. 23062306a36Sopenharmony_ci * 23162306a36Sopenharmony_ci * Architectures that do not do load speculation can have this be barrier(). 23262306a36Sopenharmony_ci */ 23362306a36Sopenharmony_ci#ifndef smp_acquire__after_ctrl_dep 23462306a36Sopenharmony_ci#define smp_acquire__after_ctrl_dep() smp_rmb() 23562306a36Sopenharmony_ci#endif 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci/** 23862306a36Sopenharmony_ci * smp_cond_load_relaxed() - (Spin) wait for cond with no ordering guarantees 23962306a36Sopenharmony_ci * @ptr: pointer to the variable to wait on 24062306a36Sopenharmony_ci * @cond: boolean expression to wait for 24162306a36Sopenharmony_ci * 24262306a36Sopenharmony_ci * Equivalent to using READ_ONCE() on the condition variable. 24362306a36Sopenharmony_ci * 24462306a36Sopenharmony_ci * Due to C lacking lambda expressions we load the value of *ptr into a 24562306a36Sopenharmony_ci * pre-named variable @VAL to be used in @cond. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci#ifndef smp_cond_load_relaxed 24862306a36Sopenharmony_ci#define smp_cond_load_relaxed(ptr, cond_expr) ({ \ 24962306a36Sopenharmony_ci typeof(ptr) __PTR = (ptr); \ 25062306a36Sopenharmony_ci __unqual_scalar_typeof(*ptr) VAL; \ 25162306a36Sopenharmony_ci for (;;) { \ 25262306a36Sopenharmony_ci VAL = READ_ONCE(*__PTR); \ 25362306a36Sopenharmony_ci if (cond_expr) \ 25462306a36Sopenharmony_ci break; \ 25562306a36Sopenharmony_ci cpu_relax(); \ 25662306a36Sopenharmony_ci } \ 25762306a36Sopenharmony_ci (typeof(*ptr))VAL; \ 25862306a36Sopenharmony_ci}) 25962306a36Sopenharmony_ci#endif 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci/** 26262306a36Sopenharmony_ci * smp_cond_load_acquire() - (Spin) wait for cond with ACQUIRE ordering 26362306a36Sopenharmony_ci * @ptr: pointer to the variable to wait on 26462306a36Sopenharmony_ci * @cond: boolean expression to wait for 26562306a36Sopenharmony_ci * 26662306a36Sopenharmony_ci * Equivalent to using smp_load_acquire() on the condition variable but employs 26762306a36Sopenharmony_ci * the control dependency of the wait to reduce the barrier on many platforms. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci#ifndef smp_cond_load_acquire 27062306a36Sopenharmony_ci#define smp_cond_load_acquire(ptr, cond_expr) ({ \ 27162306a36Sopenharmony_ci __unqual_scalar_typeof(*ptr) _val; \ 27262306a36Sopenharmony_ci _val = smp_cond_load_relaxed(ptr, cond_expr); \ 27362306a36Sopenharmony_ci smp_acquire__after_ctrl_dep(); \ 27462306a36Sopenharmony_ci (typeof(*ptr))_val; \ 27562306a36Sopenharmony_ci}) 27662306a36Sopenharmony_ci#endif 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci/* 27962306a36Sopenharmony_ci * pmem_wmb() ensures that all stores for which the modification 28062306a36Sopenharmony_ci * are written to persistent storage by preceding instructions have 28162306a36Sopenharmony_ci * updated persistent storage before any data access or data transfer 28262306a36Sopenharmony_ci * caused by subsequent instructions is initiated. 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_ci#ifndef pmem_wmb 28562306a36Sopenharmony_ci#define pmem_wmb() wmb() 28662306a36Sopenharmony_ci#endif 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/* 28962306a36Sopenharmony_ci * ioremap_wc() maps I/O memory as memory with write-combining attributes. For 29062306a36Sopenharmony_ci * this kind of memory accesses, the CPU may wait for prior accesses to be 29162306a36Sopenharmony_ci * merged with subsequent ones. In some situation, such wait is bad for the 29262306a36Sopenharmony_ci * performance. io_stop_wc() can be used to prevent the merging of 29362306a36Sopenharmony_ci * write-combining memory accesses before this macro with those after it. 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_ci#ifndef io_stop_wc 29662306a36Sopenharmony_ci#define io_stop_wc() do { } while (0) 29762306a36Sopenharmony_ci#endif 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */ 30062306a36Sopenharmony_ci#endif /* __ASM_GENERIC_BARRIER_H */ 301