Messages in this thread Patch in this message |  | | From | Karl Mehltretter <> | | Subject | [PATCH 1/2] ARM: cmpxchg: support 2-byte xchg() on pre-ARMv6 CPUs | | Date | Sat, 3 Oct 2026 11:38:26 +0200 |
| |
Pre-ARMv6 CPUs have no halfword swp, so __arch_xchg() only handles 1- and 4-byte exchanges there and turns any other size into a link error via __bad_xchg().
No C code needs a 16-bit xchg() on these CPUs, but the Rust atomic helpers in rust/helpers/atomic_ext.c provide xchg() for Atomic<i16> unconditionally, so building with CONFIG_RUST=y for ARMv5 fails:
ld.lld: error: undefined symbol: __bad_xchg >>> referenced by helpers.c >>> rust/helpers/helpers.o:(rust_helper_atomic_i16_xchg)
Implement the 2-byte case with interrupts disabled, as the pre-ARMv6 atomic_t operations already do. This is safe because SMP requires ARMv6K or later.
Assisted-by: LLM Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com> --- arch/arm/include/asm/cmpxchg.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/arch/arm/include/asm/cmpxchg.h b/arch/arm/include/asm/cmpxchg.h index 9beb64d30586..3077f7d7f520 100644 --- a/arch/arm/include/asm/cmpxchg.h +++ b/arch/arm/include/asm/cmpxchg.h @@ -31,11 +31,10 @@ __arch_xchg(unsigned long x, volatile void *ptr, int size) { extern void __bad_xchg(volatile void *, int); unsigned long ret; -#ifdef swp_is_buggy - unsigned long flags; -#endif #if __LINUX_ARM_ARCH__ >= 6 unsigned int tmp; +#else + unsigned long flags; #endif prefetchw((const void *)ptr); @@ -106,6 +105,15 @@ __arch_xchg(unsigned long x, volatile void *ptr, int size) : "r" (x), "r" (ptr) : "memory", "cc"); break; +#endif +#if __LINUX_ARM_ARCH__ < 6 + case 2: + /* swp has no halfword form. Pre-ARMv6 is never SMP. */ + raw_local_irq_save(flags); + ret = *(volatile unsigned short *)ptr; + *(volatile unsigned short *)ptr = x; + raw_local_irq_restore(flags); + break; #endif default: /* Cause a link-time error, the xchg() size is not supported */ -- 2.39.5 (Apple Git-154)
|  |