[PATCH v4 0/2] riscv: support CPUs with Zalrsc but not Zaamo

Palmer Dabbelt palmer at dabbelt.com
Tue Nov 3 14:27:51 PST 2026


On Sun, 01 Nov 2026 04:51:38 PST (-0800), vladimir.kondratiev at mobileye.com wrote:
> RISC-V split the A extension into Zaamo (AMO*.w/AMO*.d) and Zalrsc
> (LR/SC). Linux has so far required the whole A extension.
>
> MIPS P8700 [1] implements only Zalrsc. AMO instructions are emulated by a
> trap into SBI. I measured typical userspace atomics on this CPU: an
> LR/SC atomic takes about 40 cycles, an AMO atomic about 600. The same
> ratio applies to kernel refcounts, bitops, xchg and futexes, so the
> kernel needs to emit LR/SC when Zaamo is not implemented.

In RISC-V land, things that are implemented by M-mode traps are 
generally considered "implemented" in the context of supervisor mode, 
just implemented to have low performance.  I don't agree with that 
decision, but that's really an ISA thing and not something we can do 
that much about it Linux.

So I think the first thing you need to decide here is how you're going 
to be treating the atomics: are they really unimplemented, or are they 
implemented but slow?  Right now this is kind of a mixed bag: you're 
sort of treated them as unimplemented in the kernel (or at least parts 
of the kernel), but then implemented in userspace.

If you're going to treat the AMOs as "implemented but slow", then I 
think it's best to see some actual performance numbers for a real 
application.  Sure 600 cycles is slow for an atomic, but I was recently 
playing around with some much larger systems with ~300 cycle AMOs and 
couldn't get any meaningful benchmarks to show up over there -- those 
were OOO cores blocked on bus resources, so a completely different 
problem, but just saying they're 600 cycles so we can't use them isn't 
really good enough -- particularly when the alternative is 40 cycles, 
which is also super slow, so it's not like you can be doing all that 
much with atomics on these cores even with the "fast" sequences.  You're 
probably also going to need some way to tell userspace about this 
"implemented but slow" behavior, similar to how we describe misaligned 
accesses (which is all a bit of a messy retrofit, so maybe don't copy it 
exactly).

If you're going to treat the AMOs as "unimplemented", then we need some 
way to deal with userspace.  Right now we have A as part of all the base 
behaviors we expose to userspace.  We used to have the non-A userspace 
support, but we decided to drop it when upstreaming the port because it 
didn't seem useful to anyone.  There was a design sketched out here with 
a VDSO call for cmpxchg() that looked similar to some of the non-A Arm 
systems, but as far as I know nobody's implemented that in the kernel or 
userspace so it'd need to be proved out.

> Mobileye is going to use the "eyeq7h" platform, built on this CPU, for
> ADAS and autonomous driving. Kernel atomics are on the scheduling,
> memory-management and driver paths of that product, so the emulated
> AMO cost is not acceptable there.

Is that announced anywhere?  All I can find is an EyeQ 6 on the website.

Also: are you planning on continuing with these non-A systems?  Those 
40-cycle atomics are going to burn you at some point, if the plan for 
the next-generation systems is just to go implement A then maybe it's 
best to keep this out of tree.  We already have way too much 
fragmentation in RISC-V land as it is, we don't need any more.

> This series keeps today's default: both extensions on, -march still
> contains "a", generated code is unchanged. Turning Zaamo off is a
> NONPORTABLE choice. The resulting kernel matches one -march, which
> userspace has to use as well, so a runtime alternative would not
> produce a portable image.

It's really not non-portable, though: the Zalrsc code runs fine on 
systems that support Zaamo, it just may be a performance issue.  I'm not 
sure anyone's actually measured that, but I think it's sane to just 
assume that native AMOs are going to out-performance LR/SC on _some_ 
systems.  It's still just a performance thing, though...

> Zalrsc stays mandatory. cmpxchg, conditional atomics and futex CAS are
> already LR/SC sequences; Zaamo cannot replace them. BPF atomic ops
> still emit AMO and remain unsupported on a Zalrsc-only kernel.
>
> [1] https://mips.com/products/hardware/p8700/
>
> Changes in v4:
> - Require a compiler that accepts _zalrsc in -march before Zaamo can
>   be disabled. GCC 15.1 introduces that support. Older compilers keep
>   Zaamo enabled and -march keeps "a".
> - Link to v3: https://patch.msgid.link/20261026-lrsc-only-v3-0-ec29c8190fb1@mobileye.com
>
> Changes in v3:
> - Make Zalrsc mandatory. cmpxchg and the conditional atomics already
>   use LR/SC, so RISCV_ISA_ZALRSC can no longer be turned off.
> - Check AMO and LR/SC support independently. A kernel that emits both
>   requires "a", or both "zaamo" and "zalrsc".
> - Put the LR/SC bitop sequence in its own block so two inlined
>   set_bit or clear_bit calls compile.
> - Remove the LR/SC loop that ran after the hart lottery and accessed
>   address 1. Build the lottery increment with add so RV32 assembles.
> - Add an exception-table entry for sc as well as lr in the futex
>   LR/SC helper.
>
> Changes in v2:
> - Switch from a runtime choice of atomic implementation to a
>   compile-time one, gated by NONPORTABLE.
>
> Signed-off-by: Vladimir Kondratiev <vladimir.kondratiev at mobileye.com>
> ---
> Vladimir Kondratiev (2):
>       riscv: build kernel atomics from LR/SC when Zaamo is disabled
>       riscv: accept the atomic extensions this kernel was built with
>
>  arch/riscv/Kconfig               | 32 +++++++++++++++++++++++
>  arch/riscv/Makefile              | 15 ++++++++---
>  arch/riscv/include/asm/atomic.h  | 56 +++++++++++++++++++++++++++++++++++++++-
>  arch/riscv/include/asm/bitops.h  | 51 ++++++++++++++++++++++++++++++++++++
>  arch/riscv/include/asm/cmpxchg.h | 18 +++++++++++++
>  arch/riscv/include/asm/futex.h   | 53 +++++++++++++++++++++++++++++++++++++
>  arch/riscv/kernel/cpu.c          | 28 +++++++++++++++++---
>  arch/riscv/kernel/entry.S        |  9 +++++++
>  arch/riscv/kernel/head.S         | 14 ++++++++++
>  9 files changed, 267 insertions(+), 9 deletions(-)
> ---
> base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
> change-id: 20260120-lrsc-only-cc06422f5bb1
>
> Best regards,



More information about the linux-riscv mailing list