* [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures
@ 2026-09-11 19:25 Bradley Morgan
2026-09-11 19:25 ` [PATCH 1/6] lib: Add two-byte cmpxchg emulation function Bradley Morgan
` (6 more replies)
0 siblings, 7 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 19:25 UTC (permalink / raw)
To: Paul E. McKenney
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel, brads
Paul McKenney asked me off list to add cmpxchg_emu_u16() next to
cmpxchg_emu_u8() and wire it into the architectures that use the
one byte emulation, arc, ARMv6, csky, sh and xtensa.
Patch 1 adds the function, the prototype, and renames the Kconfig
symbol to ARCH_NEED_CMPXCHG_1_2_EMU since it now gates both
emulations. Patches 2 through 6 add case 2 beside each existing
case 1, following each file's current style. The function body
follows the two byte implementation in Paul's April 2024 RFC
series, of which only the one byte part landed as commit
a88d970c8bb5 ("lib: Add one-byte emulation function").
Per Paul's note, Arnd Bergmann's platform removal series was
checked before analyzing the users. It removes the imx31 and
omap24xx CPU_ARM1136R0 selectors, but INTEGRATOR_CM1136JFS still
selects CPU_ARM1136R0 until its scheduled removal in early 2027,
so the ARMv6 path in patch 3 is still live. The arc !LLSC path
already handles any size because it reads and writes through the
typed pointer under the atomic_ops lock, so only the LLSC switch
gains case 2.
Verification. The union splice is endian independent because h[i]
sits at byte offset 2*i on both layouts and i is (addr & 2) / 2,
so the selected halfword always matches the caller's byte offset.
A host test ran 240 cases across both halfword offsets, matching
and mismatching compares, against a byte level reference model,
all passing. The function also compiles big endian for ARM, which
matters because sh is a big endian user. lib/cmpxchg-emu.o builds
for arm with CONFIG_CPU_V6 and a test instantiation of cmpxchg()
on a u16 resolves to cmpxchg_emu_u16. The remaining checkpatch
warnings are the volatile and long line ones that the merged
cmpxchg_emu_u8() lines already carry.
Bradley Morgan (6):
lib: Add two-byte cmpxchg emulation function
ARC: Emulate two-byte cmpxchg
ARM: Emulate two-byte cmpxchg on ARMv6
csky: Emulate two-byte cmpxchg
sh: Emulate two-byte cmpxchg
xtensa: Emulate two-byte cmpxchg
arch/Kconfig | 2 +-
arch/arc/Kconfig | 2 +-
arch/arc/include/asm/cmpxchg.h | 3 +++
arch/arm/Kconfig | 2 +-
arch/arm/include/asm/cmpxchg.h | 3 +++
arch/csky/Kconfig | 2 +-
arch/csky/include/asm/cmpxchg.h | 9 ++++++++
arch/sh/Kconfig | 2 +-
arch/sh/include/asm/cmpxchg.h | 2 ++
arch/xtensa/Kconfig | 2 +-
arch/xtensa/include/asm/cmpxchg.h | 1 +
include/linux/cmpxchg-emu.h | 1 +
lib/Makefile | 2 +-
lib/cmpxchg-emu.c | 35 ++++++++++++++++++++++++++++---
14 files changed, 58 insertions(+), 10 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/6] lib: Add two-byte cmpxchg emulation function
2026-09-11 19:25 [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
@ 2026-09-11 19:25 ` Bradley Morgan
2026-09-11 22:10 ` David Laight
2026-09-11 19:25 ` [PATCH 2/6] ARC: Emulate two-byte cmpxchg Bradley Morgan
` (5 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 19:25 UTC (permalink / raw)
To: Paul E. McKenney
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel, brads
cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
cmpxchg() for the architectures lacking native one-byte atomics.
The same architectures also lack native two-byte cmpxchg(), where
such an operation is not supported and either fails to compile via
BUILD_BUG() or fails to link, because the bad pointer sentinels
these architectures declare are never defined.
Add cmpxchg_emu_u16(), the two-byte sibling. It reads the enclosing
word with READ_ONCE(), splices the two target bytes through a union
and loops on cmpxchg() of the full word until the compare succeeds.
Like cmpxchg_emu_u8() it is fully ordered.
The Kconfig symbol gating this file is renamed from
ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
selects both the one-byte and the two-byte emulation.
Suggested-by: Paul E. McKenney <paulmck@kernel.org>
Signed-off-by: Bradley Morgan <brads@mainlining.org>
---
arch/Kconfig | 2 +-
arch/arc/Kconfig | 2 +-
arch/arm/Kconfig | 2 +-
arch/csky/Kconfig | 2 +-
arch/sh/Kconfig | 2 +-
arch/xtensa/Kconfig | 2 +-
include/linux/cmpxchg-emu.h | 1 +
lib/Makefile | 2 +-
lib/cmpxchg-emu.c | 35 ++++++++++++++++++++++++++++++++---
9 files changed, 40 insertions(+), 10 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig
index 3bb2e568f5b1..d56064797e09 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -1817,7 +1817,7 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT
# strict alignment always, even with -falign-functions.
def_bool CC_HAS_MIN_FUNCTION_ALIGNMENT || CC_IS_CLANG
-config ARCH_NEED_CMPXCHG_1_EMU
+config ARCH_NEED_CMPXCHG_1_2_EMU
bool
config ARCH_WANTS_PRE_LINK_VMLINUX
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 80e61175bf52..0e91d254eccb 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -14,7 +14,7 @@ config ARC
select ARCH_HAS_SETUP_DMA_OPS
select ARCH_HAS_SYNC_DMA_FOR_CPU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
- select ARCH_NEED_CMPXCHG_1_EMU
+ select ARCH_NEED_CMPXCHG_1_2_EMU
select ARCH_SUPPORTS_ATOMIC_RMW if ARC_HAS_LLSC
select ARCH_32BIT_OFF_T
select BUILDTIME_TABLE_SORT
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 408aa58a2a5b..8fef4238d411 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -38,7 +38,7 @@ config ARM
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
- select ARCH_NEED_CMPXCHG_1_EMU if CPU_V6
+ select ARCH_NEED_CMPXCHG_1_2_EMU if CPU_V6
select ARCH_SUPPORTS_ATOMIC_RMW
select ARCH_SUPPORTS_CFI
select ARCH_SUPPORTS_HUGETLBFS if ARM_LPAE
diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig
index 4331313a42ff..5f26e8615d7d 100644
--- a/arch/csky/Kconfig
+++ b/arch/csky/Kconfig
@@ -37,7 +37,7 @@ config CSKY
select ARCH_INLINE_SPIN_UNLOCK_BH if !PREEMPTION
select ARCH_INLINE_SPIN_UNLOCK_IRQ if !PREEMPTION
select ARCH_INLINE_SPIN_UNLOCK_IRQRESTORE if !PREEMPTION
- select ARCH_NEED_CMPXCHG_1_EMU
+ select ARCH_NEED_CMPXCHG_1_2_EMU
select ARCH_WANT_FRAME_POINTERS if !CPU_CK610 && $(cc-option,-mbacktrace)
select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT
select COMMON_CLK
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index d60f1d5a94c0..09e556fced01 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -14,7 +14,7 @@ config SUPERH
select ARCH_HIBERNATION_POSSIBLE if MMU
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_WANT_IPC_PARSE_VERSION
- select ARCH_NEED_CMPXCHG_1_EMU
+ select ARCH_NEED_CMPXCHG_1_2_EMU
select CPU_NO_EFFICIENT_FFS
select DMA_DECLARE_COHERENT
select GENERIC_ATOMIC64
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index f2f9cd9cde50..62019fd444d4 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -14,7 +14,7 @@ config XTENSA
select ARCH_HAS_DMA_SET_UNCACHED if MMU
select ARCH_HAS_STRNCPY_FROM_USER if !KASAN
select ARCH_HAS_STRNLEN_USER
- select ARCH_NEED_CMPXCHG_1_EMU
+ select ARCH_NEED_CMPXCHG_1_2_EMU
select ARCH_USE_MEMTEST
select ARCH_USE_QUEUED_RWLOCKS
select ARCH_USE_QUEUED_SPINLOCKS
diff --git a/include/linux/cmpxchg-emu.h b/include/linux/cmpxchg-emu.h
index 998deec67740..fee8171fa05e 100644
--- a/include/linux/cmpxchg-emu.h
+++ b/include/linux/cmpxchg-emu.h
@@ -11,5 +11,6 @@
#define __LINUX_CMPXCHG_EMU_H
uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new);
+uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old, uintptr_t new);
#endif /* __LINUX_CMPXCHG_EMU_H */
diff --git a/lib/Makefile b/lib/Makefile
index 43421c39d21b..d0e69312176a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -202,7 +202,7 @@ obj-$(CONFIG_CODE_TAGGING) += codetag.o
lib-$(CONFIG_GENERIC_BUG) += bug.o
obj-$(CONFIG_HAVE_ARCH_TRACEHOOK) += syscall.o
-obj-$(CONFIG_ARCH_NEED_CMPXCHG_1_EMU) += cmpxchg-emu.o
+obj-$(CONFIG_ARCH_NEED_CMPXCHG_1_2_EMU) += cmpxchg-emu.o
obj-$(CONFIG_DYNAMIC_DEBUG_CORE) += dynamic_debug.o
#ensure exported functions have prototypes
diff --git a/lib/cmpxchg-emu.c b/lib/cmpxchg-emu.c
index 27f6f97cb60d..991a5969f471 100644
--- a/lib/cmpxchg-emu.c
+++ b/lib/cmpxchg-emu.c
@@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * Emulated 1-byte cmpxchg operation for architectures lacking direct
- * support for this size. This is implemented in terms of 4-byte cmpxchg
- * operations.
+ * Emulated 1-byte and 2-byte cmpxchg operations for architectures lacking
+ * direct support for these sizes. These are implemented in terms of
+ * 4-byte cmpxchg operations.
*
* Copyright (C) 2024 Paul E. McKenney.
*/
@@ -43,3 +43,32 @@ uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new)
return old;
}
EXPORT_SYMBOL_GPL(cmpxchg_emu_u8);
+
+union u16_32 {
+ u16 h[2];
+ u32 w;
+};
+
+/* Emulate two-byte cmpxchg() in terms of 4-byte cmpxchg. */
+uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old, uintptr_t new)
+{
+ u32 *p32 = (u32 *)(((uintptr_t)p) & ~0x3);
+ int i = (((uintptr_t)p) & 0x2) / 2;
+ union u16_32 old32;
+ union u16_32 new32;
+ u32 ret;
+
+ WARN_ON_ONCE(((uintptr_t)p) & 0x1);
+ ret = READ_ONCE(*p32);
+ do {
+ old32.w = ret;
+ if (old32.h[i] != old)
+ return old32.h[i];
+ new32.w = old32.w;
+ new32.h[i] = new;
+ instrument_atomic_read_write(p, 2);
+ ret = data_race(cmpxchg(p32, old32.w, new32.w)); // Overridden above.
+ } while (ret != old32.w);
+ return old;
+}
+EXPORT_SYMBOL_GPL(cmpxchg_emu_u16);
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 2/6] ARC: Emulate two-byte cmpxchg
2026-09-11 19:25 [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
2026-09-11 19:25 ` [PATCH 1/6] lib: Add two-byte cmpxchg emulation function Bradley Morgan
@ 2026-09-11 19:25 ` Bradley Morgan
2026-09-11 19:25 ` [PATCH 3/6] ARM: Emulate two-byte cmpxchg on ARMv6 Bradley Morgan
` (4 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 19:25 UTC (permalink / raw)
To: Paul E. McKenney
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel, brads
arc has no byte or halfword atomic memory operations, so the LLSC
arch_cmpxchg_relaxed() switch routes case 1 through cmpxchg_emu_u8()
and leaves case 2 to fall into the BUILD_BUG() default. Route case 2
through the new cmpxchg_emu_u16() instead.
The !CONFIG_ARC_HAS_LLSC arch_cmpxchg() already handles any size,
reading and writing through the typed pointer under the atomic_ops
lock, so it needs no change.
Signed-off-by: Bradley Morgan <brads@mainlining.org>
---
arch/arc/include/asm/cmpxchg.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h
index 76f43db0890f..9b48b8fe0db2 100644
--- a/arch/arc/include/asm/cmpxchg.h
+++ b/arch/arc/include/asm/cmpxchg.h
@@ -50,6 +50,9 @@
case 1: \
_prev_ = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *__force)_p_, (uintptr_t)_o_, (uintptr_t)_n_); \
break; \
+ case 2: \
+ _prev_ = (__typeof__(*(ptr)))cmpxchg_emu_u16((volatile u16 *__force)_p_, (uintptr_t)_o_, (uintptr_t)_n_); \
+ break; \
case 4: \
_prev_ = __cmpxchg(_p_, _o_, _n_); \
break; \
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 3/6] ARM: Emulate two-byte cmpxchg on ARMv6
2026-09-11 19:25 [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
2026-09-11 19:25 ` [PATCH 1/6] lib: Add two-byte cmpxchg emulation function Bradley Morgan
2026-09-11 19:25 ` [PATCH 2/6] ARC: Emulate two-byte cmpxchg Bradley Morgan
@ 2026-09-11 19:25 ` Bradley Morgan
2026-09-11 19:25 ` [PATCH 4/6] csky: Emulate two-byte cmpxchg Bradley Morgan
` (3 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 19:25 UTC (permalink / raw)
To: Paul E. McKenney
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel, brads
ARMv6 without the ARMv6K extensions, selected as CONFIG_CPU_V6,
has no ldrexh/strexh, so the __cmpxchg() switch only provides
case 1 through cmpxchg_emu_u8() and lets case 2 fall through to
__bad_cmpxchg(). Route case 2 through cmpxchg_emu_u16() so that
two-byte cmpxchg() works on these cores too.
ARMv6K and later already have native case 2 in the #else branch,
and __cmpxchg_local() already covers sizes 1 and 2 for ARMv6 via
__generic_cmpxchg_local(), so neither is touched.
Signed-off-by: Bradley Morgan <brads@mainlining.org>
---
arch/arm/include/asm/cmpxchg.h | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h
index 9beb64d30586..6c0e2f21456b 100644
--- a/arch/arm/include/asm/cmpxchg.h
+++ b/arch/arm/include/asm/cmpxchg.h
@@ -167,6 +167,9 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
case 1:
oldval = cmpxchg_emu_u8((volatile u8 *)ptr, old, new);
break;
+ case 2:
+ oldval = cmpxchg_emu_u16((volatile u16 *)ptr, old, new);
+ break;
#else /* min ARCH > ARMv6 */
case 1:
do {
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 4/6] csky: Emulate two-byte cmpxchg
2026-09-11 19:25 [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
` (2 preceding siblings ...)
2026-09-11 19:25 ` [PATCH 3/6] ARM: Emulate two-byte cmpxchg on ARMv6 Bradley Morgan
@ 2026-09-11 19:25 ` Bradley Morgan
2026-09-11 19:25 ` [PATCH 5/6] sh: " Bradley Morgan
` (2 subsequent siblings)
6 siblings, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 19:25 UTC (permalink / raw)
To: Paul E. McKenney
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel, brads
csky has no byte or halfword atomic memory operations, so the
__cmpxchg_relaxed(), __cmpxchg_acquire() and __cmpxchg() switches
each route case 1 through cmpxchg_emu_u8() and leave case 2 to
fall into the BUILD_BUG() default. Route case 2 in all three
through the new cmpxchg_emu_u16().
arch_cmpxchg_local() maps to __cmpxchg_relaxed() and so picks up
case 2 automatically.
Signed-off-by: Bradley Morgan <brads@mainlining.org>
---
arch/csky/include/asm/cmpxchg.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/csky/include/asm/cmpxchg.h b/arch/csky/include/asm/cmpxchg.h
index db6dda47184e..a6a4805064a4 100644
--- a/arch/csky/include/asm/cmpxchg.h
+++ b/arch/csky/include/asm/cmpxchg.h
@@ -65,6 +65,9 @@
case 1: \
__ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
break; \
+ case 2: \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u16((volatile u16 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
+ break; \
case 4: \
asm volatile ( \
"1: ldex.w %0, (%3) \n" \
@@ -98,6 +101,9 @@
case 1: \
__ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
break; \
+ case 2: \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u16((volatile u16 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
+ break; \
case 4: \
asm volatile ( \
"1: ldex.w %0, (%3) \n" \
@@ -132,6 +138,9 @@
case 1: \
__ret = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
break; \
+ case 2: \
+ __ret = (__typeof__(*(ptr)))cmpxchg_emu_u16((volatile u16 *)__ptr, (uintptr_t)__old, (uintptr_t)__new); \
+ break; \
case 4: \
asm volatile ( \
RELEASE_FENCE \
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 5/6] sh: Emulate two-byte cmpxchg
2026-09-11 19:25 [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
` (3 preceding siblings ...)
2026-09-11 19:25 ` [PATCH 4/6] csky: Emulate two-byte cmpxchg Bradley Morgan
@ 2026-09-11 19:25 ` Bradley Morgan
2026-09-11 19:25 ` [PATCH 6/6] xtensa: " Bradley Morgan
2026-09-11 20:17 ` [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Arnd Bergmann
6 siblings, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 19:25 UTC (permalink / raw)
To: Paul E. McKenney
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel, brads
SH has no byte or halfword atomic memory operations, so the
__cmpxchg() switch routes case 1 through cmpxchg_emu_u8() and
lets case 2 fall through to __cmpxchg_called_with_bad_pointer(),
which is declared but never defined, so a two-byte cmpxchg()
fails at link time. Route case 2 through the new cmpxchg_emu_u16().
Signed-off-by: Bradley Morgan <brads@mainlining.org>
---
arch/sh/include/asm/cmpxchg.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/sh/include/asm/cmpxchg.h b/arch/sh/include/asm/cmpxchg.h
index 1e5dc5ccf7bf..477d3025a441 100644
--- a/arch/sh/include/asm/cmpxchg.h
+++ b/arch/sh/include/asm/cmpxchg.h
@@ -59,6 +59,8 @@ static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
switch (size) {
case 1:
return cmpxchg_emu_u8(ptr, old, new);
+ case 2:
+ return cmpxchg_emu_u16(ptr, old, new);
case 4:
return __cmpxchg_u32(ptr, old, new);
}
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 6/6] xtensa: Emulate two-byte cmpxchg
2026-09-11 19:25 [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
` (4 preceding siblings ...)
2026-09-11 19:25 ` [PATCH 5/6] sh: " Bradley Morgan
@ 2026-09-11 19:25 ` Bradley Morgan
2026-09-11 20:17 ` [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Arnd Bergmann
6 siblings, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 19:25 UTC (permalink / raw)
To: Paul E. McKenney
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel, brads
Xtensa has no byte or halfword atomic memory operations, so the
__cmpxchg() switch routes case 1 through cmpxchg_emu_u8() and
lets case 2 hit the default, __cmpxchg_called_with_bad_pointer(),
which is declared but never defined, so a two-byte cmpxchg() fails
at link time. Route case 2 through the new cmpxchg_emu_u16().
Signed-off-by: Bradley Morgan <brads@mainlining.org>
---
arch/xtensa/include/asm/cmpxchg.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h
index b6db4838b175..8dea8e357fc0 100644
--- a/arch/xtensa/include/asm/cmpxchg.h
+++ b/arch/xtensa/include/asm/cmpxchg.h
@@ -76,6 +76,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
{
switch (size) {
case 1: return cmpxchg_emu_u8(ptr, old, new);
+ case 2: return cmpxchg_emu_u16(ptr, old, new);
case 4: return __cmpxchg_u32(ptr, old, new);
default: __cmpxchg_called_with_bad_pointer();
return old;
--
2.47.3
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures
2026-09-11 19:25 [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
` (5 preceding siblings ...)
2026-09-11 19:25 ` [PATCH 6/6] xtensa: " Bradley Morgan
@ 2026-09-11 20:17 ` Arnd Bergmann
2026-09-11 20:20 ` Bradley Morgan
6 siblings, 1 reply; 16+ messages in thread
From: Arnd Bergmann @ 2026-09-11 20:17 UTC (permalink / raw)
To: Bradley Morgan, Paul E. McKenney
Cc: Frederic Weisbecker, neeraj.upadhyay, Boqun Feng, Joel Fernandes,
rcu, Andrew Morton, Linux-Arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, guoren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel
On Fri, Sep 11, 2026, at 21:25, Bradley Morgan wrote:
> Per Paul's note, Arnd Bergmann's platform removal series was
> checked before analyzing the users. It removes the imx31 and
> omap24xx CPU_ARM1136R0 selectors, but INTEGRATOR_CM1136JFS still
> selects CPU_ARM1136R0 until its scheduled removal in early 2027,
> so the ARMv6 path in patch 3 is still live.
I can still restructure this and pull the INTEGRATOR_CM1136JFS
removal a little earlier. At the moment, this is part of the
patch to remove CPU_ARM1136R0, which I had planned to submit
once the arch/arm/mach-*/ platform removal patches are done:
https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/commit/?id=a8cfcc5533e33a
I could turn the mach-versatile/Kconfig change into a separate
(trivial) patch and add it to the platform series to avoid
churn here. The armv6 cmpxchg() code would still exist
in 7.4 then, but be unreachable.
Arnd
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures
2026-09-11 20:17 ` [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Arnd Bergmann
@ 2026-09-11 20:20 ` Bradley Morgan
0 siblings, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 20:20 UTC (permalink / raw)
To: Arnd Bergmann, Paul E. McKenney
Cc: Frederic Weisbecker, neeraj.upadhyay, Boqun Feng, Joel Fernandes,
rcu, Andrew Morton, Linux-Arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, guoren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel
On 11 September 2026 21:17:15 BST, Arnd Bergmann <arnd@arndb.de> wrote:
>On Fri, Sep 11, 2026, at 21:25, Bradley Morgan wrote:
>> Per Paul's note, Arnd Bergmann's platform removal series was
>> checked before analyzing the users. It removes the imx31 and
>> omap24xx CPU_ARM1136R0 selectors, but INTEGRATOR_CM1136JFS still
>> selects CPU_ARM1136R0 until its scheduled removal in early 2027,
>> so the ARMv6 path in patch 3 is still live.
>
>I can still restructure this and pull the INTEGRATOR_CM1136JFS
>removal a little earlier. At the moment, this is part of the
>patch to remove CPU_ARM1136R0, which I had planned to submit
>once the arch/arm/mach-*/ platform removal patches are done:
>
>https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git/commit/?id=a8cfcc5533e33a
>
>I could turn the mach-versatile/Kconfig change into a separate
>(trivial) patch and add it to the platform series to avoid
>churn here. The armv6 cmpxchg() code would still exist
>in 7.4 then, but be unreachable.
>
> Arnd
Hi, is this like V2 required? Or a *ugh fine that's ok* kinda message?
--- Thanks!
https://lore.kernel.org/all/EE579805-42F2-4C58-B752-F28779EEB717@grrlz.net/
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] lib: Add two-byte cmpxchg emulation function
2026-09-11 19:25 ` [PATCH 1/6] lib: Add two-byte cmpxchg emulation function Bradley Morgan
@ 2026-09-11 22:10 ` David Laight
2026-09-11 22:13 ` Bradley Morgan
2026-09-11 23:09 ` Paul E. McKenney
0 siblings, 2 replies; 16+ messages in thread
From: David Laight @ 2026-09-11 22:10 UTC (permalink / raw)
To: Bradley Morgan
Cc: Paul E. McKenney, frederic, neeraj.upadhyay, boqun, joelagnelf,
rcu, Andrew Morton, Arnd Bergmann, linux-arch, Vineet Gupta,
linux-snps-arc, Russell King, linux-arm-kernel, Guo Ren,
linux-csky, Yoshinori Sato, Rich Felker,
John Paul Adrian Glaubitz, linux-sh, Chris Zankel, Max Filippov,
linux-kernel
On Fri, 11 Sep 2026 19:25:34 +0000
Bradley Morgan <brads@mainlining.org> wrote:
> cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
> cmpxchg() for the architectures lacking native one-byte atomics.
> The same architectures also lack native two-byte cmpxchg(), where
> such an operation is not supported and either fails to compile via
> BUILD_BUG() or fails to link, because the bad pointer sentinels
> these architectures declare are never defined.
>
> Add cmpxchg_emu_u16(), the two-byte sibling. It reads the enclosing
> word with READ_ONCE(), splices the two target bytes through a union
> and loops on cmpxchg() of the full word until the compare succeeds.
> Like cmpxchg_emu_u8() it is fully ordered.
>
> The Kconfig symbol gating this file is renamed from
> ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
> selects both the one-byte and the two-byte emulation.
>
> Suggested-by: Paul E. McKenney <paulmck@kernel.org>
> Signed-off-by: Bradley Morgan <brads@mainlining.org>
> ---
> arch/Kconfig | 2 +-
> arch/arc/Kconfig | 2 +-
> arch/arm/Kconfig | 2 +-
> arch/csky/Kconfig | 2 +-
> arch/sh/Kconfig | 2 +-
> arch/xtensa/Kconfig | 2 +-
> include/linux/cmpxchg-emu.h | 1 +
> lib/Makefile | 2 +-
> lib/cmpxchg-emu.c | 35 ++++++++++++++++++++++++++++++++---
> 9 files changed, 40 insertions(+), 10 deletions(-)
>
...
> diff --git a/include/linux/cmpxchg-emu.h b/include/linux/cmpxchg-emu.h
> index 998deec67740..fee8171fa05e 100644
> --- a/include/linux/cmpxchg-emu.h
> +++ b/include/linux/cmpxchg-emu.h
> @@ -11,5 +11,6 @@
> #define __LINUX_CMPXCHG_EMU_H
>
> uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new);
> +uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old, uintptr_t new);
Why uintptr_t? Shouldn't it just be u16?
(Which probably means the code would better if it was just 'unsigned int')
David
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] lib: Add two-byte cmpxchg emulation function
2026-09-11 22:10 ` David Laight
@ 2026-09-11 22:13 ` Bradley Morgan
2026-09-11 23:09 ` Paul E. McKenney
1 sibling, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-11 22:13 UTC (permalink / raw)
To: David Laight
Cc: Paul E. McKenney, frederic, neeraj.upadhyay, boqun, joelagnelf,
rcu, Andrew Morton, Arnd Bergmann, linux-arch, Vineet Gupta,
linux-snps-arc, Russell King, linux-arm-kernel, Guo Ren,
linux-csky, Yoshinori Sato, Rich Felker,
John Paul Adrian Glaubitz, linux-sh, Chris Zankel, Max Filippov,
linux-kernel
On 11 September 2026 23:10:17 BST, David Laight
<david.laight.linux@gmail.com> wrote:
>On Fri, 11 Sep 2026 19:25:34 +0000
>Bradley Morgan <brads@mainlining.org> wrote:
>
>> cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
>> cmpxchg() for the architectures lacking native one-byte atomics.
>> The same architectures also lack native two-byte cmpxchg(), where
>> such an operation is not supported and either fails to compile via
>> BUILD_BUG() or fails to link, because the bad pointer sentinels
>> these architectures declare are never defined.
>>
>> Add cmpxchg_emu_u16(), the two-byte sibling. It reads the enclosing
>> word with READ_ONCE(), splices the two target bytes through a union
>> and loops on cmpxchg() of the full word until the compare succeeds.
>> Like cmpxchg_emu_u8() it is fully ordered.
>>
>> The Kconfig symbol gating this file is renamed from
>> ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
>> selects both the one-byte and the two-byte emulation.
>>
>> Suggested-by: Paul E. McKenney <paulmck@kernel.org>
>> Signed-off-by: Bradley Morgan <brads@mainlining.org>
>> ---
>> arch/Kconfig | 2 +-
>> arch/arc/Kconfig | 2 +-
>> arch/arm/Kconfig | 2 +-
>> arch/csky/Kconfig | 2 +-
>> arch/sh/Kconfig | 2 +-
>> arch/xtensa/Kconfig | 2 +-
>> include/linux/cmpxchg-emu.h | 1 +
>> lib/Makefile | 2 +-
>> lib/cmpxchg-emu.c | 35 ++++++++++++++++++++++++++++++++---
>> 9 files changed, 40 insertions(+), 10 deletions(-)
>>
>...
>> diff --git a/include/linux/cmpxchg-emu.h b/include/linux/cmpxchg-emu.h
>> index 998deec67740..fee8171fa05e 100644
>> --- a/include/linux/cmpxchg-emu.h
>> +++ b/include/linux/cmpxchg-emu.h
>> @@ -11,5 +11,6 @@
>> #define __LINUX_CMPXCHG_EMU_H
>>
>> uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new);
>> +uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old, uintptr_t
>new);
>
>Why uintptr_t? Shouldn't it just be u16?
Hi, Paul suggested I make it as identical as possible to u8, Do you reckon
this would break anything?
>(Which probably means the code would better if it was just 'unsigned int')
Ehh, subjective.
>
>David
>
>
--- Thanks!
https://lore.kernel.org/all/EE579805-42F2-4C58-B752-F28779EEB717@grrlz.net/
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] lib: Add two-byte cmpxchg emulation function
2026-09-11 22:10 ` David Laight
2026-09-11 22:13 ` Bradley Morgan
@ 2026-09-11 23:09 ` Paul E. McKenney
2026-09-12 9:30 ` David Laight
1 sibling, 1 reply; 16+ messages in thread
From: Paul E. McKenney @ 2026-09-11 23:09 UTC (permalink / raw)
To: David Laight
Cc: Bradley Morgan, frederic, neeraj.upadhyay, boqun, joelagnelf,
rcu, Andrew Morton, Arnd Bergmann, linux-arch, Vineet Gupta,
linux-snps-arc, Russell King, linux-arm-kernel, Guo Ren,
linux-csky, Yoshinori Sato, Rich Felker,
John Paul Adrian Glaubitz, linux-sh, Chris Zankel, Max Filippov,
linux-kernel
On Fri, Sep 11, 2026 at 11:10:17PM +0100, David Laight wrote:
> On Fri, 11 Sep 2026 19:25:34 +0000
> Bradley Morgan <brads@mainlining.org> wrote:
>
> > cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
> > cmpxchg() for the architectures lacking native one-byte atomics.
> > The same architectures also lack native two-byte cmpxchg(), where
> > such an operation is not supported and either fails to compile via
> > BUILD_BUG() or fails to link, because the bad pointer sentinels
> > these architectures declare are never defined.
> >
> > Add cmpxchg_emu_u16(), the two-byte sibling. It reads the enclosing
> > word with READ_ONCE(), splices the two target bytes through a union
> > and loops on cmpxchg() of the full word until the compare succeeds.
> > Like cmpxchg_emu_u8() it is fully ordered.
> >
> > The Kconfig symbol gating this file is renamed from
> > ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
> > selects both the one-byte and the two-byte emulation.
> >
> > Suggested-by: Paul E. McKenney <paulmck@kernel.org>
> > Signed-off-by: Bradley Morgan <brads@mainlining.org>
> > ---
> > arch/Kconfig | 2 +-
> > arch/arc/Kconfig | 2 +-
> > arch/arm/Kconfig | 2 +-
> > arch/csky/Kconfig | 2 +-
> > arch/sh/Kconfig | 2 +-
> > arch/xtensa/Kconfig | 2 +-
> > include/linux/cmpxchg-emu.h | 1 +
> > lib/Makefile | 2 +-
> > lib/cmpxchg-emu.c | 35 ++++++++++++++++++++++++++++++++---
> > 9 files changed, 40 insertions(+), 10 deletions(-)
> >
> ...
> > diff --git a/include/linux/cmpxchg-emu.h b/include/linux/cmpxchg-emu.h
> > index 998deec67740..fee8171fa05e 100644
> > --- a/include/linux/cmpxchg-emu.h
> > +++ b/include/linux/cmpxchg-emu.h
> > @@ -11,5 +11,6 @@
> > #define __LINUX_CMPXCHG_EMU_H
> >
> > uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new);
> > +uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old, uintptr_t new);
>
> Why uintptr_t? Shouldn't it just be u16?
> (Which probably means the code would better if it was just 'unsigned int')
I suspect that Bradley is just following my cmpxchg_emu_u8() example,
which also returns uintptr_t.
I remember that *something* broke when I made this be u8, but I cannot
recall what the problem was.
Bradley, could you please try making it be u16 as David suggests just to
see what happens? Who knows? Maybe it was a compiler issue that has
since been fixed. Or maybe the macros and asms using cmpxchg_emu_u8()
need that uintptr_t for some reason.
Thanx, Paul
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] lib: Add two-byte cmpxchg emulation function
2026-09-11 23:09 ` Paul E. McKenney
@ 2026-09-12 9:30 ` David Laight
2026-09-12 10:29 ` Bradley Morgan
2026-09-12 18:58 ` Paul E. McKenney
0 siblings, 2 replies; 16+ messages in thread
From: David Laight @ 2026-09-12 9:30 UTC (permalink / raw)
To: Paul E. McKenney
Cc: Bradley Morgan, frederic, neeraj.upadhyay, boqun, joelagnelf,
rcu, Andrew Morton, Arnd Bergmann, linux-arch, Vineet Gupta,
linux-snps-arc, Russell King, linux-arm-kernel, Guo Ren,
linux-csky, Yoshinori Sato, Rich Felker,
John Paul Adrian Glaubitz, linux-sh, Chris Zankel, Max Filippov,
linux-kernel
On Fri, 11 Sep 2026 16:09:16 -0700
"Paul E. McKenney" <paulmck@kernel.org> wrote:
> On Fri, Sep 11, 2026 at 11:10:17PM +0100, David Laight wrote:
> > On Fri, 11 Sep 2026 19:25:34 +0000
> > Bradley Morgan <brads@mainlining.org> wrote:
> >
> > > cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
> > > cmpxchg() for the architectures lacking native one-byte atomics.
> > > The same architectures also lack native two-byte cmpxchg(), where
> > > such an operation is not supported and either fails to compile via
> > > BUILD_BUG() or fails to link, because the bad pointer sentinels
> > > these architectures declare are never defined.
> > >
> > > Add cmpxchg_emu_u16(), the two-byte sibling. It reads the enclosing
> > > word with READ_ONCE(), splices the two target bytes through a union
> > > and loops on cmpxchg() of the full word until the compare succeeds.
> > > Like cmpxchg_emu_u8() it is fully ordered.
> > >
> > > The Kconfig symbol gating this file is renamed from
> > > ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
> > > selects both the one-byte and the two-byte emulation.
> > >
> > > Suggested-by: Paul E. McKenney <paulmck@kernel.org>
> > > Signed-off-by: Bradley Morgan <brads@mainlining.org>
> > > ---
> > > arch/Kconfig | 2 +-
> > > arch/arc/Kconfig | 2 +-
> > > arch/arm/Kconfig | 2 +-
> > > arch/csky/Kconfig | 2 +-
> > > arch/sh/Kconfig | 2 +-
> > > arch/xtensa/Kconfig | 2 +-
> > > include/linux/cmpxchg-emu.h | 1 +
> > > lib/Makefile | 2 +-
> > > lib/cmpxchg-emu.c | 35 ++++++++++++++++++++++++++++++++---
> > > 9 files changed, 40 insertions(+), 10 deletions(-)
> > >
> > ...
> > > diff --git a/include/linux/cmpxchg-emu.h b/include/linux/cmpxchg-emu.h
> > > index 998deec67740..fee8171fa05e 100644
> > > --- a/include/linux/cmpxchg-emu.h
> > > +++ b/include/linux/cmpxchg-emu.h
> > > @@ -11,5 +11,6 @@
> > > #define __LINUX_CMPXCHG_EMU_H
> > >
> > > uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new);
> > > +uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old, uintptr_t new);
> >
> > Why uintptr_t? Shouldn't it just be u16?
> > (Which probably means the code would better if it was just 'unsigned int')
>
> I suspect that Bradley is just following my cmpxchg_emu_u8() example,
> which also returns uintptr_t.
>
> I remember that *something* broke when I made this be u8, but I cannot
> recall what the problem was.
>
> Bradley, could you please try making it be u16 as David suggests just to
> see what happens? Who knows? Maybe it was a compiler issue that has
> since been fixed. Or maybe the macros and asms using cmpxchg_emu_u8()
> need that uintptr_t for some reason.
I think the uintptr (unsigned long) cast is needed to stop a compile
error when exchanging pointers.
But that is an issue with the #define not the called functions.
Possibly changing the #define to have:
unsigned long ul_old = (unsigned long)(old);
Or even, with the type check from:
unsigned long ul_old = (unsigned long)(0 ? *(ptr) : (old));
(with the same for 'new')
and the removing all the casts where the value are used might be better.
David
>
> Thanx, Paul
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] lib: Add two-byte cmpxchg emulation function
2026-09-12 9:30 ` David Laight
@ 2026-09-12 10:29 ` Bradley Morgan
2026-09-12 18:58 ` Paul E. McKenney
1 sibling, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-12 10:29 UTC (permalink / raw)
To: David Laight, Paul E. McKenney
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel
On 12 September 2026 10:30:47 BST, David Laight
<david.laight.linux@gmail.com> wrote:
>On Fri, 11 Sep 2026 16:09:16 -0700
>"Paul E. McKenney" <paulmck@kernel.org> wrote:
>
>> On Fri, Sep 11, 2026 at 11:10:17PM +0100, David Laight wrote:
>> > On Fri, 11 Sep 2026 19:25:34 +0000
>> > Bradley Morgan <brads@mainlining.org> wrote:
>> >
>> > > cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
>> > > cmpxchg() for the architectures lacking native one-byte atomics.
>> > > The same architectures also lack native two-byte cmpxchg(), where
>> > > such an operation is not supported and either fails to compile via
>> > > BUILD_BUG() or fails to link, because the bad pointer sentinels
>> > > these architectures declare are never defined.
>> > >
>> > > Add cmpxchg_emu_u16(), the two-byte sibling. It reads the enclosing
>> > > word with READ_ONCE(), splices the two target bytes through a union
>> > > and loops on cmpxchg() of the full word until the compare succeeds.
>> > > Like cmpxchg_emu_u8() it is fully ordered.
>> > >
>> > > The Kconfig symbol gating this file is renamed from
>> > > ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
>> > > selects both the one-byte and the two-byte emulation.
>> > >
>> > > Suggested-by: Paul E. McKenney <paulmck@kernel.org>
>> > > Signed-off-by: Bradley Morgan <brads@mainlining.org>
>> > > ---
>> > > arch/Kconfig | 2 +-
>> > > arch/arc/Kconfig | 2 +-
>> > > arch/arm/Kconfig | 2 +-
>> > > arch/csky/Kconfig | 2 +-
>> > > arch/sh/Kconfig | 2 +-
>> > > arch/xtensa/Kconfig | 2 +-
>> > > include/linux/cmpxchg-emu.h | 1 +
>> > > lib/Makefile | 2 +-
>> > > lib/cmpxchg-emu.c | 35
>++++++++++++++++++++++++++++++++---
>> > > 9 files changed, 40 insertions(+), 10 deletions(-)
>> > >
>> > ...
>> > > diff --git a/include/linux/cmpxchg-emu.h
>b/include/linux/cmpxchg-emu.h
>> > > index 998deec67740..fee8171fa05e 100644
>> > > --- a/include/linux/cmpxchg-emu.h
>> > > +++ b/include/linux/cmpxchg-emu.h
>> > > @@ -11,5 +11,6 @@
>> > > #define __LINUX_CMPXCHG_EMU_H
>> > >
>> > > uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t
>new);
>> > > +uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old, uintptr_t
>new);
>> >
>> > Why uintptr_t? Shouldn't it just be u16?
>> > (Which probably means the code would better if it was just 'unsigned
>int')
>>
>> I suspect that Bradley is just following my cmpxchg_emu_u8() example,
>> which also returns uintptr_t.
>>
>> I remember that *something* broke when I made this be u8, but I cannot
>> recall what the problem was.
>>
>> Bradley, could you please try making it be u16 as David suggests just to
>> see what happens? Who knows? Maybe it was a compiler issue that has
>> since been fixed. Or maybe the macros and asms using cmpxchg_emu_u8()
>> need that uintptr_t for some reason.
>
>I think the uintptr (unsigned long) cast is needed to stop a compile
>error when exchanging pointers.
>But that is an issue with the #define not the called functions.
>
>Possibly changing the #define to have:
> unsigned long ul_old = (unsigned long)(old);
>Or even, with the type check from:
> unsigned long ul_old = (unsigned long)(0 ? *(ptr) : (old));
>(with the same for 'new')
>and the removing all the casts where the value are used might be better.
>
>David
>
>>
>> Thanx, Paul
>
>
Hmm. Okie dokie, noted for V2, thanks for the review,
I'm sure arch code is just implementing this function, so I hope nothing
went wrong with the arch code.
--- Thanks!
https://lore.kernel.org/all/EE579805-42F2-4C58-B752-F28779EEB717@grrlz.net/
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] lib: Add two-byte cmpxchg emulation function
2026-09-12 9:30 ` David Laight
2026-09-12 10:29 ` Bradley Morgan
@ 2026-09-12 18:58 ` Paul E. McKenney
2026-09-12 21:11 ` Bradley Morgan
1 sibling, 1 reply; 16+ messages in thread
From: Paul E. McKenney @ 2026-09-12 18:58 UTC (permalink / raw)
To: David Laight
Cc: Bradley Morgan, frederic, neeraj.upadhyay, boqun, joelagnelf,
rcu, Andrew Morton, Arnd Bergmann, linux-arch, Vineet Gupta,
linux-snps-arc, Russell King, linux-arm-kernel, Guo Ren,
linux-csky, Yoshinori Sato, Rich Felker,
John Paul Adrian Glaubitz, linux-sh, Chris Zankel, Max Filippov,
linux-kernel
On Sat, Sep 12, 2026 at 10:30:47AM +0100, David Laight wrote:
> On Fri, 11 Sep 2026 16:09:16 -0700
> "Paul E. McKenney" <paulmck@kernel.org> wrote:
>
> > On Fri, Sep 11, 2026 at 11:10:17PM +0100, David Laight wrote:
> > > On Fri, 11 Sep 2026 19:25:34 +0000
> > > Bradley Morgan <brads@mainlining.org> wrote:
> > >
> > > > cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
> > > > cmpxchg() for the architectures lacking native one-byte atomics.
> > > > The same architectures also lack native two-byte cmpxchg(), where
> > > > such an operation is not supported and either fails to compile via
> > > > BUILD_BUG() or fails to link, because the bad pointer sentinels
> > > > these architectures declare are never defined.
> > > >
> > > > Add cmpxchg_emu_u16(), the two-byte sibling. It reads the enclosing
> > > > word with READ_ONCE(), splices the two target bytes through a union
> > > > and loops on cmpxchg() of the full word until the compare succeeds.
> > > > Like cmpxchg_emu_u8() it is fully ordered.
> > > >
> > > > The Kconfig symbol gating this file is renamed from
> > > > ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
> > > > selects both the one-byte and the two-byte emulation.
> > > >
> > > > Suggested-by: Paul E. McKenney <paulmck@kernel.org>
> > > > Signed-off-by: Bradley Morgan <brads@mainlining.org>
> > > > ---
> > > > arch/Kconfig | 2 +-
> > > > arch/arc/Kconfig | 2 +-
> > > > arch/arm/Kconfig | 2 +-
> > > > arch/csky/Kconfig | 2 +-
> > > > arch/sh/Kconfig | 2 +-
> > > > arch/xtensa/Kconfig | 2 +-
> > > > include/linux/cmpxchg-emu.h | 1 +
> > > > lib/Makefile | 2 +-
> > > > lib/cmpxchg-emu.c | 35 ++++++++++++++++++++++++++++++++---
> > > > 9 files changed, 40 insertions(+), 10 deletions(-)
> > > >
> > > ...
> > > > diff --git a/include/linux/cmpxchg-emu.h b/include/linux/cmpxchg-emu.h
> > > > index 998deec67740..fee8171fa05e 100644
> > > > --- a/include/linux/cmpxchg-emu.h
> > > > +++ b/include/linux/cmpxchg-emu.h
> > > > @@ -11,5 +11,6 @@
> > > > #define __LINUX_CMPXCHG_EMU_H
> > > >
> > > > uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t new);
> > > > +uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old, uintptr_t new);
> > >
> > > Why uintptr_t? Shouldn't it just be u16?
> > > (Which probably means the code would better if it was just 'unsigned int')
> >
> > I suspect that Bradley is just following my cmpxchg_emu_u8() example,
> > which also returns uintptr_t.
> >
> > I remember that *something* broke when I made this be u8, but I cannot
> > recall what the problem was.
> >
> > Bradley, could you please try making it be u16 as David suggests just to
> > see what happens? Who knows? Maybe it was a compiler issue that has
> > since been fixed. Or maybe the macros and asms using cmpxchg_emu_u8()
> > need that uintptr_t for some reason.
>
> I think the uintptr (unsigned long) cast is needed to stop a compile
> error when exchanging pointers.
> But that is an issue with the #define not the called functions.
>
> Possibly changing the #define to have:
> unsigned long ul_old = (unsigned long)(old);
> Or even, with the type check from:
> unsigned long ul_old = (unsigned long)(0 ? *(ptr) : (old));
> (with the same for 'new')
> and the removing all the casts where the value are used might be better.
It does sound worth a try, especially since we have the uintptr_t version
to fall back on should that fail, or in case it somehow makes things
more complicated.
But we have been living with uintptr_t for some years with the 8-bit
code, so this should be able to be a follow-on patch.
Thanx, Paul
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/6] lib: Add two-byte cmpxchg emulation function
2026-09-12 18:58 ` Paul E. McKenney
@ 2026-09-12 21:11 ` Bradley Morgan
0 siblings, 0 replies; 16+ messages in thread
From: Bradley Morgan @ 2026-09-12 21:11 UTC (permalink / raw)
To: paulmck, Paul E. McKenney, David Laight
Cc: frederic, neeraj.upadhyay, boqun, joelagnelf, rcu, Andrew Morton,
Arnd Bergmann, linux-arch, Vineet Gupta, linux-snps-arc,
Russell King, linux-arm-kernel, Guo Ren, linux-csky,
Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz, linux-sh,
Chris Zankel, Max Filippov, linux-kernel
On 12 September 2026 19:58:02 BST, "Paul E. McKenney" <paulmck@kernel.org>
wrote:
>On Sat, Sep 12, 2026 at 10:30:47AM +0100, David Laight wrote:
>> On Fri, 11 Sep 2026 16:09:16 -0700
>> "Paul E. McKenney" <paulmck@kernel.org> wrote:
>>
>> > On Fri, Sep 11, 2026 at 11:10:17PM +0100, David Laight wrote:
>> > > On Fri, 11 Sep 2026 19:25:34 +0000
>> > > Bradley Morgan <brads@mainlining.org> wrote:
>> > >
>> > > > cmpxchg_emu_u8() emulates one-byte cmpxchg() in terms of four-byte
>> > > > cmpxchg() for the architectures lacking native one-byte atomics.
>> > > > The same architectures also lack native two-byte cmpxchg(), where
>> > > > such an operation is not supported and either fails to compile via
>> > > > BUILD_BUG() or fails to link, because the bad pointer sentinels
>> > > > these architectures declare are never defined.
>> > > >
>> > > > Add cmpxchg_emu_u16(), the two-byte sibling. It reads the
>enclosing
>> > > > word with READ_ONCE(), splices the two target bytes through a
>union
>> > > > and loops on cmpxchg() of the full word until the compare
>succeeds.
>> > > > Like cmpxchg_emu_u8() it is fully ordered.
>> > > >
>> > > > The Kconfig symbol gating this file is renamed from
>> > > > ARCH_NEED_CMPXCHG_1_EMU to ARCH_NEED_CMPXCHG_1_2_EMU, as it now
>> > > > selects both the one-byte and the two-byte emulation.
>> > > >
>> > > > Suggested-by: Paul E. McKenney <paulmck@kernel.org>
>> > > > Signed-off-by: Bradley Morgan <brads@mainlining.org>
>> > > > ---
>> > > > arch/Kconfig | 2 +-
>> > > > arch/arc/Kconfig | 2 +-
>> > > > arch/arm/Kconfig | 2 +-
>> > > > arch/csky/Kconfig | 2 +-
>> > > > arch/sh/Kconfig | 2 +-
>> > > > arch/xtensa/Kconfig | 2 +-
>> > > > include/linux/cmpxchg-emu.h | 1 +
>> > > > lib/Makefile | 2 +-
>> > > > lib/cmpxchg-emu.c | 35
>++++++++++++++++++++++++++++++++---
>> > > > 9 files changed, 40 insertions(+), 10 deletions(-)
>> > > >
>> > > ...
>> > > > diff --git a/include/linux/cmpxchg-emu.h
>b/include/linux/cmpxchg-emu.h
>> > > > index 998deec67740..fee8171fa05e 100644
>> > > > --- a/include/linux/cmpxchg-emu.h
>> > > > +++ b/include/linux/cmpxchg-emu.h
>> > > > @@ -11,5 +11,6 @@
>> > > > #define __LINUX_CMPXCHG_EMU_H
>> > > >
>> > > > uintptr_t cmpxchg_emu_u8(volatile u8 *p, uintptr_t old, uintptr_t
>new);
>> > > > +uintptr_t cmpxchg_emu_u16(volatile u16 *p, uintptr_t old,
>uintptr_t new);
>> > >
>> > > Why uintptr_t? Shouldn't it just be u16?
>> > > (Which probably means the code would better if it was just 'unsigned
>int')
>> >
>> > I suspect that Bradley is just following my cmpxchg_emu_u8() example,
>> > which also returns uintptr_t.
>> >
>> > I remember that *something* broke when I made this be u8, but I cannot
>> > recall what the problem was.
>> >
>> > Bradley, could you please try making it be u16 as David suggests just
>to
>> > see what happens? Who knows? Maybe it was a compiler issue that has
>> > since been fixed. Or maybe the macros and asms using cmpxchg_emu_u8()
>> > need that uintptr_t for some reason.
>>
>> I think the uintptr (unsigned long) cast is needed to stop a compile
>> error when exchanging pointers.
>> But that is an issue with the #define not the called functions.
>>
>> Possibly changing the #define to have:
>> unsigned long ul_old = (unsigned long)(old);
>> Or even, with the type check from:
>> unsigned long ul_old = (unsigned long)(0 ? *(ptr) : (old));
>> (with the same for 'new')
>> and the removing all the casts where the value are used might be better.
>
>It does sound worth a try, especially since we have the uintptr_t version
>to fall back on should that fail, or in case it somehow makes things
>more complicated.
>
>But we have been living with uintptr_t for some years with the 8-bit
>code, so this should be able to be a follow-on patch.
>
> Thanx, Paul
I'll try u16 and then add another patch tryna fix the issue.
--- Thanks!
https://lore.kernel.org/all/EE579805-42F2-4C58-B752-F28779EEB717@grrlz.net/
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-09-12 21:14 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-11 19:25 [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Bradley Morgan
2026-09-11 19:25 ` [PATCH 1/6] lib: Add two-byte cmpxchg emulation function Bradley Morgan
2026-09-11 22:10 ` David Laight
2026-09-11 22:13 ` Bradley Morgan
2026-09-11 23:09 ` Paul E. McKenney
2026-09-12 9:30 ` David Laight
2026-09-12 10:29 ` Bradley Morgan
2026-09-12 18:58 ` Paul E. McKenney
2026-09-12 21:11 ` Bradley Morgan
2026-09-11 19:25 ` [PATCH 2/6] ARC: Emulate two-byte cmpxchg Bradley Morgan
2026-09-11 19:25 ` [PATCH 3/6] ARM: Emulate two-byte cmpxchg on ARMv6 Bradley Morgan
2026-09-11 19:25 ` [PATCH 4/6] csky: Emulate two-byte cmpxchg Bradley Morgan
2026-09-11 19:25 ` [PATCH 5/6] sh: " Bradley Morgan
2026-09-11 19:25 ` [PATCH 6/6] xtensa: " Bradley Morgan
2026-09-11 20:17 ` [PATCH 0/6] Add two-byte cmpxchg emulation and wire it into the architectures Arnd Bergmann
2026-09-11 20:20 ` Bradley Morgan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®