]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/percpu: Provide arch_this_cpu_read() implementation
authorHeiko Carstens <hca@linux.ibm.com>
Tue, 26 May 2026 05:57:01 +0000 (07:57 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Wed, 3 Jun 2026 13:32:47 +0000 (15:32 +0200)
Provide an s390 specific implementation of arch_this_cpu_read() instead
of the generic variant. The generic variant uses preempt_disable() /
preempt_enable() pair and READ_ONCE().

Get rid of the preempt_disable() / preempt_enable() pairs by providing an
own variant which makes use of the new percpu code section infrastructure.

With this the text size of the kernel image is reduced by ~1k
(defconfig). Also 87 generated preempt_schedule_notrace() function
calls within the kernel image (modules not counted) are removed.

Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/include/asm/percpu.h

index 5e0185e5960b03decd9895e4e688a651289f3083..83195a5dc409d890ddedf072fb5e653a7975fb66 100644 (file)
@@ -248,6 +248,37 @@ do {                                                                       \
 
 #endif /* MARCH_HAS_Z196_FEATURES */
 
+#define arch_this_cpu_read(pcp, op)                                    \
+({                                                                     \
+       unsigned long lc_pcpr, lc_pcpo, res__;                          \
+       typedef typeof(pcp) pcp_op_T__;                                 \
+       pcp_op_T__ *ptr__;                                              \
+                                                                       \
+       lc_pcpr = offsetof(struct lowcore, percpu_register);            \
+       lc_pcpo = offsetof(struct lowcore, percpu_offset);              \
+       ptr__ = PERCPU_PTR(&(pcp));                                     \
+       asm_inline volatile(                                            \
+               MVIY_PERCPU("%[disppcpr]", "%[dispaltpcpr]", "%[ptr__]")\
+               AG_ALT("%[disppcpo]", "%[dispaltpcpo]", "%[ptr__]")     \
+               op "    %[res__],0(%[ptr__])\n"                         \
+               MVIY_ALT("%[disppcpr]", "%[dispaltpcpr]")               \
+               : [res__] "=&d" (res__), [ptr__] "+&a" (ptr__),         \
+                 "=m" (((struct lowcore *)0)->percpu_register)         \
+               : [disppcpr] "i" (lc_pcpr),                             \
+                 [disppcpo] "i" (lc_pcpo),                             \
+                 [dispaltpcpr] "i" (lc_pcpr + LOWCORE_ALT_ADDRESS),    \
+                 [dispaltpcpo] "i" (lc_pcpo + LOWCORE_ALT_ADDRESS),    \
+                 "m" (*ptr__),                                         \
+                 "m" (((struct lowcore *)0)->percpu_offset)            \
+               : "cc");                                                \
+       (pcp_op_T__)res__;                                              \
+})
+
+#define this_cpu_read_1(pcp) arch_this_cpu_read(pcp, "llgc")
+#define this_cpu_read_2(pcp) arch_this_cpu_read(pcp, "llgh")
+#define this_cpu_read_4(pcp) arch_this_cpu_read(pcp, "llgf")
+#define this_cpu_read_8(pcp) arch_this_cpu_read(pcp, "lg")
+
 #define arch_this_cpu_cmpxchg(pcp, oval, nval)                         \
 ({                                                                     \
        typedef typeof(pcp) pcp_op_T__;                                 \