Эх сурвалжийг харах

uclibc-ng: backport the m68k CAS guard to 1.0.59

1.0.59 picks the atomic implementation by asking whether the core is a
ColdFire, assuming everything else has the CAS instruction. The 68000 and
68010 do not - CAS arrived with the 68020 - so a build for them dies at the
first atomic:

  {standard input}:33: Error: invalid instruction for this architecture;
    needs 68020 or higher -- statement `cas.l %d0,%d3,(%a0)' ignored

Found by the Buildroot autobuilders and reported by Waldemar; the same error
stops a 68000 toolchain here in libc/stdlib/__cxa_finalize.c. The patch tests
for the cores that have CAS and lets the others use the kernel helper, which
is what ColdFire already does. Sent to devel@uclibc-ng.org, so this can go
once 1.0.60 is out.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
Signed-off-by: Waldemar Brodkorb <wbx@openadk.org>
ramin 1 долоо хоног өмнө
parent
commit
08a6596c34

+ 114 - 0
toolchain/uclibc-ng/patches/1.0.59/0002-m68k-use-kernel-helper-on-cores-without-cas.patch

@@ -0,0 +1,114 @@
+From b6506973a202de45561a8f52cd20b17453b77c14 Mon Sep 17 00:00:00 2001
+From: ramin <lordrasmus@gmail.com>
+Date: Mon, 24 Aug 2026 13:03:05 +0200
+Subject: [PATCH] m68k: use the kernel helper on every core without CAS, not
+ just ColdFire
+
+The atomic header split the world into ColdFire and "the rest", assuming the
+rest was 68020 and up. That holds for the MMU port, but not for the 68000 and
+68010, which have no atomic read-modify-write instruction either. Building for
+one of them stops at the first cas:
+
+  Error: invalid instruction for this architecture; needs 68020 or higher
+         (68020 [68k, 68ec020], 68030 [68ec030], 68040 [68ec040],
+          68060 [68ec060]) -- statement `cas.l %d0,%d1,(%a1)' ignored
+
+Reported by Waldemar Brodkorb from a Buildroot autobuilder failure; Buildroot
+supports m68000 and has at least one user on it.
+
+Decide by the presence of CAS instead. The instruction came with the 68020, so
+the test is the list of the 68020-and-up cores: gcc defines a separate macro
+per core and does not imply __mc68020__ on the later ones, and __mc68000__ is
+no help because it is defined on every m68k, the 68040 and ColdFire included.
+
+Nothing else changes: the kernel's atomic_cmpxchg_32 is syscall 335 "common"
+in arch/m68k/kernel/syscalls/syscall.tbl and has an implementation for the MMU
+as well as the noMMU port, so the branch the old cores now take is the one
+ColdFire has been using all along - including its documented limit that the
+8- and 16-bit variants stay non-atomic, since the helper is 32-bit only.
+
+Checked with a cross gcc over -m68000, -m68010, -m68020, -m68030, -m68040,
+-m68060, -mcpu=5206 and -mcpu=5208: the three old cores and both ColdFires
+select the helper, the four others select cas, and each branch assembles for
+the cores that select it.
+
+Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
+---
+ libc/sysdeps/linux/m68k/bits/atomic.h | 32 ++++++++++++++++++---------
+ 1 file changed, 22 insertions(+), 10 deletions(-)
+
+diff --git a/libc/sysdeps/linux/m68k/bits/atomic.h b/libc/sysdeps/linux/m68k/bits/atomic.h
+index cf7fd5f65..6acec1ed8 100644
+--- a/libc/sysdeps/linux/m68k/bits/atomic.h
++++ b/libc/sysdeps/linux/m68k/bits/atomic.h
+@@ -3,13 +3,15 @@
+ 
+    Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ 
+-   m68k (68020 and up, which is everything the MMU Linux port runs on) has
+-   the CAS instruction.  We implement the compare-and-exchange primitive
+-   with cas.b/cas.w/cas.l; include/atomic.h derives every higher-level
+-   operation from it.
++   The CAS instruction arrived with the 68020.  Where it exists we implement
++   the compare-and-exchange primitive with cas.b/cas.w/cas.l and let
++   include/atomic.h derive every higher-level operation from it.
+ 
+-   ColdFire has no CAS at all, so there we use the kernel's
+-   atomic_cmpxchg_32 helper, which exists for exactly this reason.
++   ColdFire, 68000 and 68010 have no atomic read-modify-write instruction at
++   all.  There we use the kernel's atomic_cmpxchg_32 helper, which exists for
++   exactly this reason and is available on every m68k (syscall 335, "common"
++   in arch/m68k/kernel/syscalls/syscall.tbl, with an implementation for both
++   the MMU and the noMMU port).
+ 
+    Without this file m68k fell back to the generic non-atomic
+    bits/atomic.h, whose "atomic" compare-and-exchange is a plain
+@@ -22,7 +24,17 @@
+ #define _M68K_BITS_ATOMIC_H	1
+ 
+ #include <stdint.h>
+-#ifdef __mcoldfire__
++
++/* CAS came with the 68020.  gcc sets a separate macro per core and does not
++   imply __mc68020__ on the later ones, hence the list; __mc68000__ is no help
++   here, it is defined on every m68k, the 68040 and ColdFire included.
++   Everything without CAS - ColdFire, 68000, 68010 - uses the kernel helper.  */
++#if defined __mc68020__ || defined __mc68030__ \
++    || defined __mc68040__ || defined __mc68060__
++# define __M68K_HAVE_CAS	1
++#endif
++
++#ifndef __M68K_HAVE_CAS
+ # include <sys/syscall.h>
+ #endif
+ 
+@@ -58,7 +70,7 @@ typedef uintmax_t uatomic_max_t;
+ #define atomic_read_barrier()	atomic_full_barrier ()
+ #define atomic_write_barrier()	atomic_full_barrier ()
+ 
+-#ifndef __mcoldfire__
++#ifdef __M68K_HAVE_CAS
+ 
+ /* cas Dc,Du,<ea>: compare <ea> with Dc; if equal store Du, else load <ea>
+    into Dc.  Either way Dc ends up holding the original *MEM, which is the
+@@ -87,7 +99,7 @@ typedef uintmax_t uatomic_max_t;
+ 		       : "memory");					\
+      __ret; })
+ 
+-#else /* __mcoldfire__ */
++#else /* !__M68K_HAVE_CAS */
+ 
+ /* d0 = syscall number, d1 = newval, d2 = oldval, a0 = mem; the helper
+    returns the previous value.  The swap happens inside the syscall, so
+@@ -116,7 +128,7 @@ typedef uintmax_t uatomic_max_t;
+ #define __arch_compare_and_exchange_val_16_acq(mem, newval, oldval) \
+   __arch_compare_and_exchange_val_8_acq (mem, newval, oldval)
+ 
+-#endif /* __mcoldfire__ */
++#endif /* __M68K_HAVE_CAS */
+ 
+ /* m68k has no 64-bit CAS; NPTL and include/atomic.h only use int- and
+    pointer-sized objects, so the bysize dispatch never reaches this.  */
+-- 
+2.53.0
+