18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci#ifndef __ARCH_S390_PERCPU__ 38c2ecf20Sopenharmony_ci#define __ARCH_S390_PERCPU__ 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ci#include <linux/preempt.h> 68c2ecf20Sopenharmony_ci#include <asm/cmpxchg.h> 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * s390 uses its own implementation for per cpu data, the offset of 108c2ecf20Sopenharmony_ci * the cpu local data area is cached in the cpu's lowcore memory. 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci#define __my_cpu_offset S390_lowcore.percpu_offset 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci/* 158c2ecf20Sopenharmony_ci * For 64 bit module code, the module may be more than 4G above the 168c2ecf20Sopenharmony_ci * per cpu area, use weak definitions to force the compiler to 178c2ecf20Sopenharmony_ci * generate external references. 188c2ecf20Sopenharmony_ci */ 198c2ecf20Sopenharmony_ci#if defined(MODULE) 208c2ecf20Sopenharmony_ci#define ARCH_NEEDS_WEAK_PER_CPU 218c2ecf20Sopenharmony_ci#endif 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci/* 248c2ecf20Sopenharmony_ci * We use a compare-and-swap loop since that uses less cpu cycles than 258c2ecf20Sopenharmony_ci * disabling and enabling interrupts like the generic variant would do. 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci#define arch_this_cpu_to_op_simple(pcp, val, op) \ 288c2ecf20Sopenharmony_ci({ \ 298c2ecf20Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 308c2ecf20Sopenharmony_ci pcp_op_T__ old__, new__, prev__; \ 318c2ecf20Sopenharmony_ci pcp_op_T__ *ptr__; \ 328c2ecf20Sopenharmony_ci preempt_disable_notrace(); \ 338c2ecf20Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 348c2ecf20Sopenharmony_ci prev__ = READ_ONCE(*ptr__); \ 358c2ecf20Sopenharmony_ci do { \ 368c2ecf20Sopenharmony_ci old__ = prev__; \ 378c2ecf20Sopenharmony_ci new__ = old__ op (val); \ 388c2ecf20Sopenharmony_ci prev__ = cmpxchg(ptr__, old__, new__); \ 398c2ecf20Sopenharmony_ci } while (prev__ != old__); \ 408c2ecf20Sopenharmony_ci preempt_enable_notrace(); \ 418c2ecf20Sopenharmony_ci new__; \ 428c2ecf20Sopenharmony_ci}) 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci#define this_cpu_add_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 458c2ecf20Sopenharmony_ci#define this_cpu_add_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 468c2ecf20Sopenharmony_ci#define this_cpu_add_return_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 478c2ecf20Sopenharmony_ci#define this_cpu_add_return_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 488c2ecf20Sopenharmony_ci#define this_cpu_and_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, &) 498c2ecf20Sopenharmony_ci#define this_cpu_and_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, &) 508c2ecf20Sopenharmony_ci#define this_cpu_or_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) 518c2ecf20Sopenharmony_ci#define this_cpu_or_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#ifndef CONFIG_HAVE_MARCH_Z196_FEATURES 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define this_cpu_add_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 568c2ecf20Sopenharmony_ci#define this_cpu_add_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 578c2ecf20Sopenharmony_ci#define this_cpu_add_return_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 588c2ecf20Sopenharmony_ci#define this_cpu_add_return_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 598c2ecf20Sopenharmony_ci#define this_cpu_and_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, &) 608c2ecf20Sopenharmony_ci#define this_cpu_and_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, &) 618c2ecf20Sopenharmony_ci#define this_cpu_or_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) 628c2ecf20Sopenharmony_ci#define this_cpu_or_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define arch_this_cpu_add(pcp, val, op1, op2, szcast) \ 678c2ecf20Sopenharmony_ci{ \ 688c2ecf20Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 698c2ecf20Sopenharmony_ci pcp_op_T__ val__ = (val); \ 708c2ecf20Sopenharmony_ci pcp_op_T__ old__, *ptr__; \ 718c2ecf20Sopenharmony_ci preempt_disable_notrace(); \ 728c2ecf20Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 738c2ecf20Sopenharmony_ci if (__builtin_constant_p(val__) && \ 748c2ecf20Sopenharmony_ci ((szcast)val__ > -129) && ((szcast)val__ < 128)) { \ 758c2ecf20Sopenharmony_ci asm volatile( \ 768c2ecf20Sopenharmony_ci op2 " %[ptr__],%[val__]\n" \ 778c2ecf20Sopenharmony_ci : [ptr__] "+Q" (*ptr__) \ 788c2ecf20Sopenharmony_ci : [val__] "i" ((szcast)val__) \ 798c2ecf20Sopenharmony_ci : "cc"); \ 808c2ecf20Sopenharmony_ci } else { \ 818c2ecf20Sopenharmony_ci asm volatile( \ 828c2ecf20Sopenharmony_ci op1 " %[old__],%[val__],%[ptr__]\n" \ 838c2ecf20Sopenharmony_ci : [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \ 848c2ecf20Sopenharmony_ci : [val__] "d" (val__) \ 858c2ecf20Sopenharmony_ci : "cc"); \ 868c2ecf20Sopenharmony_ci } \ 878c2ecf20Sopenharmony_ci preempt_enable_notrace(); \ 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci#define this_cpu_add_4(pcp, val) arch_this_cpu_add(pcp, val, "laa", "asi", int) 918c2ecf20Sopenharmony_ci#define this_cpu_add_8(pcp, val) arch_this_cpu_add(pcp, val, "laag", "agsi", long) 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci#define arch_this_cpu_add_return(pcp, val, op) \ 948c2ecf20Sopenharmony_ci({ \ 958c2ecf20Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 968c2ecf20Sopenharmony_ci pcp_op_T__ val__ = (val); \ 978c2ecf20Sopenharmony_ci pcp_op_T__ old__, *ptr__; \ 988c2ecf20Sopenharmony_ci preempt_disable_notrace(); \ 998c2ecf20Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 1008c2ecf20Sopenharmony_ci asm volatile( \ 1018c2ecf20Sopenharmony_ci op " %[old__],%[val__],%[ptr__]\n" \ 1028c2ecf20Sopenharmony_ci : [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \ 1038c2ecf20Sopenharmony_ci : [val__] "d" (val__) \ 1048c2ecf20Sopenharmony_ci : "cc"); \ 1058c2ecf20Sopenharmony_ci preempt_enable_notrace(); \ 1068c2ecf20Sopenharmony_ci old__ + val__; \ 1078c2ecf20Sopenharmony_ci}) 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci#define this_cpu_add_return_4(pcp, val) arch_this_cpu_add_return(pcp, val, "laa") 1108c2ecf20Sopenharmony_ci#define this_cpu_add_return_8(pcp, val) arch_this_cpu_add_return(pcp, val, "laag") 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci#define arch_this_cpu_to_op(pcp, val, op) \ 1138c2ecf20Sopenharmony_ci{ \ 1148c2ecf20Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 1158c2ecf20Sopenharmony_ci pcp_op_T__ val__ = (val); \ 1168c2ecf20Sopenharmony_ci pcp_op_T__ old__, *ptr__; \ 1178c2ecf20Sopenharmony_ci preempt_disable_notrace(); \ 1188c2ecf20Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 1198c2ecf20Sopenharmony_ci asm volatile( \ 1208c2ecf20Sopenharmony_ci op " %[old__],%[val__],%[ptr__]\n" \ 1218c2ecf20Sopenharmony_ci : [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \ 1228c2ecf20Sopenharmony_ci : [val__] "d" (val__) \ 1238c2ecf20Sopenharmony_ci : "cc"); \ 1248c2ecf20Sopenharmony_ci preempt_enable_notrace(); \ 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci#define this_cpu_and_4(pcp, val) arch_this_cpu_to_op(pcp, val, "lan") 1288c2ecf20Sopenharmony_ci#define this_cpu_and_8(pcp, val) arch_this_cpu_to_op(pcp, val, "lang") 1298c2ecf20Sopenharmony_ci#define this_cpu_or_4(pcp, val) arch_this_cpu_to_op(pcp, val, "lao") 1308c2ecf20Sopenharmony_ci#define this_cpu_or_8(pcp, val) arch_this_cpu_to_op(pcp, val, "laog") 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci#define arch_this_cpu_cmpxchg(pcp, oval, nval) \ 1358c2ecf20Sopenharmony_ci({ \ 1368c2ecf20Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 1378c2ecf20Sopenharmony_ci pcp_op_T__ ret__; \ 1388c2ecf20Sopenharmony_ci pcp_op_T__ *ptr__; \ 1398c2ecf20Sopenharmony_ci preempt_disable_notrace(); \ 1408c2ecf20Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 1418c2ecf20Sopenharmony_ci ret__ = cmpxchg(ptr__, oval, nval); \ 1428c2ecf20Sopenharmony_ci preempt_enable_notrace(); \ 1438c2ecf20Sopenharmony_ci ret__; \ 1448c2ecf20Sopenharmony_ci}) 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci#define this_cpu_cmpxchg_1(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) 1478c2ecf20Sopenharmony_ci#define this_cpu_cmpxchg_2(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) 1488c2ecf20Sopenharmony_ci#define this_cpu_cmpxchg_4(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) 1498c2ecf20Sopenharmony_ci#define this_cpu_cmpxchg_8(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci#define arch_this_cpu_xchg(pcp, nval) \ 1528c2ecf20Sopenharmony_ci({ \ 1538c2ecf20Sopenharmony_ci typeof(pcp) *ptr__; \ 1548c2ecf20Sopenharmony_ci typeof(pcp) ret__; \ 1558c2ecf20Sopenharmony_ci preempt_disable_notrace(); \ 1568c2ecf20Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 1578c2ecf20Sopenharmony_ci ret__ = xchg(ptr__, nval); \ 1588c2ecf20Sopenharmony_ci preempt_enable_notrace(); \ 1598c2ecf20Sopenharmony_ci ret__; \ 1608c2ecf20Sopenharmony_ci}) 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci#define this_cpu_xchg_1(pcp, nval) arch_this_cpu_xchg(pcp, nval) 1638c2ecf20Sopenharmony_ci#define this_cpu_xchg_2(pcp, nval) arch_this_cpu_xchg(pcp, nval) 1648c2ecf20Sopenharmony_ci#define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval) 1658c2ecf20Sopenharmony_ci#define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval) 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci#define arch_this_cpu_cmpxchg_double(pcp1, pcp2, o1, o2, n1, n2) \ 1688c2ecf20Sopenharmony_ci({ \ 1698c2ecf20Sopenharmony_ci typeof(pcp1) o1__ = (o1), n1__ = (n1); \ 1708c2ecf20Sopenharmony_ci typeof(pcp2) o2__ = (o2), n2__ = (n2); \ 1718c2ecf20Sopenharmony_ci typeof(pcp1) *p1__; \ 1728c2ecf20Sopenharmony_ci typeof(pcp2) *p2__; \ 1738c2ecf20Sopenharmony_ci int ret__; \ 1748c2ecf20Sopenharmony_ci preempt_disable_notrace(); \ 1758c2ecf20Sopenharmony_ci p1__ = raw_cpu_ptr(&(pcp1)); \ 1768c2ecf20Sopenharmony_ci p2__ = raw_cpu_ptr(&(pcp2)); \ 1778c2ecf20Sopenharmony_ci ret__ = __cmpxchg_double(p1__, p2__, o1__, o2__, n1__, n2__); \ 1788c2ecf20Sopenharmony_ci preempt_enable_notrace(); \ 1798c2ecf20Sopenharmony_ci ret__; \ 1808c2ecf20Sopenharmony_ci}) 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci#define this_cpu_cmpxchg_double_8 arch_this_cpu_cmpxchg_double 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci#include <asm-generic/percpu.h> 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci#endif /* __ARCH_S390_PERCPU__ */ 187