18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Generic barrier definitions.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * It should be possible to use these on really simple architectures,
68c2ecf20Sopenharmony_ci * but it serves more as a starting point for new ports.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
98c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci#ifndef __ASM_GENERIC_BARRIER_H
128c2ecf20Sopenharmony_ci#define __ASM_GENERIC_BARRIER_H
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#ifndef __ASSEMBLY__
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include <linux/compiler.h>
178c2ecf20Sopenharmony_ci#include <asm/rwonce.h>
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#ifndef nop
208c2ecf20Sopenharmony_ci#define nop()	asm volatile ("nop")
218c2ecf20Sopenharmony_ci#endif
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/*
248c2ecf20Sopenharmony_ci * Force strict CPU ordering. And yes, this is required on UP too when we're
258c2ecf20Sopenharmony_ci * talking to devices.
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci * Fall back to compiler barriers if nothing better is provided.
288c2ecf20Sopenharmony_ci */
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci#ifndef mb
318c2ecf20Sopenharmony_ci#define mb()	barrier()
328c2ecf20Sopenharmony_ci#endif
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#ifndef rmb
358c2ecf20Sopenharmony_ci#define rmb()	mb()
368c2ecf20Sopenharmony_ci#endif
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#ifndef wmb
398c2ecf20Sopenharmony_ci#define wmb()	mb()
408c2ecf20Sopenharmony_ci#endif
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#ifndef dma_rmb
438c2ecf20Sopenharmony_ci#define dma_rmb()	rmb()
448c2ecf20Sopenharmony_ci#endif
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#ifndef dma_wmb
478c2ecf20Sopenharmony_ci#define dma_wmb()	wmb()
488c2ecf20Sopenharmony_ci#endif
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#ifndef __smp_mb
518c2ecf20Sopenharmony_ci#define __smp_mb()	mb()
528c2ecf20Sopenharmony_ci#endif
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#ifndef __smp_rmb
558c2ecf20Sopenharmony_ci#define __smp_rmb()	rmb()
568c2ecf20Sopenharmony_ci#endif
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci#ifndef __smp_wmb
598c2ecf20Sopenharmony_ci#define __smp_wmb()	wmb()
608c2ecf20Sopenharmony_ci#endif
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci#ifndef smp_mb
658c2ecf20Sopenharmony_ci#define smp_mb()	__smp_mb()
668c2ecf20Sopenharmony_ci#endif
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#ifndef smp_rmb
698c2ecf20Sopenharmony_ci#define smp_rmb()	__smp_rmb()
708c2ecf20Sopenharmony_ci#endif
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#ifndef smp_wmb
738c2ecf20Sopenharmony_ci#define smp_wmb()	__smp_wmb()
748c2ecf20Sopenharmony_ci#endif
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci#else	/* !CONFIG_SMP */
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci#ifndef smp_mb
798c2ecf20Sopenharmony_ci#define smp_mb()	barrier()
808c2ecf20Sopenharmony_ci#endif
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci#ifndef smp_rmb
838c2ecf20Sopenharmony_ci#define smp_rmb()	barrier()
848c2ecf20Sopenharmony_ci#endif
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci#ifndef smp_wmb
878c2ecf20Sopenharmony_ci#define smp_wmb()	barrier()
888c2ecf20Sopenharmony_ci#endif
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci#endif	/* CONFIG_SMP */
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci#ifndef __smp_store_mb
938c2ecf20Sopenharmony_ci#define __smp_store_mb(var, value)  do { WRITE_ONCE(var, value); __smp_mb(); } while (0)
948c2ecf20Sopenharmony_ci#endif
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#ifndef __smp_mb__before_atomic
978c2ecf20Sopenharmony_ci#define __smp_mb__before_atomic()	__smp_mb()
988c2ecf20Sopenharmony_ci#endif
998c2ecf20Sopenharmony_ci
1008c2ecf20Sopenharmony_ci#ifndef __smp_mb__after_atomic
1018c2ecf20Sopenharmony_ci#define __smp_mb__after_atomic()	__smp_mb()
1028c2ecf20Sopenharmony_ci#endif
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci#ifndef __smp_store_release
1058c2ecf20Sopenharmony_ci#define __smp_store_release(p, v)					\
1068c2ecf20Sopenharmony_cido {									\
1078c2ecf20Sopenharmony_ci	compiletime_assert_atomic_type(*p);				\
1088c2ecf20Sopenharmony_ci	__smp_mb();							\
1098c2ecf20Sopenharmony_ci	WRITE_ONCE(*p, v);						\
1108c2ecf20Sopenharmony_ci} while (0)
1118c2ecf20Sopenharmony_ci#endif
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#ifndef __smp_load_acquire
1148c2ecf20Sopenharmony_ci#define __smp_load_acquire(p)						\
1158c2ecf20Sopenharmony_ci({									\
1168c2ecf20Sopenharmony_ci	__unqual_scalar_typeof(*p) ___p1 = READ_ONCE(*p);		\
1178c2ecf20Sopenharmony_ci	compiletime_assert_atomic_type(*p);				\
1188c2ecf20Sopenharmony_ci	__smp_mb();							\
1198c2ecf20Sopenharmony_ci	(typeof(*p))___p1;						\
1208c2ecf20Sopenharmony_ci})
1218c2ecf20Sopenharmony_ci#endif
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci#ifndef smp_store_mb
1268c2ecf20Sopenharmony_ci#define smp_store_mb(var, value)  __smp_store_mb(var, value)
1278c2ecf20Sopenharmony_ci#endif
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci#ifndef smp_mb__before_atomic
1308c2ecf20Sopenharmony_ci#define smp_mb__before_atomic()	__smp_mb__before_atomic()
1318c2ecf20Sopenharmony_ci#endif
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci#ifndef smp_mb__after_atomic
1348c2ecf20Sopenharmony_ci#define smp_mb__after_atomic()	__smp_mb__after_atomic()
1358c2ecf20Sopenharmony_ci#endif
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci#ifndef smp_store_release
1388c2ecf20Sopenharmony_ci#define smp_store_release(p, v) __smp_store_release(p, v)
1398c2ecf20Sopenharmony_ci#endif
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci#ifndef smp_load_acquire
1428c2ecf20Sopenharmony_ci#define smp_load_acquire(p) __smp_load_acquire(p)
1438c2ecf20Sopenharmony_ci#endif
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci#else	/* !CONFIG_SMP */
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci#ifndef smp_store_mb
1488c2ecf20Sopenharmony_ci#define smp_store_mb(var, value)  do { WRITE_ONCE(var, value); barrier(); } while (0)
1498c2ecf20Sopenharmony_ci#endif
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci#ifndef smp_mb__before_atomic
1528c2ecf20Sopenharmony_ci#define smp_mb__before_atomic()	barrier()
1538c2ecf20Sopenharmony_ci#endif
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci#ifndef smp_mb__after_atomic
1568c2ecf20Sopenharmony_ci#define smp_mb__after_atomic()	barrier()
1578c2ecf20Sopenharmony_ci#endif
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci#ifndef smp_store_release
1608c2ecf20Sopenharmony_ci#define smp_store_release(p, v)						\
1618c2ecf20Sopenharmony_cido {									\
1628c2ecf20Sopenharmony_ci	compiletime_assert_atomic_type(*p);				\
1638c2ecf20Sopenharmony_ci	barrier();							\
1648c2ecf20Sopenharmony_ci	WRITE_ONCE(*p, v);						\
1658c2ecf20Sopenharmony_ci} while (0)
1668c2ecf20Sopenharmony_ci#endif
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci#ifndef smp_load_acquire
1698c2ecf20Sopenharmony_ci#define smp_load_acquire(p)						\
1708c2ecf20Sopenharmony_ci({									\
1718c2ecf20Sopenharmony_ci	__unqual_scalar_typeof(*p) ___p1 = READ_ONCE(*p);		\
1728c2ecf20Sopenharmony_ci	compiletime_assert_atomic_type(*p);				\
1738c2ecf20Sopenharmony_ci	barrier();							\
1748c2ecf20Sopenharmony_ci	(typeof(*p))___p1;						\
1758c2ecf20Sopenharmony_ci})
1768c2ecf20Sopenharmony_ci#endif
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci#endif	/* CONFIG_SMP */
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci/* Barriers for virtual machine guests when talking to an SMP host */
1818c2ecf20Sopenharmony_ci#define virt_mb() __smp_mb()
1828c2ecf20Sopenharmony_ci#define virt_rmb() __smp_rmb()
1838c2ecf20Sopenharmony_ci#define virt_wmb() __smp_wmb()
1848c2ecf20Sopenharmony_ci#define virt_store_mb(var, value) __smp_store_mb(var, value)
1858c2ecf20Sopenharmony_ci#define virt_mb__before_atomic() __smp_mb__before_atomic()
1868c2ecf20Sopenharmony_ci#define virt_mb__after_atomic()	__smp_mb__after_atomic()
1878c2ecf20Sopenharmony_ci#define virt_store_release(p, v) __smp_store_release(p, v)
1888c2ecf20Sopenharmony_ci#define virt_load_acquire(p) __smp_load_acquire(p)
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci/**
1918c2ecf20Sopenharmony_ci * smp_acquire__after_ctrl_dep() - Provide ACQUIRE ordering after a control dependency
1928c2ecf20Sopenharmony_ci *
1938c2ecf20Sopenharmony_ci * A control dependency provides a LOAD->STORE order, the additional RMB
1948c2ecf20Sopenharmony_ci * provides LOAD->LOAD order, together they provide LOAD->{LOAD,STORE} order,
1958c2ecf20Sopenharmony_ci * aka. (load)-ACQUIRE.
1968c2ecf20Sopenharmony_ci *
1978c2ecf20Sopenharmony_ci * Architectures that do not do load speculation can have this be barrier().
1988c2ecf20Sopenharmony_ci */
1998c2ecf20Sopenharmony_ci#ifndef smp_acquire__after_ctrl_dep
2008c2ecf20Sopenharmony_ci#define smp_acquire__after_ctrl_dep()		smp_rmb()
2018c2ecf20Sopenharmony_ci#endif
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci/**
2048c2ecf20Sopenharmony_ci * smp_cond_load_relaxed() - (Spin) wait for cond with no ordering guarantees
2058c2ecf20Sopenharmony_ci * @ptr: pointer to the variable to wait on
2068c2ecf20Sopenharmony_ci * @cond: boolean expression to wait for
2078c2ecf20Sopenharmony_ci *
2088c2ecf20Sopenharmony_ci * Equivalent to using READ_ONCE() on the condition variable.
2098c2ecf20Sopenharmony_ci *
2108c2ecf20Sopenharmony_ci * Due to C lacking lambda expressions we load the value of *ptr into a
2118c2ecf20Sopenharmony_ci * pre-named variable @VAL to be used in @cond.
2128c2ecf20Sopenharmony_ci */
2138c2ecf20Sopenharmony_ci#ifndef smp_cond_load_relaxed
2148c2ecf20Sopenharmony_ci#define smp_cond_load_relaxed(ptr, cond_expr) ({		\
2158c2ecf20Sopenharmony_ci	typeof(ptr) __PTR = (ptr);				\
2168c2ecf20Sopenharmony_ci	__unqual_scalar_typeof(*ptr) VAL;			\
2178c2ecf20Sopenharmony_ci	for (;;) {						\
2188c2ecf20Sopenharmony_ci		VAL = READ_ONCE(*__PTR);			\
2198c2ecf20Sopenharmony_ci		if (cond_expr)					\
2208c2ecf20Sopenharmony_ci			break;					\
2218c2ecf20Sopenharmony_ci		cpu_relax();					\
2228c2ecf20Sopenharmony_ci	}							\
2238c2ecf20Sopenharmony_ci	(typeof(*ptr))VAL;					\
2248c2ecf20Sopenharmony_ci})
2258c2ecf20Sopenharmony_ci#endif
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_ci/**
2288c2ecf20Sopenharmony_ci * smp_cond_load_acquire() - (Spin) wait for cond with ACQUIRE ordering
2298c2ecf20Sopenharmony_ci * @ptr: pointer to the variable to wait on
2308c2ecf20Sopenharmony_ci * @cond: boolean expression to wait for
2318c2ecf20Sopenharmony_ci *
2328c2ecf20Sopenharmony_ci * Equivalent to using smp_load_acquire() on the condition variable but employs
2338c2ecf20Sopenharmony_ci * the control dependency of the wait to reduce the barrier on many platforms.
2348c2ecf20Sopenharmony_ci */
2358c2ecf20Sopenharmony_ci#ifndef smp_cond_load_acquire
2368c2ecf20Sopenharmony_ci#define smp_cond_load_acquire(ptr, cond_expr) ({		\
2378c2ecf20Sopenharmony_ci	__unqual_scalar_typeof(*ptr) _val;			\
2388c2ecf20Sopenharmony_ci	_val = smp_cond_load_relaxed(ptr, cond_expr);		\
2398c2ecf20Sopenharmony_ci	smp_acquire__after_ctrl_dep();				\
2408c2ecf20Sopenharmony_ci	(typeof(*ptr))_val;					\
2418c2ecf20Sopenharmony_ci})
2428c2ecf20Sopenharmony_ci#endif
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci/*
2458c2ecf20Sopenharmony_ci * pmem_wmb() ensures that all stores for which the modification
2468c2ecf20Sopenharmony_ci * are written to persistent storage by preceding instructions have
2478c2ecf20Sopenharmony_ci * updated persistent storage before any data  access or data transfer
2488c2ecf20Sopenharmony_ci * caused by subsequent instructions is initiated.
2498c2ecf20Sopenharmony_ci */
2508c2ecf20Sopenharmony_ci#ifndef pmem_wmb
2518c2ecf20Sopenharmony_ci#define pmem_wmb()	wmb()
2528c2ecf20Sopenharmony_ci#endif
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci#endif /* !__ASSEMBLY__ */
2558c2ecf20Sopenharmony_ci#endif /* __ASM_GENERIC_BARRIER_H */
256