]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/percpu: Provide arch_this_cpu_write() implementation
authorHeiko Carstens <hca@linux.ibm.com>
Tue, 26 May 2026 05:57:02 +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_write()
instead of the generic variant. The generic variant uses a quite
expensive raw_local_irq_save() / raw_local_irq_restore() pair.

Get rid of this 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).

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 83195a5dc409d890ddedf072fb5e653a7975fb66..1d955dd0defa3f878525b115c0b4de9d8401fb22 100644 (file)
@@ -279,6 +279,36 @@ do {                                                                       \
 #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_write(pcp, val, op)                              \
+do {                                                                   \
+       unsigned long lc_pcpr, lc_pcpo;                                 \
+       typedef typeof(pcp) pcp_op_T__;                                 \
+       pcp_op_T__ *ptr__, val__ = (val);                               \
+                                                                       \
+       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 "    %[val__],0(%[ptr__])\n"                         \
+               MVIY_ALT("%[disppcpr]", "%[dispaltpcpr]")               \
+               : [ptr__] "+&a" (ptr__), "=m" (*ptr__),                 \
+                 "=m" (((struct lowcore *)0)->percpu_register)         \
+               : [val__] "d" (val__),                                  \
+                 [disppcpr] "i" (lc_pcpr),                             \
+                 [disppcpo] "i" (lc_pcpo),                             \
+                 [dispaltpcpr] "i" (lc_pcpr + LOWCORE_ALT_ADDRESS),    \
+                 [dispaltpcpo] "i" (lc_pcpo + LOWCORE_ALT_ADDRESS),    \
+                 "m" (((struct lowcore *)0)->percpu_offset)            \
+               : "cc");                                                \
+} while (0)
+
+#define this_cpu_write_1(pcp, val) arch_this_cpu_write(pcp, val, "stc")
+#define this_cpu_write_2(pcp, val) arch_this_cpu_write(pcp, val, "sth")
+#define this_cpu_write_4(pcp, val) arch_this_cpu_write(pcp, val, "st")
+#define this_cpu_write_8(pcp, val) arch_this_cpu_write(pcp, val, "stg")
+
 #define arch_this_cpu_cmpxchg(pcp, oval, nval)                         \
 ({                                                                     \
        typedef typeof(pcp) pcp_op_T__;                                 \