162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci#ifndef __ARCH_S390_PERCPU__ 362306a36Sopenharmony_ci#define __ARCH_S390_PERCPU__ 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/preempt.h> 662306a36Sopenharmony_ci#include <asm/cmpxchg.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * s390 uses its own implementation for per cpu data, the offset of 1062306a36Sopenharmony_ci * the cpu local data area is cached in the cpu's lowcore memory. 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci#define __my_cpu_offset S390_lowcore.percpu_offset 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* 1562306a36Sopenharmony_ci * For 64 bit module code, the module may be more than 4G above the 1662306a36Sopenharmony_ci * per cpu area, use weak definitions to force the compiler to 1762306a36Sopenharmony_ci * generate external references. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci#if defined(MODULE) 2062306a36Sopenharmony_ci#define ARCH_NEEDS_WEAK_PER_CPU 2162306a36Sopenharmony_ci#endif 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* 2462306a36Sopenharmony_ci * We use a compare-and-swap loop since that uses less cpu cycles than 2562306a36Sopenharmony_ci * disabling and enabling interrupts like the generic variant would do. 2662306a36Sopenharmony_ci */ 2762306a36Sopenharmony_ci#define arch_this_cpu_to_op_simple(pcp, val, op) \ 2862306a36Sopenharmony_ci({ \ 2962306a36Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 3062306a36Sopenharmony_ci pcp_op_T__ old__, new__, prev__; \ 3162306a36Sopenharmony_ci pcp_op_T__ *ptr__; \ 3262306a36Sopenharmony_ci preempt_disable_notrace(); \ 3362306a36Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 3462306a36Sopenharmony_ci prev__ = READ_ONCE(*ptr__); \ 3562306a36Sopenharmony_ci do { \ 3662306a36Sopenharmony_ci old__ = prev__; \ 3762306a36Sopenharmony_ci new__ = old__ op (val); \ 3862306a36Sopenharmony_ci prev__ = cmpxchg(ptr__, old__, new__); \ 3962306a36Sopenharmony_ci } while (prev__ != old__); \ 4062306a36Sopenharmony_ci preempt_enable_notrace(); \ 4162306a36Sopenharmony_ci new__; \ 4262306a36Sopenharmony_ci}) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci#define this_cpu_add_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 4562306a36Sopenharmony_ci#define this_cpu_add_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 4662306a36Sopenharmony_ci#define this_cpu_add_return_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 4762306a36Sopenharmony_ci#define this_cpu_add_return_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 4862306a36Sopenharmony_ci#define this_cpu_and_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, &) 4962306a36Sopenharmony_ci#define this_cpu_and_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, &) 5062306a36Sopenharmony_ci#define this_cpu_or_1(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) 5162306a36Sopenharmony_ci#define this_cpu_or_2(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#ifndef CONFIG_HAVE_MARCH_Z196_FEATURES 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define this_cpu_add_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 5662306a36Sopenharmony_ci#define this_cpu_add_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 5762306a36Sopenharmony_ci#define this_cpu_add_return_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 5862306a36Sopenharmony_ci#define this_cpu_add_return_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, +) 5962306a36Sopenharmony_ci#define this_cpu_and_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, &) 6062306a36Sopenharmony_ci#define this_cpu_and_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, &) 6162306a36Sopenharmony_ci#define this_cpu_or_4(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) 6262306a36Sopenharmony_ci#define this_cpu_or_8(pcp, val) arch_this_cpu_to_op_simple(pcp, val, |) 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci#else /* CONFIG_HAVE_MARCH_Z196_FEATURES */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define arch_this_cpu_add(pcp, val, op1, op2, szcast) \ 6762306a36Sopenharmony_ci{ \ 6862306a36Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 6962306a36Sopenharmony_ci pcp_op_T__ val__ = (val); \ 7062306a36Sopenharmony_ci pcp_op_T__ old__, *ptr__; \ 7162306a36Sopenharmony_ci preempt_disable_notrace(); \ 7262306a36Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 7362306a36Sopenharmony_ci if (__builtin_constant_p(val__) && \ 7462306a36Sopenharmony_ci ((szcast)val__ > -129) && ((szcast)val__ < 128)) { \ 7562306a36Sopenharmony_ci asm volatile( \ 7662306a36Sopenharmony_ci op2 " %[ptr__],%[val__]\n" \ 7762306a36Sopenharmony_ci : [ptr__] "+Q" (*ptr__) \ 7862306a36Sopenharmony_ci : [val__] "i" ((szcast)val__) \ 7962306a36Sopenharmony_ci : "cc"); \ 8062306a36Sopenharmony_ci } else { \ 8162306a36Sopenharmony_ci asm volatile( \ 8262306a36Sopenharmony_ci op1 " %[old__],%[val__],%[ptr__]\n" \ 8362306a36Sopenharmony_ci : [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \ 8462306a36Sopenharmony_ci : [val__] "d" (val__) \ 8562306a36Sopenharmony_ci : "cc"); \ 8662306a36Sopenharmony_ci } \ 8762306a36Sopenharmony_ci preempt_enable_notrace(); \ 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci#define this_cpu_add_4(pcp, val) arch_this_cpu_add(pcp, val, "laa", "asi", int) 9162306a36Sopenharmony_ci#define this_cpu_add_8(pcp, val) arch_this_cpu_add(pcp, val, "laag", "agsi", long) 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci#define arch_this_cpu_add_return(pcp, val, op) \ 9462306a36Sopenharmony_ci({ \ 9562306a36Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 9662306a36Sopenharmony_ci pcp_op_T__ val__ = (val); \ 9762306a36Sopenharmony_ci pcp_op_T__ old__, *ptr__; \ 9862306a36Sopenharmony_ci preempt_disable_notrace(); \ 9962306a36Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 10062306a36Sopenharmony_ci asm volatile( \ 10162306a36Sopenharmony_ci op " %[old__],%[val__],%[ptr__]\n" \ 10262306a36Sopenharmony_ci : [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \ 10362306a36Sopenharmony_ci : [val__] "d" (val__) \ 10462306a36Sopenharmony_ci : "cc"); \ 10562306a36Sopenharmony_ci preempt_enable_notrace(); \ 10662306a36Sopenharmony_ci old__ + val__; \ 10762306a36Sopenharmony_ci}) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define this_cpu_add_return_4(pcp, val) arch_this_cpu_add_return(pcp, val, "laa") 11062306a36Sopenharmony_ci#define this_cpu_add_return_8(pcp, val) arch_this_cpu_add_return(pcp, val, "laag") 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define arch_this_cpu_to_op(pcp, val, op) \ 11362306a36Sopenharmony_ci{ \ 11462306a36Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 11562306a36Sopenharmony_ci pcp_op_T__ val__ = (val); \ 11662306a36Sopenharmony_ci pcp_op_T__ old__, *ptr__; \ 11762306a36Sopenharmony_ci preempt_disable_notrace(); \ 11862306a36Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 11962306a36Sopenharmony_ci asm volatile( \ 12062306a36Sopenharmony_ci op " %[old__],%[val__],%[ptr__]\n" \ 12162306a36Sopenharmony_ci : [old__] "=d" (old__), [ptr__] "+Q" (*ptr__) \ 12262306a36Sopenharmony_ci : [val__] "d" (val__) \ 12362306a36Sopenharmony_ci : "cc"); \ 12462306a36Sopenharmony_ci preempt_enable_notrace(); \ 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci#define this_cpu_and_4(pcp, val) arch_this_cpu_to_op(pcp, val, "lan") 12862306a36Sopenharmony_ci#define this_cpu_and_8(pcp, val) arch_this_cpu_to_op(pcp, val, "lang") 12962306a36Sopenharmony_ci#define this_cpu_or_4(pcp, val) arch_this_cpu_to_op(pcp, val, "lao") 13062306a36Sopenharmony_ci#define this_cpu_or_8(pcp, val) arch_this_cpu_to_op(pcp, val, "laog") 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci#endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci#define arch_this_cpu_cmpxchg(pcp, oval, nval) \ 13562306a36Sopenharmony_ci({ \ 13662306a36Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 13762306a36Sopenharmony_ci pcp_op_T__ ret__; \ 13862306a36Sopenharmony_ci pcp_op_T__ *ptr__; \ 13962306a36Sopenharmony_ci preempt_disable_notrace(); \ 14062306a36Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 14162306a36Sopenharmony_ci ret__ = cmpxchg(ptr__, oval, nval); \ 14262306a36Sopenharmony_ci preempt_enable_notrace(); \ 14362306a36Sopenharmony_ci ret__; \ 14462306a36Sopenharmony_ci}) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci#define this_cpu_cmpxchg_1(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) 14762306a36Sopenharmony_ci#define this_cpu_cmpxchg_2(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) 14862306a36Sopenharmony_ci#define this_cpu_cmpxchg_4(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) 14962306a36Sopenharmony_ci#define this_cpu_cmpxchg_8(pcp, oval, nval) arch_this_cpu_cmpxchg(pcp, oval, nval) 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci#define this_cpu_cmpxchg64(pcp, o, n) this_cpu_cmpxchg_8(pcp, o, n) 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci#define this_cpu_cmpxchg128(pcp, oval, nval) \ 15462306a36Sopenharmony_ci({ \ 15562306a36Sopenharmony_ci typedef typeof(pcp) pcp_op_T__; \ 15662306a36Sopenharmony_ci u128 old__, new__, ret__; \ 15762306a36Sopenharmony_ci pcp_op_T__ *ptr__; \ 15862306a36Sopenharmony_ci old__ = oval; \ 15962306a36Sopenharmony_ci new__ = nval; \ 16062306a36Sopenharmony_ci preempt_disable_notrace(); \ 16162306a36Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 16262306a36Sopenharmony_ci ret__ = cmpxchg128((void *)ptr__, old__, new__); \ 16362306a36Sopenharmony_ci preempt_enable_notrace(); \ 16462306a36Sopenharmony_ci ret__; \ 16562306a36Sopenharmony_ci}) 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#define arch_this_cpu_xchg(pcp, nval) \ 16862306a36Sopenharmony_ci({ \ 16962306a36Sopenharmony_ci typeof(pcp) *ptr__; \ 17062306a36Sopenharmony_ci typeof(pcp) ret__; \ 17162306a36Sopenharmony_ci preempt_disable_notrace(); \ 17262306a36Sopenharmony_ci ptr__ = raw_cpu_ptr(&(pcp)); \ 17362306a36Sopenharmony_ci ret__ = xchg(ptr__, nval); \ 17462306a36Sopenharmony_ci preempt_enable_notrace(); \ 17562306a36Sopenharmony_ci ret__; \ 17662306a36Sopenharmony_ci}) 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#define this_cpu_xchg_1(pcp, nval) arch_this_cpu_xchg(pcp, nval) 17962306a36Sopenharmony_ci#define this_cpu_xchg_2(pcp, nval) arch_this_cpu_xchg(pcp, nval) 18062306a36Sopenharmony_ci#define this_cpu_xchg_4(pcp, nval) arch_this_cpu_xchg(pcp, nval) 18162306a36Sopenharmony_ci#define this_cpu_xchg_8(pcp, nval) arch_this_cpu_xchg(pcp, nval) 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci#include <asm-generic/percpu.h> 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci#endif /* __ARCH_S390_PERCPU__ */ 186