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