Re: [PATCH bpf v2] bpf, riscv: Make arena support depend on ZACAS

From: Pu Lehui

Date: Fri Sep 04 2026 - 23:13:12 EST


Hi Pei,

On 2026/9/2 14:14, Chen Pei wrote:
The arena range tree allocates its nodes with kmalloc_nolock() since
commit f8c67d8550ee ("bpf: Use kmalloc_nolock() in range tree").
kmalloc_nolock() requires slab caches with cmpxchg128 support
(__CMPXCHG_DOUBLE); on riscv cmpxchg128 is provided by the ZACAS
extension. On systems without ZACAS every arena map creation fails

This limitation has a significant impact, as much of the hardware on the market lacks ZACAS support given that it is not mandatory in RVA23.

with a misleading -ENOMEM.

Report the missing support instead: make bpf_jit_supports_arena()
return system_has_cmpxchg128() where it is defined, so arena map

Originally, I thought rv_ext_enabled(ZACAS) && IS_ENABLED(CONFIG_TOOLCHAIN_HAS_ZACAS) would make it more explicit, but system_has_cmpxchg128() seems to better capture what we were missing.


Acked-by: Pu Lehui <pulehui@xxxxxxxxxx>

creation fails with -EOPNOTSUPP on systems without ZACAS. The macro
is only defined when both CONFIG_RISCV_ISA_ZACAS and
CONFIG_TOOLCHAIN_HAS_ZACAS are enabled, so guard it with #ifdef the
same way mm/slab.h consumes it, and reject arena otherwise. This
matches how arena BPF_CMPXCHG instructions are already gated on ZACAS
in bpf_jit_supports_insn().

Fixes: f8c67d8550ee ("bpf: Use kmalloc_nolock() in range tree")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Chen Pei <cp0613@xxxxxxxxxxxxxxxxx>
---
Changes since v1:
- Guard system_has_cmpxchg128() with #ifdef instead of calling it
unconditionally: the macro is only defined when both
CONFIG_RISCV_ISA_ZACAS and CONFIG_TOOLCHAIN_HAS_ZACAS are enabled
(as reported by sashiko-bot), so v1 broke the build when either
was disabled. This mirrors how mm/slab.h consumes the macro.

Why #ifdef rather than rv_ext_enabled(ZACAS)? The predicates differ
exactly in the configurations that matter:

scenario (ISA_ZACAS/TOOLCHAIN/hw) v1 rv_ext_enabled #ifdef
ISA=n or TOOLCHAIN=n build fails rejects rejects
ISA=y TOOLCHAIN=n hw has ZACAS build fails accepts, then rejects
-ENOMEM again
ISA=y TOOLCHAIN=y hw has ZACAS exact exact exact

rv_ext_enabled(ZACAS) does not check CONFIG_TOOLCHAIN_HAS_ZACAS, but
slab's cmpxchg128 - and thus kmalloc_nolock() - does require it, so
on an old toolchain with ZACAS hardware it would accept arena maps
and bring back the very -ENOMEM failure this patch fixes. The #ifdef
form builds in every configuration and matches exactly the
kmalloc_nolock() availability gate in mm/slab.h.

This issue was reported by sashiko-bot:
https://sashiko.dev/#/patchset/20260901120013.16104-1-cp0613@xxxxxxxxxxxxxxxxx?part=1

Question for reviewers: should the arena selftests gate on ZACAS,
e.g. probing it via riscv_hwprobe() (RISCV_ISA_EXT_ZACAS) and
SKIPping cleanly on systems without the extension?

riscv isn't currently integrated into the BPF CI, and handling this locally via qemu is fairly straightforward, so I'm not entirely sure this is strictly necessary.


arch/riscv/net/bpf_jit_comp64.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 74efe4b138d2..151031e97a24 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -2128,7 +2128,15 @@ bool bpf_jit_supports_ptr_xchg(void)
bool bpf_jit_supports_arena(void)
{
- return true;
+ /*
+ * The arena range tree uses kmalloc_nolock(), which needs
+ * cmpxchg128, provided by ZACAS on riscv.
+ */
+#ifdef system_has_cmpxchg128
+ return system_has_cmpxchg128();
+#else
+ return false;
+#endif
}
bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)