Re: [PATCH 0/3] sparc32: SMP futexes, casa and idiv emulation
From: Magnus Lindholm
Date: Sun Oct 04 2026 - 06:04:47 EST
Hi Imre,
On Sun, Sep 27, 2026 at 2:59 AM Imre Kaloz <kaloz@xxxxxxxxxx> wrote:
>
> sun4m has no compare-and-swap instruction and casa is optional on
> LEON, so SMP sparc32 has had no futexes, and user code on those CPUs
> has no CAS to build locks from.
>
> Patch 1 implements the futex atomic ops in atomic32.c and drops the
> !(SPARC32 && SMP) dependency of FUTEX. A LEON part that implements
> casa, found by a boot-time probe, runs casa on the user word; other
> CPUs take the __atomic_hash spinlocks.
>
> Patch 2 completes user casa from illegal_instruction on CPUs without
> it, through patch 1's futex_atomic_cmpxchg_inatomic(), so emulated
> casa and the futex ops serialize on the same lock. It is atomic
> against itself and against the futex ops, not against a plain store
> to the same word, so a C library using it has to do its atomic stores
> with casa too.
>
> Patch 3 completes udiv, sdiv and their -cc forms from the same
> do_illegal_instruction() dispatch: SuperSPARC and SuperSPARC-II trap
> those when the {Y, rs1} dividend has significant bits above bit 51,
> which gcc -mcpu=v8 output, including libgcc's __udivdi3, can produce.
> It shares patch 2's windowed-operand helpers and the dispatch block,
> which is why it comes last.
>
> Patch 1 comes first because patch 2 is built on it. On its own it
> races nothing: without patch 2, user casa on these CPUs is SIGILL.
>
> Magnus Lindholm has an independent RFC covering the same ground from
> a different ABI: "[RFC PATCH 0/5] sparc32: kernel assisted
> compare-and-swap, and futex on SMP" (patchwork sparclinux, Message-Id
> 20260923201830.865553-1-linmag7@xxxxxxxxx), with a companion glibc
> series (patchwork glibc, Message-Id
> 20260924064228.867909-1-linmag7@xxxxxxxxx). That RFC adds a new
> software trap, ta 0x11 (trap type 0x91), extending David Miller's
> 2016 CAS-trap prototype at ta 0x23 rather than completing it, so
> userspace has to be rebuilt to call it. This series instead
> completes the casa opcode itself, so a binary already emitting casa
> (gcc -mcpu=leon3 or -mcpu=v9 output, or a C library that encodes it
> as a .word) runs unmodified on a CPU without hardware casa, with no
> new trap number and no libc rebuild. Happy to share the futex and
> do_illegal_instruction() plumbing with whichever ABI lands.
>
> Andreas: do LEON3FT parts want the GRLIB-TN-0010/0011 "nop; .balignl
> 16" alignment before the casa word here, or is the plain encoding as
> posted fine for them?
>
> Notes, not for the log:
>
> - checkpatch on patch 1: "Lines should not end with a '('" is the
> __asm__ __volatile__( idiom of uaccess_32.h; the -ENOSYS warning is
> the futex API's return for an unknown op, as on every architecture.
> "does MAINTAINERS need updating?" on patches 2 and 3 is covered by
> the F: arch/sparc/ entry.
> - On qemu's SS-20 with two SuperSPARCs and the casa emulation alone,
> futex() returns ENOSYS and musl's mutex, PI mutex and robust mutex
> tests fail. With patches 1 and 2 they pass, as does a PI lock
> contended between user casa and FUTEX_LOCK_PI/FUTEX_UNLOCK_PI on
> both CPUs.
> - The casa branch of the futex ops has not run on LEON hardware. The
> probe runs on LEON only; its fixup path, which a LEON without casa
> takes, has run only in a test kernel that forced the probe on
> qemu's SS-20.
> - The divide emulation has run on no CPU that traps it. No sparc32
> model in qemu raises the trap, and no SuperSPARC or SuperSPARC-II
> was available for this series; it is exercised only by build and
> link.
>
> Imre Kaloz (3):
> sparc32: support futexes on SMP
> sparc32: emulate casa on V8 CPUs
> sparc32: emulate integer divide taken as illegal_instruction
>
> arch/sparc/include/asm/futex_32.h | 6 +-
> arch/sparc/kernel/Makefile | 2 +
> arch/sparc/kernel/cas_emu_32.c | 117 +++++++++++++++++++++++++++
> arch/sparc/kernel/div_emu_32.c | 127 ++++++++++++++++++++++++++++++
> arch/sparc/kernel/entry.h | 2 +
> arch/sparc/kernel/traps_32.c | 23 +++++-
> arch/sparc/kernel/unimp_32.h | 71 +++++++++++++++++
> arch/sparc/lib/atomic32.c | 122 ++++++++++++++++++++++++++++
> init/Kconfig | 1 -
> 9 files changed, 468 insertions(+), 3 deletions(-)
> create mode 100644 arch/sparc/kernel/cas_emu_32.c
> create mode 100644 arch/sparc/kernel/div_emu_32.c
> create mode 100644 arch/sparc/kernel/unimp_32.h
>
>
> base-commit: 62f4c998b297cf233997a2b4cd6fc2d2df0319c9
> --
> 2.47.3
>
I'm following up on this series after some more testing, overall:
very nice series, this lets us run modern linux user-space on
sparc32 hardware again, with minimal changes to glibc, which I
believe is in line with what Zanella responded on the glibc mailing
list: get the support on the kernel first, and glibc can catch up
transparently.
This replaces my own CAS/futex v3 series entirely:
https://lore.kernel.org/sparclinux/20260923201830.865553-1-linmag7@xxxxxxxxx/
As well as my previous fix for UDIV/SDIV:
https://lore.kernel.org/sparclinux/20260924205646.870950-1-linmag7@xxxxxxxxx/
This series is altogether a better solution for getting sparc32 userland
up and running properly.
One thing worth mentioning for anyone testing this: a stock sparc32
glibc build (mine, with its own kernel-trap fallback) does not just
lose a feature on this kernel, it hard-crashes - cas32() falls
through its HWCAP dispatch to a fatal abort the moment anything
needs a real compare-and-swap, which in practice means every
threaded program, including sshd's own connection handling.
Confirmed this the hard way on real hardware.
The glibc fix this needs in return is smaller than my CAS/futex
series ever was, once the kernel completes casa
unconditionally, cas32() collapses to one unconditional casa
instruction, with the whole HWCAP dispatch, the kernel-trap
fallback, and the fatal path deleted outright. Built and tested that
reduced patch against a real portage glibc build.
Tested on a real SPARCstation 20, on both a HyperSPARC and a real
dual SuperSPARC-II module, so the udiv erratum genuinely traps:
- casa and SMP futex (plain and PI) all work correctly
- 8-thread pthread_mutex contention, 1.6M locked increments,
zero lost, on both CPUs
- userspace casa-based locking and FUTEX_LOCK_PI/UNLOCK_PI
correctly serialize on the same lock word under contention
- udiv/sdiv: 10/10 correct, including the saturation boundary in
both directions, INT64_MIN / -1, divide-by-zero -> SIGFPE, and
udivcc condition codes
Individual Tested-by tags follow on each patch. Thanks for doing
this.
Magnus