mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
To: "Paul Walmsley" <pjw@kernel.org>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Albert Ou" <aou@eecs.berkeley.edu>,
	"Alexandre Ghiti" <alex@ghiti.fr>,
	"Will Deacon" <will@kernel.org>,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Mark Rutland" <mark.rutland@arm.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Yury Norov" <yury.norov@gmail.com>,
	"Rasmus Villemoes" <linux@rasmusvillemoes.dk>,
	"Chao-ying Fu" <chao-ying.fu@globalfoundries.com>,
	"Conor Dooley" <conor.dooley@microchip.com>,
	torvalds@linux-foundation.org, olof@lixom.net,
	aleksa.paunovic@htecgroup.com, arikalo@gmail.com,
	"Boqun Feng" <boqun@kernel.org>,
	"Alexei Starovoitov" <ast@kernel.org>,
	"Daniel Borkmann" <daniel@iogearbox.net>,
	"Andrii Nakryiko" <andrii@kernel.org>,
	"Eduard Zingerman" <eddyz87@gmail.com>,
	"Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
	"Martin KaFai Lau" <martin.lau@linux.dev>,
	"Song Liu" <song@kernel.org>,
	"Yonghong Song" <yonghong.song@linux.dev>,
	"Jiri Olsa" <jolsa@kernel.org>,
	"Emil Tsalapatis" <emil@etsalapatis.com>,
	"Ihor Solodrai" <ihor.solodrai@linux.dev>,
	"Luke Nelson" <luke.r.nels@gmail.com>,
	"Xi Wang" <xi.wang@gmail.com>, "Björn Töpel" <bjorn@kernel.org>,
	"Pu Lehui" <pulehui@huawei.com>,
	"Puranjay Mohan" <puranjay@kernel.org>,
	"Masami Hiramatsu" <mhiramat@kernel.org>,
	"Oleg Nesterov" <oleg@redhat.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Daniel Almeida" <daniel.almeida@collabora.com>,
	"Tamir Duberstein" <tamird@kernel.org>,
	"Alexandre Courbot" <acourbot@nvidia.com>,
	"Onur Özkan" <work@onurozkan.dev>,
	"Shuah Khan" <skhan@linuxfoundation.org>,
	"Randy Dunlap" <rdunlap@infradead.org>,
	"Boqun Feng" <boqun@kernel.org>
Cc: linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
	 Vladimir.Kondratiev@mobileye.com, bpf@vger.kernel.org,
	 linux-trace-kernel@vger.kernel.org, linux-doc@vger.kernel.org,
	 Jonathan Corbet <corbet@lwn.net>,
	 Charlie Jenkins <thecharlesjenkins@gmail.com>,
	 Nam Cao <namcao@linutronix.de>,
	rust-for-linux@vger.kernel.org,
	 Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>
Subject: [PATCH v6 0/6] riscv: restrict the ISA used for atomics to avoid unsupported or slow AMO
Date: Tue, 10 Nov 2026 15:20:57 +0200	[thread overview]
Message-ID: <20261110-lrsc-only-v6-0-bafc3cc0fcae@mobileye.com> (raw)

The A extension is Zaamo (AMO*.w/d) plus Zalrsc (LR/SC). The kernel
requires all of it: -march has "a", atomic_add, bitops, xchg and the
like are AMO instructions, cmpxchg is an LR/SC loop.

This series lets the kernel restrict the ISA it uses for atomics to
Zalrsc, when the toolchain can express that, for CPUs where AMO is
missing or slow. MIPS P8700 [1] traps every AMO instruction into
M-mode and emulates it there. The extension is formally present, but a
typical uncontended atomic increment costs:

  native AMO                                    2..5 cycles
  LR/SC, private L1 reservation monitor        6..12 cycles
  LR/SC, PoC (L2) reservation monitor       about 40 cycles
  AMO emulated by an M-mode trap           about 600 cycles

The last two were measured on Mobileye's eyeq7h, which is built on
this CPU for ADAS and autonomous driving. Kernel atomics are on its
scheduling, memory-management and driver paths, so the emulated AMO
cost is not acceptable there. perf bench on eyeq7h, same tree built
with RISCV_ISA_ZAAMO=y and =n, same userspace, built with LR/SC
atomics in both cases so that only the kernel changes:

                                     ZAAMO=y     ZAAMO=n
  sched messaging, 400 processes     0.653 s     0.536 s    -18%
  futex hash, 24 threads          64131 op/s  79142 op/s    +23%
  futex wake, 24 threads            0.221 ms    0.168 ms    -24%
  futex requeue, 24 threads         0.064 ms    0.036 ms    -44%
  futex lock-pi, 24 threads         435 op/s    478 op/s    +10%

futex wake-parallel swings by an order of magnitude between runs on
both kernels and is left out. With the ZAAMO=y kernel the firmware
counter of emulated instructions, fw_illegal_insn, runs at about
4000 per second per CPU at idle, and at about 85000 per second on
CPU0, where network Rx runs, under iperf3 Rx traffic.

Patch 1 makes kprobes and uprobes reject a probe inside an LR/SC
sequence, where the breakpoint trap drops the reservation and the loop
never completes. Both scan forward from the probed instruction using
the constrained-sequence rules of the ISA. The problem exists today,
since cmpxchg is already LR/SC. The patch is independent of the others
and can be merged on its own.

Patch 2 adds RISCV_ISA_ZAAMO, default y, with no change to the default
build. With it off, -march carries _zalrsc instead of "a" and every
kernel atomic is an LR/SC loop, selected with the preprocessor like
the other ISA options. The loops use the ordering convention of the
existing LR/SC code: lr, sc.rl and a full fence when fully ordered,
lr.aq for acquire, sc.rl for release. The choice is made at compile
time rather than with alternatives, so the many kernels for CPUs with
native AMO do not pay for nop padding at every atomic site. Such a
kernel runs on any hart with A, so there is no NONPORTABLE dependency.
It needs a compiler that accepts _zaamo and _zalrsc in -march, GCC
15.1 or later; TOOLCHAIN_HAS_ZALRSC_ZAAMO keeps the option fixed at y
otherwise. Zabha, Zacas, userspace CFI and Rust emit AMO instructions
and depend on RISCV_ISA_ZAAMO. Zalrsc stays mandatory: cmpxchg, the
conditional atomics and futex CAS are LR/SC sequences. Zaamo plus
Zacas, with CAS loops as on x86, would also provide every atomic and
is left for whoever has such hardware.

Patch 3 makes the boot-time check accept a hart that lists "zalrsc"
alone, or "zaamo" and "zalrsc" instead of "a", when the kernel was
built for that. Userspace sees whatever the hart advertises.

Patch 4 sets A when a hart lists "zaamo" and "zalrsc" instead of "a",
so ELF hwcap and /proc/cpuinfo report the same ISA either way.

Patch 5 makes the BPF JIT emit LR/SC loops when Zaamo is off, so BPF
programs do not trap either.

Patch 6 measures at boot whether an uncontended AMO is faster than the
equivalent LR/SC sequence on each CPU and reports the answer to
userspace through a new hwprobe key, RISCV_HWPROBE_KEY_AMO_PERF, the
way the misaligned access speed is reported. On P8700 it says "slow";
a program or a runtime that can choose then knows to use LR/SC. This
patch is optional. eyeq7h does not need it: it is an embedded platform
whose userspace is built for the hardware, not a generic distribution
that has to find out at run time. It is here for whoever has to run
generic userspace on such a CPU.

How the pieces fit together, with "..." for the rest of -march:

  Hardware AMO  DT, cpuinfo  RISCV_ISA_ZAAMO  Userspace -march
  ------------  -----------  ---------------  ---------------------------
  native        a            y (default)      ...a, unchanged
  native        a            n                ...a; only the kernel
                                              switches to LR/SC
  emulated      a            y                ...a or ..._zalrsc; the
                                              kernel traps on every
                                              AMO. This is today.
  emulated      a            n                ...a runs but traps on
                                              every AMO; ..._zalrsc
                                              does not
  emulated      zalrsc       n (y: hart       ..._zalrsc; ...a still
                             rejected)        runs, slowly
  absent        zalrsc       n (y: hart       ..._zalrsc; ...a dies
                             rejected)        with SIGILL

The kernel expands "a" to zaamo and zalrsc, and with patch 4 folds
the two back into "a", so userspace sees the same ISA in hwcap,
hwprobe and /proc/cpuinfo whether the DT lists "a" or both
sub-extensions. For an emulating CPU the firmware chooses between
"a", which is formally true and keeps every existing binary running,
and "zalrsc" alone, which lets userspace that checks hwcap or hwprobe
know not to use AMO; with patch 6, hwprobe says so in either case.
Nothing in the series depends on the last column:
a kernel built without Zaamo runs userspace built either way. Building
userspace without "a" needs the same GCC 15.1 as the kernel and an
-march that spells out the base, e.g. rv64imfdc_zicsr_zifencei_zalrsc,
since "g" implies "a".

Tested on the eyeq7h hardware running locktorture for a several hours.

Conor Dooley NAKed the v5 Kconfig option [2] on the grounds that
Zalrsc-only hardware does not exist and the kernel should not carry
an option for an emulation workaround. The trailer is kept on patch 2.
The option is for hardware that exists, P8700 based eyeq7h, where the
alternative is a kernel that is unusably slow; the series is small,
compile-time only and leaves the default build untouched.

[1] https://mips.com/products/hardware/p8700/
[2] https://lore.kernel.org/linux-riscv/20261106-smock-headband-d6a7d568c228@spud/

Changes in v6:
- Fully ordered LR/SC loops in atomic_fetch_*, test_and_*_bit, xchg
  and futex are now lr, sc.rl and a trailing fence rw,rw, following
  commit 5ce6c1f3535f ("riscv/atomic: Strengthen implementations with
  fences"), instead of lr.aqrl/sc.aqrl.
- test_and_set_bit_lock uses lr.aq with a plain sc, and
  clear_bit_unlock and xor_unlock_is_negative_byte use a plain lr
  with sc.rl, instead of putting the ordering bit on both.
- Bound the futex LR/SC loop to 128 retries and return -EAGAIN, as
  arm64 does; futex_wake_op() retries.
- RISCV_ISA_ZABHA, RISCV_ISA_ZACAS, RISCV_USER_CFI and
  RUSTC_SUPPORTS_RISCV depend on RISCV_ISA_ZAAMO, since Zabha, Zacas,
  ssamoswap and the Rust target emit AMO instructions.
- Drop RISCV_ISA_ZALRSC and RISCV_ISA_A. The Makefile and the boot
  check key on RISCV_ISA_ZAAMO alone.
- kprobes scan forward with the same constrained-sequence rules as
  uprobes, so an lr without an sc, as in __cmpwait(), no longer
  rejects every later probe in the function.
- Move the probes patch first.
- Bring back the boot-time extension check as patch 3, keyed on
  RISCV_ISA_ZAAMO. A hart may list "zalrsc" alone, or "zaamo" and
  "zalrsc" instead of "a".
- Add patch 4: a hart that lists "zaamo" and "zalrsc" gets A set,
  so hwcap and /proc/cpuinfo match a hart that lists "a".
- Add patch 6: probe AMO speed against LR/SC at boot and report it
  through hwprobe, RISCV_HWPROBE_KEY_AMO_PERF.
- Record Conor Dooley's NAK on patch 2.
- Rewrite the cover letter; add perf bench results and a table of
  hardware, DT, Kconfig and userspace combinations.
- Link to v5: https://patch.msgid.link/20261105-lrsc-only-v5-0-f0648f57b2e1@mobileye.com

Changes in v5:
- Treat Zaamo as supported but slow rather than absent. The hart keeps
  advertising "a" and the kernel keeps accepting it, so the boot-time
  extension check patch is dropped.
- Drop the NONPORTABLE dependency. A kernel built without Zaamo runs
  on any hart that implements A.
- Rename TOOLCHAIN_HAS_ZALRSC to TOOLCHAIN_HAS_ZALRSC_ZAAMO and test
  both _zaamo and _zalrsc in -march.
- Explain why RISCV_ISA_ZALRSC and RISCV_ISA_A exist, and why the
  choice is made at compile time rather than with alternatives.
- Add the BPF JIT patch. Without Zaamo the JIT emits LR/SC loops for
  the BPF read-modify-write atomics on RV32 and RV64, and reserves a
  second exception-table entry for the sc of an arena atomic.
- Reject kprobes and uprobes on lr and sc, and on any instruction
  between them.
- Link to v4: https://patch.msgid.link/20261101-lrsc-only-v4-0-4e1d010463b3@mobileye.com

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@mobileye.com>
---
Vladimir Kondratiev (6):
      riscv: probes: reject probes inside an LR/SC sequence
      riscv: build kernel atomics from LR/SC when Zaamo is disabled
      riscv: accept the atomic extensions this kernel was built with
      riscv: report the A extension when Zaamo and Zalrsc are both present
      riscv, bpf: emit LR/SC loops when Zaamo is disabled
      riscv: hwprobe: report whether AMO is faster than LR/SC

 Documentation/admin-guide/kernel-parameters.txt |   7 +
 Documentation/arch/riscv/hwprobe.rst            |  18 +++
 arch/riscv/Kconfig                              |  49 +++++++
 arch/riscv/Makefile                             |  15 +-
 arch/riscv/include/asm/atomic.h                 |  53 ++++++-
 arch/riscv/include/asm/bitops.h                 |  76 +++++++++-
 arch/riscv/include/asm/cmpxchg.h                |  39 ++++-
 arch/riscv/include/asm/cpufeature.h             |   4 +
 arch/riscv/include/asm/futex.h                  |  58 ++++++++
 arch/riscv/include/asm/hwprobe.h                |   2 +-
 arch/riscv/include/asm/insn-def.h               |   5 +
 arch/riscv/include/asm/insn.h                   |  28 ++++
 arch/riscv/include/uapi/asm/hwprobe.h           |   5 +
 arch/riscv/kernel/Makefile                      |   1 +
 arch/riscv/kernel/amo_speed.c                   | 183 ++++++++++++++++++++++++
 arch/riscv/kernel/cpu.c                         |  23 ++-
 arch/riscv/kernel/cpufeature.c                  |   9 ++
 arch/riscv/kernel/entry.S                       |   7 +
 arch/riscv/kernel/head.S                        |  12 ++
 arch/riscv/kernel/probes/decode-insn.c          |  94 ++++++++++++
 arch/riscv/kernel/probes/decode-insn.h          |   7 +
 arch/riscv/kernel/probes/kprobes.c              |  15 +-
 arch/riscv/kernel/probes/uprobes.c              |  31 ++++
 arch/riscv/kernel/sys_hwprobe.c                 |  37 +++++
 arch/riscv/net/bpf_jit.h                        |   1 +
 arch/riscv/net/bpf_jit_comp32.c                 |  81 ++++++++++-
 arch/riscv/net/bpf_jit_comp64.c                 | 108 +++++++++++++-
 arch/riscv/net/bpf_jit_core.c                   |  29 ++++
 28 files changed, 969 insertions(+), 28 deletions(-)
---
base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
change-id: 20260120-lrsc-only-cc06422f5bb1

Best regards,
--  
Vladimir Kondratiev <vladimir.kondratiev@mobileye.com>


             reply	other threads:[~2026-11-10 13:25 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 13:20 Vladimir Kondratiev [this message]
2026-11-10 13:20 ` [PATCH v6 1/6] riscv: probes: reject probes inside an LR/SC sequence Vladimir Kondratiev
2026-11-10 13:20 ` [PATCH v6 2/6] riscv: build kernel atomics from LR/SC when Zaamo is disabled Vladimir Kondratiev
2026-11-10 13:21 ` [PATCH v6 3/6] riscv: accept the atomic extensions this kernel was built with Vladimir Kondratiev
2026-11-10 13:21 ` [PATCH v6 4/6] riscv: report the A extension when Zaamo and Zalrsc are both present Vladimir Kondratiev
2026-11-10 13:21 ` [PATCH v6 5/6] riscv, bpf: emit LR/SC loops when Zaamo is disabled Vladimir Kondratiev
2026-11-10 13:21 ` [PATCH v6 6/6] riscv: hwprobe: report whether AMO is faster than LR/SC Vladimir Kondratiev

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261110-lrsc-only-v6-0-bafc3cc0fcae@mobileye.com \
    --to=vladimir.kondratiev@mobileye.com \
    --cc=a.hindborg@kernel.org \
    --cc=acourbot@nvidia.com \
    --cc=aleksa.paunovic@htecgroup.com \
    --cc=alex@ghiti.fr \
    --cc=aliceryhl@google.com \
    --cc=andrii@kernel.org \
    --cc=aou@eecs.berkeley.edu \
    --cc=arikalo@gmail.com \
    --cc=ast@kernel.org \
    --cc=bjorn3_gh@protonmail.com \
    --cc=bjorn@kernel.org \
    --cc=boqun@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=chao-ying.fu@globalfoundries.com \
    --cc=conor.dooley@microchip.com \
    --cc=corbet@lwn.net \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=emil@etsalapatis.com \
    --cc=gary@garyguo.net \
    --cc=ihor.solodrai@linux.dev \
    --cc=jolsa@kernel.org \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=linux@rasmusvillemoes.dk \
    --cc=lossin@kernel.org \
    --cc=luke.r.nels@gmail.com \
    --cc=mark.rutland@arm.com \
    --cc=martin.lau@linux.dev \
    --cc=memxor@gmail.com \
    --cc=mhiramat@kernel.org \
    --cc=namcao@linutronix.de \
    --cc=ojeda@kernel.org \
    --cc=oleg@redhat.com \
    --cc=olof@lixom.net \
    --cc=palmer@dabbelt.com \
    --cc=peterz@infradead.org \
    --cc=pjw@kernel.org \
    --cc=pulehui@huawei.com \
    --cc=puranjay@kernel.org \
    --cc=rdunlap@infradead.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=skhan@linuxfoundation.org \
    --cc=song@kernel.org \
    --cc=tamird@kernel.org \
    --cc=thecharlesjenkins@gmail.com \
    --cc=tmgross@umich.edu \
    --cc=torvalds@linux-foundation.org \
    --cc=will@kernel.org \
    --cc=work@onurozkan.dev \
    --cc=xi.wang@gmail.com \
    --cc=yonghong.song@linux.dev \
    --cc=yury.norov@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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®