mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs
@ 2026-11-02 22:07 Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 1/8] selftests/bpf: Build callx tests with GCC that defines __BPF_FEATURE_CALLX Vineet Gupta
                   ` (7 more replies)
  0 siblings, 8 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

This series came out of testing a still in-works __arena support for
BPF_GCC and anomalies seen in the A/B reports.

BPF_GCC selftest builds reports a number of things that are not true.
 - Tests the compiler cannot build do not appear at all, so the
   report is silent about them
 - Others are compiled down to an empty body and report OK despite
   not even been executed
 - Two programs that fail to verify take four unrelated tests down with
   them, because everything in that object is loaded together.
 - Unconditional gating on __clang__ when newer GCC support for those
   is coming online.

Only 7/8 needs the in-works arena support to be exercised at all; the
rest are measured below with a stock bpf-gcc.  Nothing in the series
changes what clang emits.

What each patch does, and what it measurably changes.  Numbers are
test_progs on bpf-next with a stock bpf-gcc:

 1/8: Gate the callx tests on CAN_USE_CALLX, which also accepts a GCC
      defining __BPF_FEATURE_CALLX.
   -> 79 subtests newly visible, 78 OK and one @unpriv SKIP; the two
      dummies retire; callx_rodata_lskel SKIP -> OK.

 2/8: Keep clang-only warning flags out of GCC builds.

 3/8: Add __skip_without_arena, and give each arena guard an #else
      dummy carrying it.
   -> 7 subtests newly visible, all SKIP; arena_kfunc_jit OK -> SKIP.

 4/8: Make arena_base() opaque to GCC's -Warray-bounds, behind
      #ifdef __clang__ since clang does not warn.
   -> no verdict change.  +35 insns over 20 call sites under GCC;
      clang output unchanged, bit for bit.

 5/8: Tag the tests whose body dereferences an arena pointer, and only
      those; drop the in-body guards.
   -> 13 subtests OK -> SKIP, check_arena_arg_ret FAIL -> SKIP, and
      verifier_arena itself FAIL -> OK.  The rest now actually run.

 6/8: Cast explicitly with bpf_addr_space_cast() in the arena subprog
      and callback faults, as the sibling tests already do.
   -> 15 FAIL -> OK, and 5 subtests newly visible.

 7/8: Write the mixed arena/scalar ALU tests in asm, rather than a
      volatile register variable GCC may optimise away.
   -> not exercised by a stock bpf-gcc.

 8/8: trigger() in the four struct_ops arena progs is guarded in-body
      and test_loader does not drive them, so the tag cannot reach
      them; use the flag-in-.data pattern from linked_externs.c.
   -> 2 tests stop reporting a vacuous OK.  The other two need a
      testmod BTF carrying the arena tag, so are unreached here.

Totals for the series.  Nothing regresses:

  FAIL  472 -> 456        OK -> FAIL regressions:  0
  OK   7061 -> 7141
  SKIP  753 ->  779

Two things worth re-iterating explicitly:

 - 1/8 needs a GCC defining __BPF_FEATURE_CALLX, in bleeding-edge
   but not released yet.

 - 7/8, needs a GCC with arena support; that work is coming along
   but not yet ready for public review.

v1 -> v2:

 - 1/8: the __skip() reason named only x86/arm64 while CAN_USE_CALLX
   also accepts riscv64.  Say "arch JIT" instead of listing them, so
   the string cannot go stale the next time an arch is added.  (bot)
 - 3/8: jit_insns_arena.c was missed.  Both of its programs are inside
   the guard, so without arena support the object has none at all and
   RUN_TESTS(jit_insns_arena) ran zero subtests without saying so.
   (bot)
 - 5/8: commit message only.  It cited arena_types to argue the kfunc
   tests need no cast, but the address parameters carry the __ign
   suffix, so get_kfunc_arg_type() returns ARG_IGNORE and
   check_func_arg() returns before any register type check.
   Conclusion unchanged, for a better reason.  (bot)
 - 5/8: arena_kfunc.c, verifier_arena_globals1.c and
   verifier_arena_globals2.c had the same empty-body shape and were
   missed; nine more guards go and seven more tags arrive.
   arena_kfunc.c alone had eight subtests reporting a vacuous OK.
 - 8/8: new patch, for the four struct_ops arena progs.

The three bot findings prompted a sweep of every prog with an arena
guard, which is where the last two came from.  The totals above were
re-measured on the series as posted.

v2 -> v3:

 - Rebased on bpf-next.
 - 1/8: the bot asked about data_in_arena.c, whose use_ops() gated an
   indirect call on __clang__ with no arch condition.  That file has
   since gone in 3c13b2e5a40e ("selftests/bpf: Remove tests for global
   data in arena"), so nothing is left to convert.  The missing word in
   the commit message is fixed.  (bot)
 - 7/8: the comment on the r9 load said it was what makes libbpf record
   the arena, which stopped being true with cd7a395838cb ("libbpf: Bind
   the arena of an object to every program in it").  The load is now
   only a fallback for a kernel without fd_array_cnt and for the light
   skeleton; say that instead.  (bot)

Link: https://lore.kernel.org/bpf/20261028000411.4010967-1-vineet.gupta@linux.dev/ [v1]
Link: https://lore.kernel.org/bpf/20261028204158.1021284-1-vineet.gupta@linux.dev/ [v2]

Vineet Gupta (8):
  selftests/bpf: Build callx tests with GCC that defines
    __BPF_FEATURE_CALLX
  selftests/bpf: don't pass clang-only warning flags to GCC
  selftests/bpf: report SKIP for arena tests a compiler cannot build
  selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds
  selftests/bpf: don't report arena tests as passing with an empty body
  selftests/bpf: cast explicitly in the arena subprog and callback
    faults
  selftests/bpf: write the mixed arena/scalar ALU tests in asm
  selftests/bpf: skip the struct_ops arena tests without compiler
    support

 tools/testing/selftests/bpf/Makefile          |   8 +-
 .../testing/selftests/bpf/Makefile.buildvars  |   6 +-
 .../bpf/libarena/include/bpf_arena_common.h   |  16 +++
 .../bpf/prog_tests/callx_rodata_lskel.c       |   2 +-
 .../bpf/prog_tests/test_struct_ops_arena.c    |  27 ++++
 .../testing/selftests/bpf/progs/arena_kfunc.c |  18 +--
 .../selftests/bpf/progs/arena_kfunc_jit.c     |   9 ++
 tools/testing/selftests/bpf/progs/bpf_misc.h  |  21 +++
 .../selftests/bpf/progs/callx_rodata.c        |   4 +-
 .../bpf/progs/compute_live_registers.c        |  10 ++
 .../selftests/bpf/progs/jit_insns_arena.c     |  10 ++
 tools/testing/selftests/bpf/progs/stream.c    |   7 +-
 .../selftests/bpf/progs/struct_ops_arena.c    |  10 ++
 .../bpf/progs/struct_ops_arena_autobind.c     |  10 ++
 .../bpf/progs/struct_ops_arena_member.c       |  10 ++
 .../progs/struct_ops_arena_member_render.c    |  10 ++
 .../selftests/bpf/progs/verifier_arena.c      | 131 +++++++++---------
 .../bpf/progs/verifier_arena_globals1.c       |   6 +-
 .../bpf/progs/verifier_arena_globals2.c       |   3 +-
 .../bpf/progs/verifier_arena_large.c          |  24 ++--
 .../selftests/bpf/progs/verifier_callx.c      |   5 +-
 .../bpf/progs/verifier_callx_rodata.c         |   5 +-
 .../selftests/bpf/progs/verifier_ldsx.c       |   9 ++
 .../selftests/bpf/progs/verifier_zext.c       |   9 ++
 24 files changed, 253 insertions(+), 117 deletions(-)

-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next v3 1/8] selftests/bpf: Build callx tests with GCC that defines __BPF_FEATURE_CALLX
  2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
@ 2026-11-02 22:07 ` Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 2/8] selftests/bpf: don't pass clang-only warning flags to GCC Vineet Gupta
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

Commit 7cd1f73b37ea ("selftests/bpf: Fix build of callx tests with GCC")
gated the callx progs on __clang__. GCC had indirect call support which was
recently refurbished along with a __BPF_FEATURE_CALLX macro [1], so gate
on that as well so once this GCC is released, the tests start passing.

Put the arch and compiler conditions in a CAN_USE_CALLX macro in
bpf_misc.h, and use it in all the test programs.

While at it, mark the placeholder programs left for unsupported
toolchains and arches with __skip(), so they report SKIP rather than OK.

[1] https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=ffe3ead4a8ad704b557b0cfa4f823df647c65a0d

Measured on bpf-next with a stock bpf-gcc that defines
__BPF_FEATURE_CALLX, test_progs before and after: 79 subtests run that
previously did not exist in the report, 78 OK and one @unpriv SKIP,
with no failures.  The two dummy placeholders retire and
callx_rodata_lskel goes SKIP -> OK.

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 .../testing/selftests/bpf/prog_tests/callx_rodata_lskel.c  | 2 +-
 tools/testing/selftests/bpf/progs/bpf_misc.h               | 7 +++++++
 tools/testing/selftests/bpf/progs/callx_rodata.c           | 4 ++--
 tools/testing/selftests/bpf/progs/verifier_callx.c         | 5 ++---
 tools/testing/selftests/bpf/progs/verifier_callx_rodata.c  | 5 ++---
 5 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/callx_rodata_lskel.c b/tools/testing/selftests/bpf/prog_tests/callx_rodata_lskel.c
index f6ef67c3141e..acd821fb568f 100644
--- a/tools/testing/selftests/bpf/prog_tests/callx_rodata_lskel.c
+++ b/tools/testing/selftests/bpf/prog_tests/callx_rodata_lskel.c
@@ -36,7 +36,7 @@ static void __test_callx_rodata_lskel(void)
 	if (!ASSERT_OK_PTR(skel, "open"))
 		return;
 
-	/* gcc doesn't support indirect calls */
+	/* toolchain or JIT can't do callx */
 	if (skel->rodata->skip) {
 		test__skip();
 		goto out;
diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index d7f706c3bc4a..1b264480e128 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -295,6 +295,13 @@
 #define CAN_USE_LOAD_ACQ_STORE_REL
 #endif
 
+/* clang always emits callx, gcc only when it defines __BPF_FEATURE_CALLX */
+#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) ||	\
+     (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64)) &&		\
+	(defined(__clang__) || defined(__BPF_FEATURE_CALLX))
+#define CAN_USE_CALLX
+#endif
+
 #if defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86)
 #define SPEC_V1
 #endif
diff --git a/tools/testing/selftests/bpf/progs/callx_rodata.c b/tools/testing/selftests/bpf/progs/callx_rodata.c
index e3f8335f80f8..8c28f01b7113 100644
--- a/tools/testing/selftests/bpf/progs/callx_rodata.c
+++ b/tools/testing/selftests/bpf/progs/callx_rodata.c
@@ -4,13 +4,14 @@
 #include <stdbool.h>
 #include <linux/bpf.h>
 #include <bpf/bpf_helpers.h>
+#include "bpf_misc.h"
 
 /* set by user space before the programs are loaded, it's in .rodata too */
 const volatile int bias = 1;
 
 int op_idx;
 
-#ifdef __clang__
+#ifdef CAN_USE_CALLX
 
 const volatile bool skip = false;
 
@@ -48,7 +49,6 @@ int both_ops(void *ctx)
 
 #else
 
-/* gcc doesn't support indirect calls */
 const volatile bool skip = true;
 
 SEC("socket")
diff --git a/tools/testing/selftests/bpf/progs/verifier_callx.c b/tools/testing/selftests/bpf/progs/verifier_callx.c
index 7e59188d9fca..ca1aef34ab72 100644
--- a/tools/testing/selftests/bpf/progs/verifier_callx.c
+++ b/tools/testing/selftests/bpf/progs/verifier_callx.c
@@ -6,9 +6,7 @@
 #include "bpf_misc.h"
 #include "../../../include/linux/filter.h"
 
-/* gcc doesn't support indirect calls */
-#if defined(__clang__) && (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
-    (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64))
+#ifdef CAN_USE_CALLX
 
 #define CALLX_INSN(DST, SRC, OFF, IMM) \
 	BPF_RAW_INSN(BPF_JMP | BPF_CALL | BPF_X, DST, SRC, OFF, IMM)
@@ -1075,6 +1073,7 @@ int callx_c_ops_on_stack(void *ctx)
 #else
 
 SEC("socket")
+__skip("callx needs arch JIT and compiler support")
 __success
 int dummy(void *ctx)
 {
diff --git a/tools/testing/selftests/bpf/progs/verifier_callx_rodata.c b/tools/testing/selftests/bpf/progs/verifier_callx_rodata.c
index b2ee0c8e042b..642071fa7498 100644
--- a/tools/testing/selftests/bpf/progs/verifier_callx_rodata.c
+++ b/tools/testing/selftests/bpf/progs/verifier_callx_rodata.c
@@ -6,9 +6,7 @@
 #include "bpf_misc.h"
 #include "../../../include/linux/filter.h"
 
-/* gcc doesn't support indirect calls */
-#if defined(__clang__) && (defined(__TARGET_ARCH_x86) || defined(__TARGET_ARCH_arm64) || \
-    (defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64))
+#ifdef CAN_USE_CALLX
 
 /*
  * Read-only data with pointers to functions, where the compiler puts tables
@@ -992,6 +990,7 @@ int callx_c_packed_struct(void *ctx)
 #else
 
 SEC("socket")
+__skip("callx needs arch JIT and compiler support")
 __success
 int dummy(void *ctx)
 {
-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next v3 2/8] selftests/bpf: don't pass clang-only warning flags to GCC
  2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 1/8] selftests/bpf: Build callx tests with GCC that defines __BPF_FEATURE_CALLX Vineet Gupta
@ 2026-11-02 22:07 ` Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 3/8] selftests/bpf: report SKIP for arena tests a compiler cannot build Vineet Gupta
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

The clang only togges are passed to every BPF object build, including
for BPF_GCC build.

GCC accepts an unknown -Wno-foo silently until some other diagnostic fires,
and then appends a note to it, so every warning in a bpf_gcc build comes with
two lines of noise:

  cc1: note: unrecognized command-line option '-Wno-initializer-overrides' may have been intended to silence earlier diagnostics
  cc1: note: unrecognized command-line option '-Wno-microsoft-anon-tag' may have been intended to silence earlier diagnostics

Collect them in CLANG_BPF_CFLAGS and hand them only to the clang
flavors, through the per-flavor BPF_CC_FLAGS that Makefile.skel appends
after BPF_CFLAGS.

Only these two are clang-only; -Wno-compare-distinct-pointer-types and
-fms-extensions are understood by GCC 14 and later and stay in
BPF_CFLAGS.

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 tools/testing/selftests/bpf/Makefile           | 8 ++++----
 tools/testing/selftests/bpf/Makefile.buildvars | 6 ++++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index c99e0f623e10..77682bf28c6e 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -376,7 +376,7 @@ CLANG_TARGET_ARCH = --target=$(notdir $(CROSS_COMPILE:%-=%))
 endif
 
 CLANG_SYS_INCLUDES = $(call get_sys_includes,$(CLANG),$(CLANG_TARGET_ARCH))
-CLANG_CFLAGS = $(CLANG_SYS_INCLUDES)
+CLANG_CFLAGS = $(CLANG_SYS_INCLUDES) $(CLANG_BPF_CFLAGS)
 
 # genkey writes both outputs. Pattern rules group them even on make
 # versions before 4.3, preventing concurrent genkey invocations.
@@ -511,7 +511,7 @@ BINARY := test_progs
 BPF_CC := $(CLANG)
 BPF_CC_MSG := CLNG-BPF
 BPF_SYS_INCLUDES := $(CLANG_SYS_INCLUDES)
-BPF_CC_FLAGS := -O2 $(BPF_TARGET_ENDIAN) -mcpu=v3
+BPF_CC_FLAGS := -O2 $(BPF_TARGET_ENDIAN) -mcpu=v3 $(CLANG_BPF_CFLAGS)
 BPF_DEFINES := -DENABLE_ATOMICS_TESTS
 include Makefile.skel
 
@@ -527,12 +527,12 @@ $(OUTPUT)/test_progs: $(RUNNER_PREREQS) $(BPF_OBJS) $(ALL_SKELS) FORCE
 
 $(OUTPUT)/test_progs-no_alu32: $(RUNNER_PREREQS) FORCE
 	+$(Q)$(RUNNER_MAKE) RUNNER=test_progs FLAVOR=no_alu32 TESTS_DIR=prog_tests \
-		$(CLANG_RUNNER_ARGS) BPF_CC_FLAGS='-O2 $(BPF_TARGET_ENDIAN) -mcpu=v2'
+		$(CLANG_RUNNER_ARGS) BPF_CC_FLAGS='-O2 $(BPF_TARGET_ENDIAN) -mcpu=v2 $(CLANG_BPF_CFLAGS)'
 
 ifneq ($(CLANG_CPUV4),)
 $(OUTPUT)/test_progs-cpuv4: $(RUNNER_PREREQS) FORCE
 	+$(Q)$(RUNNER_MAKE) RUNNER=test_progs FLAVOR=cpuv4 TESTS_DIR=prog_tests \
-		$(CLANG_RUNNER_ARGS) BPF_CC_FLAGS='-O2 $(BPF_TARGET_ENDIAN) -mcpu=v4' \
+		$(CLANG_RUNNER_ARGS) BPF_CC_FLAGS='-O2 $(BPF_TARGET_ENDIAN) -mcpu=v4 $(CLANG_BPF_CFLAGS)' \
 		BPF_DEFINES=-DENABLE_ATOMICS_TESTS
 endif
 
diff --git a/tools/testing/selftests/bpf/Makefile.buildvars b/tools/testing/selftests/bpf/Makefile.buildvars
index d2a0c0031b87..4d25a736376c 100644
--- a/tools/testing/selftests/bpf/Makefile.buildvars
+++ b/tools/testing/selftests/bpf/Makefile.buildvars
@@ -132,13 +132,15 @@ BPF_CFLAGS = -g -Wall -Werror -D__TARGET_ARCH_$(SRCARCH) $(MENDIAN)	\
 	     -I$(abspath $(OUTPUT)/../usr/include)			\
 	     -std=gnu11		 					\
 	     -fno-strict-aliasing 					\
-	     -Wno-microsoft-anon-tag					\
 	     -fms-extensions						\
 	     -Wno-compare-distinct-pointer-types			\
-	     -Wno-initializer-overrides					\
 	     #
 # TODO: enable me -Wsign-compare
 
+# Warning flags that only clang has.  GCC accepts an unknown -Wno-foo
+# silently and then notes it on the next diagnostic it emits.
+CLANG_BPF_CFLAGS := -Wno-microsoft-anon-tag -Wno-initializer-overrides
+
 VERIFY_SIG_SETUP := $(CURDIR)/verify_sig_setup.sh
 VERIFICATION_CERT   := $(BUILD_DIR)/signing_key.der
 PRIVATE_KEY := $(BUILD_DIR)/signing_key.pem
-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next v3 3/8] selftests/bpf: report SKIP for arena tests a compiler cannot build
  2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 1/8] selftests/bpf: Build callx tests with GCC that defines __BPF_FEATURE_CALLX Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 2/8] selftests/bpf: don't pass clang-only warning flags to GCC Vineet Gupta
@ 2026-11-02 22:07 ` Vineet Gupta
  2026-11-02 22:36   ` Alexei Starovoitov
  2026-11-02 22:07 ` [PATCH bpf-next v3 4/8] selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds Vineet Gupta
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

Tests guarded by __BPF_FEATURE_ADDR_SPACE_CAST don't have a dummy fall back
when the compiler doesn't support the feature: so they are absent from such
a report entirely.
Every subtest inside one of those guards is invisible: 24 across seven
files, plus the five in stream_arena_fault_address, which has no guard
and fails to load instead (addressed separately, later in this series).

Give each guard an #else with a dummy marked __skip(), so the skip gap is
reported rather than invisible.  Add __skip_without_arena for it, which
expands to __skip() with a fixed reason when the compiler cannot do arena.

Measured on bpf-next with a stock bpf-gcc, test_progs before and after:
seven subtests appear that were previously absent from the report
altogether, and arena_kfunc_jit goes OK -> SKIP because every subtest
it has is now one of them.

  arena_kfunc_jit/arena_unsupported          SKIP
  compute_live_registers/arena_unsupported   SKIP
  jit_insns/arena_unsupported                SKIP
  verifier_arena/arena_unsupported           SKIP
  verifier_arena_large/arena_unsupported     SKIP
  verifier_ldsx/arena_unsupported            SKIP
  verifier_zext/arena_unsupported            SKIP
jit_insns_arena.c needs the same treatment and is easy to miss: both
of its programs are inside the guard, so without arena support the
object has none at all and RUN_TESTS(jit_insns_arena) runs zero
subtests without saying so.

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 .../testing/selftests/bpf/progs/arena_kfunc_jit.c  |  9 +++++++++
 tools/testing/selftests/bpf/progs/bpf_misc.h       | 14 ++++++++++++++
 .../selftests/bpf/progs/compute_live_registers.c   | 10 ++++++++++
 .../testing/selftests/bpf/progs/jit_insns_arena.c  | 10 ++++++++++
 tools/testing/selftests/bpf/progs/verifier_arena.c |  9 +++++++++
 .../selftests/bpf/progs/verifier_arena_large.c     | 10 ++++++++++
 tools/testing/selftests/bpf/progs/verifier_ldsx.c  |  9 +++++++++
 tools/testing/selftests/bpf/progs/verifier_zext.c  |  9 +++++++++
 8 files changed, 80 insertions(+)

diff --git a/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c b/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
index b5a01cbc33a7..97912a7b6b5e 100644
--- a/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
+++ b/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
@@ -112,6 +112,15 @@ int arena_arg_jit_args5(void *ctx)
 				   (u64 *)&val[4]);
 	return 0;
 }
+#else
+
+SEC("socket")
+__skip_without_arena
+__success
+int arena_unsupported(void)
+{
+	return 0;
+}
 
 #endif /* __BPF_FEATURE_ADDR_SPACE_CAST */
 
diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index 1b264480e128..ed1ed1b5bd09 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -116,6 +116,10 @@
  *                   feature the toolchain or JIT cannot provide, so a run does
  *                   not report OK for coverage it never executed.
  *
+ * __skip_without_arena
+ *                   __skip() with a fixed reason when the compiler cannot do
+ *                   the arena address space, nothing otherwise.
+ *
  * __log_level       Log level to use for the program, numeric value expected.
  *
  * __flag            Adds one flag use for the program, the following values are valid:
@@ -156,6 +160,16 @@
 #define __success		__test_tag("test_expect_success")
 #define __description(desc)	__test_tag("test_description=" desc)
 #define __skip(reason)		__test_tag("test_skip=" reason)
+
+/*
+ * Without compiler arena support, report the test as SKIP rather than let it
+ * pass vacuously or fail to load.
+ */
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
+#define __skip_without_arena
+#else
+#define __skip_without_arena	__skip("compiler does not support the arena address space")
+#endif
 #define __msg_unpriv(msg)	__test_tag("test_expect_msg_unpriv=" msg)
 #define __not_msg_unpriv(msg)	__test_tag("test_expect_not_msg_unpriv=" msg)
 #define __msg_next_unpriv(msg)	__test_tag("test_expect_msg_next_unpriv=" msg)
diff --git a/tools/testing/selftests/bpf/progs/compute_live_registers.c b/tools/testing/selftests/bpf/progs/compute_live_registers.c
index 1ff24bbc7beb..e05431600358 100644
--- a/tools/testing/selftests/bpf/progs/compute_live_registers.c
+++ b/tools/testing/selftests/bpf/progs/compute_live_registers.c
@@ -403,6 +403,16 @@ __naked void addr_space_cast(void)
 		  __imm_addr(arena)
 		: __clobber_all);
 }
+#else
+
+SEC("socket")
+__skip_without_arena
+__success
+int arena_unsupported(void)
+{
+	return 0;
+}
+
 #endif
 
 static __used __naked int aux1(void)
diff --git a/tools/testing/selftests/bpf/progs/jit_insns_arena.c b/tools/testing/selftests/bpf/progs/jit_insns_arena.c
index 95736eae2a58..ccda60e96524 100644
--- a/tools/testing/selftests/bpf/progs/jit_insns_arena.c
+++ b/tools/testing/selftests/bpf/progs/jit_insns_arena.c
@@ -106,6 +106,16 @@ int cast_to_user(void *ctx)
 	: "r1", "r2", "r7", "r9");
 	return res != 0;
 }
+#else
+
+SEC("socket")
+__skip_without_arena
+__success
+int arena_unsupported(void)
+{
+	return 0;
+}
+
 #endif
 
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena.c b/tools/testing/selftests/bpf/progs/verifier_arena.c
index b17a6dfc100d..121f8cea8c25 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena.c
@@ -728,6 +728,15 @@ __naked void mixed_arena_stack_atomic(void)
 	  __imm(bpf_get_prandom_u32)
 	: __clobber_all);
 }
+#else
+
+SEC("socket")
+__skip_without_arena
+__success
+int arena_unsupported(void)
+{
+	return 0;
+}
 
 #endif /* defined(__BPF_FEATURE_ADDR_SPACE_CAST) */
 
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena_large.c b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
index dbdea14ca76f..34f0a0f88e12 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena_large.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
@@ -348,5 +348,15 @@ int big_alloc4(void *ctx)
 #endif
 	return 0;
 }
+#else
+
+SEC("socket")
+__skip_without_arena
+__success
+int arena_unsupported(void)
+{
+	return 0;
+}
+
 #endif
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_ldsx.c b/tools/testing/selftests/bpf/progs/verifier_ldsx.c
index 49e8cd4bb4f9..35b20d0796db 100644
--- a/tools/testing/selftests/bpf/progs/verifier_ldsx.c
+++ b/tools/testing/selftests/bpf/progs/verifier_ldsx.c
@@ -450,6 +450,15 @@ void kfunc_root(void)
 {
 	bpf_arena_alloc_pages(0, 0, 0, 0, 0);
 }
+#else
+
+SEC("socket")
+__skip_without_arena
+__success
+int arena_unsupported(void)
+{
+	return 0;
+}
 
 #endif /* __BPF_FEATURE_ADDR_SPACE_CAST */
 
diff --git a/tools/testing/selftests/bpf/progs/verifier_zext.c b/tools/testing/selftests/bpf/progs/verifier_zext.c
index 572017fe28fb..dbfeeea4cf9f 100644
--- a/tools/testing/selftests/bpf/progs/verifier_zext.c
+++ b/tools/testing/selftests/bpf/progs/verifier_zext.c
@@ -381,6 +381,15 @@ __naked void zext_arena_cmpxchg32(void)
 		     BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_1, BPF_REG_2, 0))
 	: __clobber_all);
 }
+#else
+
+SEC("socket")
+__skip_without_arena
+__success
+int arena_unsupported(void)
+{
+	return 0;
+}
 
 #endif
 
-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next v3 4/8] selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds
  2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
                   ` (2 preceding siblings ...)
  2026-11-02 22:07 ` [PATCH bpf-next v3 3/8] selftests/bpf: report SKIP for arena tests a compiler cannot build Vineet Gupta
@ 2026-11-02 22:07 ` Vineet Gupta
  2026-11-02 22:38   ` Alexei Starovoitov
  2026-11-02 22:07 ` [PATCH bpf-next v3 5/8] selftests/bpf: don't report arena tests as passing with an empty body Vineet Gupta
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

arena_base() casts the map definition to the kernel's struct bpf_arena
and reads user_vm_start out of it.  In the object file that definition
is only the 32-byte BTF placeholder the loader rewrites, so the access
is past the end of the object and GCC says so:

  libarena/include/bpf_arena_common.h:52:69: error: array subscript 'struct bpf_arena[0]' is partly outside array bounds of 'struct <anonymous>[1]' [-Werror=array-bounds=]
     52 | #define arena_base(map) ((void __arena *)((struct bpf_arena *)(map))->user_vm_start)
  progs/arena_race.c:58:30: note: in expansion of macro 'arena_base'

GCC is right; clang has the same warning but does not apply it to a
member access through a cast.  With BPF_CFLAGS carrying -Werror this is
a build failure, today, for every prog that calls arena_base() and is
compiled by a GCC with arena support: verifier_arena.c,
verifier_arena_large.c, verifier_arena_globals1.c,
verifier_arena_globals2.c and arena_race.c.

Make the pointer opaque instead, which is what progs/stream.c already
does for its own open-coded copy of the same access.  The bounds
analysis then has nothing to reason about, and every caller is covered
without a per-file opt-out that has to be maintained -- arena_race.c
was added without one and broke the bpf_gcc build.

The barrier is behind #ifdef __clang__ so clang keeps the plain macro.
It does not need it, and the barrier is not free: it blocks reuse of
the map address, so each call site reloads it.  Across the five progs
and 20 call sites that is +35 instructions under GCC
(2528 -> 2563), about 1.4% on those objects and nothing elsewhere.
Clang output is unchanged, bit for bit.

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 .../bpf/libarena/include/bpf_arena_common.h      | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h b/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
index 82aafe879fae..4f2c6050215f 100644
--- a/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
+++ b/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
@@ -49,7 +49,23 @@ void __arena* bpf_arena_alloc_pages(void *map, void __arena *addr, __u32 page_cn
 int bpf_arena_reserve_pages(void *map, void __arena *addr, __u32 page_cnt) __ksym __weak;
 void bpf_arena_free_pages(void *map, void __arena *ptr, __u32 page_cnt) __ksym __weak;
 
+/*
+ * GCC's -Warray-bounds fires on the member access: the map definition the
+ * object file carries is smaller than struct bpf_arena.  Make the pointer
+ * opaque to it, as the open-coded form in progs/stream.c already does.
+ * clang does not warn and does not need the barrier, which costs a reload
+ * of the map address at every call site.
+ */
+#ifdef __clang__
 #define arena_base(map) ((void __arena *)((struct bpf_arena *)(map))->user_vm_start)
+#else
+#define arena_base(map)							\
+({									\
+	struct bpf_arena *__ma = (void *)(map);				\
+	barrier_var(__ma);						\
+	(void __arena *)__ma->user_vm_start;				\
+})
+#endif
 
 #else /* when compiled as user space code */
 
-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next v3 5/8] selftests/bpf: don't report arena tests as passing with an empty body
  2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
                   ` (3 preceding siblings ...)
  2026-11-02 22:07 ` [PATCH bpf-next v3 4/8] selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds Vineet Gupta
@ 2026-11-02 22:07 ` Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 6/8] selftests/bpf: cast explicitly in the arena subprog and callback faults Vineet Gupta
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

Some arena tests put the __BPF_FEATURE_ADDR_SPACE_CAST guard inside the
function rather than around it, so without arena support the program
still exists, its body is empty, and __success __retval(0) is met by
doing nothing.  A reader sees

  #584/1	 verifier_arena/basic_alloc1_nosleep:OK

and concludes arena works.  That is worse than the tests which vanish
entirely, since nothing hints anything is missing.

The guard was never needed to compile those bodies: without the
feature __arena is still btf_type_tag("arena"), which every compiler
accepts.  What it avoided was the load failure that follows from no
addr_space_cast being emitted — but only for a body that dereferences
an arena pointer.  The arena kfuncs do not check theirs at all: the
address parameter of bpf_arena_{alloc,free,reserve}_pages() carries the
__ign suffix, get_kfunc_arg_type() returns ARG_IGNORE for it, and
check_func_arg() returns before any register type check.  So a test
that only passes pointers to those kfuncs needs no cast and runs fine.

test_loader checks skip_reason before it opens anything, so the body no
longer has to be empty to stay loadable: drop all 19 in-body guards.
They do not all need a tag in their place, which is why 19 guards go
and 7 tags arrive:

  6   dereference, so they get __skip_without_arena and report SKIP:
      basic_alloc1{,_nosleep}, basic_alloc2{,_nosleep}, big_alloc1,
      access_reserved
  11  never dereference, so they get no tag and run for real instead
      of reporting a vacuous OK
  2   big_alloc3 and big_alloc4, already inside the file's outer
      whole-program guard, so the in-body one was redundant

The 7th tag goes on check_arena_arg_ret(), which has no guard at all
and is the one verifier_arena subtest that really fails under a stock
GCC.

Measured on bpf-next with a stock bpf-gcc, for verifier_arena and
verifier_arena_large:

  verifier_arena/basic_alloc1            OK   -> SKIP
  verifier_arena/basic_alloc1_nosleep    OK   -> SKIP
  verifier_arena/basic_alloc2            OK   -> SKIP
  verifier_arena/basic_alloc2_nosleep    OK   -> SKIP
  verifier_arena_large/big_alloc1        OK   -> SKIP
  verifier_arena_large/access_reserved   OK   -> SKIP
  verifier_arena/check_arena_arg_ret     FAIL -> SKIP

the six that dereference stop claiming to pass, and check_arena_arg_ret
stops failing.  The eleven that do not dereference stay OK, having gone
from an empty body to actually running.

Removing the guards exposes the arena_base() calls they were hiding.
The previous patch made that macro opaque to GCC's -Warray-bounds, so
nothing is needed here beyond the guards going away.
arena_kfunc.c, verifier_arena_globals1.c and verifier_arena_globals2.c
have the same shape and are included here: nine more guards go, seven
more tags arrive, and seven more subtests go OK -> SKIP.  arena_kfunc.c
had six of those, the most of the three.

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 .../testing/selftests/bpf/progs/arena_kfunc.c | 18 +++--------
 .../selftests/bpf/progs/verifier_arena.c      | 31 +++----------------
 .../bpf/progs/verifier_arena_globals1.c       |  6 ++--
 .../bpf/progs/verifier_arena_globals2.c       |  3 +-
 .../bpf/progs/verifier_arena_large.c          | 16 ++--------
 5 files changed, 14 insertions(+), 60 deletions(-)

diff --git a/tools/testing/selftests/bpf/progs/arena_kfunc.c b/tools/testing/selftests/bpf/progs/arena_kfunc.c
index 5d1cb1a7e8ee..757aa0618571 100644
--- a/tools/testing/selftests/bpf/progs/arena_kfunc.c
+++ b/tools/testing/selftests/bpf/progs/arena_kfunc.c
@@ -29,9 +29,9 @@ SEC("syscall")
 __arch_x86_64
 __arch_arm64
 __success __retval(0)
+__skip_without_arena
 int arena_arg_forms(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 	u64 ret;
 
@@ -59,7 +59,6 @@ int arena_arg_forms(void *ctx)
 		return 4;
 
 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }
 
@@ -75,7 +74,6 @@ __arch_arm64
 __success __retval(0)
 int arena_arg_rebase(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 	u64 base, off;
 
@@ -107,7 +105,6 @@ int arena_arg_rebase(void *ctx)
 		return 7;
 
 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }
 
@@ -115,9 +112,9 @@ SEC("syscall")
 __arch_x86_64
 __arch_arm64
 __success __retval(0)
+__skip_without_arena
 int arena_args5(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 
 	val = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
@@ -139,7 +136,6 @@ int arena_args5(void *ctx)
 		return 3;
 
 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }
 
@@ -147,9 +143,9 @@ SEC("syscall")
 __arch_x86_64
 __arch_arm64
 __success __retval(0)
+__skip_without_arena
 int arena_arg_mixed(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 
 	val = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
@@ -166,7 +162,6 @@ int arena_arg_mixed(void *ctx)
 		return 3;
 
 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }
 
@@ -177,7 +172,6 @@ __arch_arm64
 __success __retval(0)
 int arena_arg_unpopulated(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 
 	val = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
@@ -188,7 +182,6 @@ int arena_arg_unpopulated(void *ctx)
 	bpf_kfunc_arena_arg_test((u64 *)stash);
 
 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }
 
@@ -220,9 +213,9 @@ SEC("syscall")
 __arch_x86_64
 __arch_arm64
 __success __retval(0)
+__skip_without_arena
 int arena_arg_subprog(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 	int ret;
 
@@ -238,9 +231,6 @@ int arena_arg_subprog(void *ctx)
 
 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
 	return ret;
-#else
-	return 0;
-#endif
 }
 
 SEC("syscall")
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena.c b/tools/testing/selftests/bpf/progs/verifier_arena.c
index 121f8cea8c25..27ffd74567ec 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena.c
@@ -27,9 +27,9 @@ struct {
 
 SEC("socket")
 __success __retval(0)
+__skip_without_arena
 int basic_alloc1_nosleep(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	volatile int __arena *page1, *page2, *no_page;
 
 	page1 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
@@ -52,15 +52,14 @@ int basic_alloc1_nosleep(void *ctx)
 		return 6;
 	if (*page2 != 0 && *page2 != 2) /* use-after-free should return 0 or the stored value */
 		return 7;
-#endif
 	return 0;
 }
 
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int basic_alloc1(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	volatile int __arena *page1, *page2, *no_page, *page3;
 
 	page1 = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
@@ -91,7 +90,6 @@ int basic_alloc1(void *ctx)
 		return 9;
 	if (*page1 != 1)
 		return 10;
-#endif
 	return 0;
 }
 
@@ -125,9 +123,9 @@ int free_scalar_below_arena(void *ctx)
 
 SEC("socket")
 __success __retval(0)
+__skip_without_arena
 int basic_alloc2_nosleep(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	volatile char __arena *page1, *page2, *page3, *page4;
 
 	page1 = bpf_arena_alloc_pages(&arena, NULL, 2, NUMA_NO_NODE, 0);
@@ -157,15 +155,14 @@ int basic_alloc2_nosleep(void *ctx)
 		return 7;
 	if (*page4 != 0)
 		return 8;
-#endif
 	return 0;
 }
 
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int basic_alloc2(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	volatile char __arena *page1, *page2, *page3, *page4;
 
 	page1 = bpf_arena_alloc_pages(&arena, NULL, 2, NUMA_NO_NODE, 0);
@@ -195,7 +192,6 @@ int basic_alloc2(void *ctx)
 		return 7;
 	if (*page4 != 0)
 		return 8;
-#endif
 	return 0;
 }
 
@@ -233,7 +229,6 @@ SEC("socket")
 __success __retval(0)
 int basic_reserve1_nosleep(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -257,7 +252,6 @@ int basic_reserve1_nosleep(void *ctx)
 	page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
 	if (page)
 		return 4;
-#endif
 	return 0;
 }
 
@@ -265,7 +259,6 @@ SEC("syscall")
 __success __retval(0)
 int basic_reserve1(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -289,7 +282,6 @@ int basic_reserve1(void *ctx)
 	page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
 	if (page)
 		return 4;
-#endif
 	return 0;
 }
 
@@ -297,7 +289,6 @@ SEC("socket")
 __success __retval(0)
 int basic_reserve2_nosleep(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -309,7 +300,6 @@ int basic_reserve2_nosleep(void *ctx)
 	page = bpf_arena_alloc_pages(&arena, page, 1, NUMA_NO_NODE, 0);
 	if ((u64)page)
 		return 2;
-#endif
 	return 0;
 }
 
@@ -317,7 +307,6 @@ SEC("syscall")
 __success __retval(0)
 int basic_reserve2(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -329,7 +318,6 @@ int basic_reserve2(void *ctx)
 	page = bpf_arena_alloc_pages(&arena, page, 1, NUMA_NO_NODE, 0);
 	if ((u64)page)
 		return 2;
-#endif
 	return 0;
 }
 
@@ -338,7 +326,6 @@ SEC("socket")
 __success __retval(0)
 int reserve_twice_nosleep(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -351,7 +338,6 @@ int reserve_twice_nosleep(void *ctx)
 	ret = bpf_arena_reserve_pages(&arena, page, 1);
 	if (ret != -EBUSY)
 		return 2;
-#endif
 	return 0;
 }
 
@@ -359,7 +345,6 @@ SEC("syscall")
 __success __retval(0)
 int reserve_twice(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -372,7 +357,6 @@ int reserve_twice(void *ctx)
 	ret = bpf_arena_reserve_pages(&arena, page, 1);
 	if (ret != -EBUSY)
 		return 2;
-#endif
 	return 0;
 }
 
@@ -381,7 +365,6 @@ SEC("socket")
 __success __retval(0)
 int reserve_invalid_region_nosleep(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -403,7 +386,6 @@ int reserve_invalid_region_nosleep(void *ctx)
 	ret = bpf_arena_reserve_pages(&arena, page, (1ULL << 32) - 1);
 	if (ret != -EINVAL)
 		return 4;
-#endif
 	return 0;
 }
 
@@ -411,7 +393,6 @@ SEC("syscall")
 __success __retval(0)
 int reserve_invalid_region(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -433,7 +414,6 @@ int reserve_invalid_region(void *ctx)
 	ret = bpf_arena_reserve_pages(&arena, page, (1ULL << 32) - 1);
 	if (ret != -EINVAL)
 		return 4;
-#endif
 	return 0;
 }
 
@@ -478,7 +458,6 @@ SEC("syscall")
 __success __retval(0)
 int arena_kfuncs_under_bpf_lock(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *page;
 	int ret;
 
@@ -503,7 +482,6 @@ int arena_kfuncs_under_bpf_lock(void *ctx)
 	bpf_arena_free_pages(&arena, page, 1);
 
 	bpf_spin_unlock(&arena_bpf_test_lock);
-#endif
 
 	return 0;
 }
@@ -780,6 +758,7 @@ u32 __arena volatile *check_arena_arg_quals2(u32 volatile __arena *arg1, u32 __a
 
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int check_arena_arg_ret(void *ctx)
 {
 	u32 __arena *page = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena_globals1.c b/tools/testing/selftests/bpf/progs/verifier_arena_globals1.c
index 45d364b0bc85..31be4c944252 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena_globals1.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena_globals1.c
@@ -30,9 +30,9 @@ volatile char __arena global_data[GLOBAL_PAGES][PAGE_SIZE];
 
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int check_reserve1(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	const u8 magic = 0x5a;
 	__u8 __arena *guard, *globals;
 	volatile char __arena *ptr;
@@ -60,7 +60,6 @@ int check_reserve1(void *ctx)
 		if (*ptr != magic)
 			return i + 3;
 	}
-#endif
 	return 0;
 }
 
@@ -69,9 +68,9 @@ int check_reserve1(void *ctx)
  */
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int check_relocation(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	const u8 magic = 0xfa;
 	u8 __arena *ptr;
 
@@ -80,7 +79,6 @@ int check_relocation(void *ctx)
 	if (*ptr != magic)
 		return 1;
 
-#endif
 	return 0;
 }
 
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena_globals2.c b/tools/testing/selftests/bpf/progs/verifier_arena_globals2.c
index b51594dbc005..cd48d6bd782e 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena_globals2.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena_globals2.c
@@ -30,9 +30,9 @@ char __arena global_data[ARENA_PAGES][PAGE_SIZE];
 
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int check_reserve2(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	void __arena *guard;
 	int ret;
 
@@ -42,7 +42,6 @@ int check_reserve2(void *ctx)
 	ret = bpf_arena_reserve_pages(&arena, guard, 1);
 	if (!ret)
 		return 1;
-#endif
 	return 0;
 }
 
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena_large.c b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
index 34f0a0f88e12..6ef99793cac1 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena_large.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
@@ -22,9 +22,9 @@ struct {
 
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int big_alloc1(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	volatile char __arena *page1, *page2, *no_page, *page3;
 	u64 base;
 
@@ -79,16 +79,15 @@ int big_alloc1(void *ctx)
 		return 13;
 	if (*(page2 - PAGE_SIZE) != 0)
 		return 14;
-#endif
 	return 0;
 }
 
 /* Try to access a reserved page. Behavior should be identical with accessing unallocated pages. */
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int access_reserved(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	volatile char __arena *page;
 	char __arena *base;
 	const size_t len = 4;
@@ -118,7 +117,6 @@ int access_reserved(void *ctx)
 		if (*page)
 			return 2 + 2 * i + 1;
 	}
-#endif
 	return 0;
 }
 
@@ -127,7 +125,6 @@ SEC("syscall")
 __success __retval(0)
 int request_partially_reserved(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	volatile char __arena *page;
 	char __arena *base;
 	int ret;
@@ -142,7 +139,6 @@ int request_partially_reserved(void *ctx)
 	page = bpf_arena_alloc_pages(&arena, base, 5, NUMA_NO_NODE, 0);
 	if ((u64)page != 0ULL)
 		return 2;
-#endif
 	return 0;
 }
 
@@ -150,7 +146,6 @@ SEC("syscall")
 __success __retval(0)
 int free_reserved(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *addr;
 	char __arena *page;
 	int ret;
@@ -177,7 +172,6 @@ int free_reserved(void *ctx)
 	page = bpf_arena_alloc_pages(&arena, addr + __PAGE_SIZE, 2, NUMA_NO_NODE, 0);
 	if (!page)
 		return 3;
-#endif
 	return 0;
 }
 
@@ -292,7 +286,6 @@ SEC("socket")
 __success __retval(0)
 int big_alloc3(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *pages;
 	u64 i;
 	int err = 0;
@@ -314,8 +307,6 @@ int big_alloc3(void *ctx)
 
 	bpf_arena_free_pages(&arena, pages, LARGE_PAGE_CNT);
 	return err;
-#endif
-	return 0;
 }
 
 /* SYSCALL programs are always sleepable. */
@@ -323,7 +314,6 @@ SEC("syscall")
 __success __retval(0)
 int big_alloc4(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *pages;
 	u64 i;
 	int err = 0;
@@ -345,8 +335,6 @@ int big_alloc4(void *ctx)
 
 	bpf_arena_free_pages(&arena, pages, LARGE_PAGE_CNT);
 	return err;
-#endif
-	return 0;
 }
 #else
 
-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next v3 6/8] selftests/bpf: cast explicitly in the arena subprog and callback faults
  2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
                   ` (4 preceding siblings ...)
  2026-11-02 22:07 ` [PATCH bpf-next v3 5/8] selftests/bpf: don't report arena tests as passing with an empty body Vineet Gupta
@ 2026-11-02 22:07 ` Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 7/8] selftests/bpf: write the mixed arena/scalar ALU tests in asm Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 8/8] selftests/bpf: skip the struct_ops arena tests without compiler support Vineet Gupta
  7 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

Four stream tests fail with BPF_GCC:

  test_stream_arena_fault_address:FAIL:stream__open_and_load unexpected error: -13
  #479 stream_oversize:FAIL
  #480 stream_partial_read:FAIL
  #482 stream_syscall:FAIL

They call stream__open_and_load(), which loads every program in the object,
and two of those do not verify:

  #481/11 stream_success/stream_arena_subprog_fault:FAIL
  #481/12 stream_success/stream_arena_callback_fault:FAIL

Both dereference an arena pointer and leave the cast to the compiler:

  int __arena *addr = (int __arena *)0xdeadbeef;
  *addr = 1;

Without arena support __arena is only btf_type_tag("arena"), so no
addr_space_cast is emitted and the store is to a scalar, which the
verifier rejects.  GCC splits it into byte stores, 0xdeadbeef not
being aligned:

  r2=3735928559 ll
  *(u8*)(r2+0)=1            <- plain store, no cast

Their siblings in the same file do not rely on the compiler; they use
bpf_addr_space_cast(), which emits the instruction byte by byte and
works anywhere.  Do the same here.

The address space has to come off the local as well.  Left on, a
compiler that supports arenas casts a second time for the
dereference, on a pointer the explicit cast has already converted:

  r2 = addr_space_cast(r2, 0, 1)
  r3 = addr_space_cast(r2, 0, 1)
  *(u32*)(r3+0)=1

With it off, GCC with and without arena support and clang all emit the
same thing, which is what the test wants:

  r2 = addr_space_cast(r2, 0, 1)
  *(u32*)(r2+0)=1

What these two assert is the fault report, not how the pointer was
produced, so nothing they were testing is lost.

Measured on bpf-next with a stock bpf-gcc, test_progs before and after.
Fifteen results go FAIL -> OK -- every test that loads this object, not
just the arena ones:

  stream_arena_fault_address             stream_oversize
  stream_fd        stream_fd/blocking    stream_partial_read
  stream_fd/edge   stream_fd/empty       stream_success
  stream_fd/hup    stream_fd/nmi_epoll   stream_success/stream_arena_callback_fault
  stream_fd/open   stream_fd/nonblock    stream_success/stream_arena_subprog_fault
                                         stream_syscall

and the five stream_arena_fault_address subtests become visible for the
first time (read, write, xchg, cmpxchg and load_acquire faults).

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 tools/testing/selftests/bpf/progs/stream.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/tools/testing/selftests/bpf/progs/stream.c b/tools/testing/selftests/bpf/progs/stream.c
index 1ae015c4e6b4..dc56779cac06 100644
--- a/tools/testing/selftests/bpf/progs/stream.c
+++ b/tools/testing/selftests/bpf/progs/stream.c
@@ -5,7 +5,6 @@
 #include <bpf/bpf_helpers.h>
 #include "bpf_misc.h"
 #include "bpf_experimental.h"
-#include <bpf_arena_common.h>
 
 struct arr_elem {
 	struct bpf_res_spin_lock lock;
@@ -381,9 +380,10 @@ int stream_arena_cmpxchg_fault(void *ctx)
 
 static __noinline void subprog(void)
 {
-	int __arena *addr = (int __arena *)0xdeadbeef;
+	int *addr = (int *)0xdeadbeef;
 
 	arena_ptr = &arena;
+	bpf_addr_space_cast(addr, 0, 1);
 	*addr = 1;
 }
 
@@ -404,9 +404,10 @@ int stream_arena_subprog_fault(void *ctx)
 
 static __noinline int timer_cb(void *map, int *key, struct bpf_timer *timer)
 {
-	int __arena *addr = (int __arena *)0xdeadbeef;
+	int *addr = (int *)0xdeadbeef;
 
 	arena_ptr = &arena;
+	bpf_addr_space_cast(addr, 0, 1);
 	*addr = 1;
 	return 0;
 }
-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next v3 7/8] selftests/bpf: write the mixed arena/scalar ALU tests in asm
  2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
                   ` (5 preceding siblings ...)
  2026-11-02 22:07 ` [PATCH bpf-next v3 6/8] selftests/bpf: cast explicitly in the arena subprog and callback faults Vineet Gupta
@ 2026-11-02 22:07 ` Vineet Gupta
  2026-11-02 22:07 ` [PATCH bpf-next v3 8/8] selftests/bpf: skip the struct_ops arena tests without compiler support Vineet Gupta
  7 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

They fail to build with BPF_GCC:

  progs/verifier_arena.c:566:5: error: optimization may eliminate reads and/or writes to register variables [-Werror=volatile-register-var]

for

  volatile register __u64 reg asm("r3");

and GCC means it.  With the warning silenced it drops both scalar
accesses, leaving nothing that uses r3 as a scalar:

  call	7
  if w0 == 0 goto .L136
  r9 = arena ll;r3 = 0;r3 = addr_space_cast(r3, 0, 1);
  .L136:
  r0 = 0
  exit

`reg = 1ULL << 32' and `reg += 1' are both gone.  The tests need one
instruction reached with r3 live as a scalar on one path and as an
arena pointer on the other; what is left gives the verifier no reason
to reject anything, so the __failure expectation would not hold.  A
local register variable is not guaranteed to survive a helper call
either, which GCC is also entitled to act on.

Nothing here needs a compiler to allocate registers, so write the
whole body in asm like mixed_arena_stack_atomic below, which tests the
same shape.  Both compilers then emit the same sequence, with the
branch landing on the shared ALU op:

  call 7
  r6=r0
  r3=1
  r3<<=32
  if w6==0 goto 4          <- lands on r3+=1
  r9=0 ll
  r3=0
  r3 = addr_space_cast(r3, 0, 1)
  r3+=1                    <- scalar on one path, arena pointer on the other
  r0=0
  exit

Take __load_if_JITed() from the sibling while here.  A program binding
an arena map is rejected in check_map_prog_compatibility() with "JIT is
required to use arena" during map resolution, before do_check() can
reach the shared instruction, so without a JIT these would fail on the
wrong message rather than skip.

Not exercised by a stock bpf-gcc, which compiles both tests out with the
rest of the arena block; the build failure above needs a compiler that
has arena support.  Under clang the rewrite is not a no-op either: the
pre-image spilled r3 to the stack and did the shared ALU op on r1
reloaded from it, so the test was not exercising one register live as
both a scalar and an arena pointer.

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 .../selftests/bpf/progs/verifier_arena.c      | 91 +++++++++++--------
 1 file changed, 51 insertions(+), 40 deletions(-)

diff --git a/tools/testing/selftests/bpf/progs/verifier_arena.c b/tools/testing/selftests/bpf/progs/verifier_arena.c
index 27ffd74567ec..3b13f6aa6b62 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena.c
@@ -539,53 +539,64 @@ int arena_ptr_add_arena_ptr(void *ctx)
 	return 0;
 }
 
+/*
+ * Tests that one insn cannot be reached with a register holding a scalar
+ * on one path and an arena pointer on the other.
+ */
 SEC("syscall")
 __failure __msg("same insn cannot be used with and without arena pointer")
-int mixed_arena_scalar_alu64_scalar_first(void *ctx)
-{
-	volatile register __u64 reg asm("r3");
-	__u32 pick_arena = bpf_get_prandom_u32();
-
-	reg = 1ULL << 32;
-
-	if (pick_arena) {
-		asm volatile (
-			"r9 = %[arena] ll;"
-			"%[reg] = 0;"
-			"%[reg] = addr_space_cast(%[reg], 0x0, 0x1);"
-			: [reg] "=r"(reg)
-			: __imm_addr(arena)
-			: "r9"
-		);
-	}
-
-	reg += 1;
-
-	return 0;
+__load_if_JITed()
+__naked void mixed_arena_scalar_alu64_scalar_first(void)
+{
+	/*
+	 * The r9 load is never read.  libbpf binds the object's arena to
+	 * every program through fd_array, so the verifier knows about it
+	 * without this; the load is the fallback for a kernel without
+	 * fd_array_cnt and for the light skeleton loader.
+	 */
+	asm volatile ("					\
+	call %[bpf_get_prandom_u32];			\
+	r6 = r0;					\
+	r3 = 1;						\
+	r3 <<= 32;					\
+	if w6 == 0 goto 1f;				\
+	r9 = %[arena] ll;				\
+	r3 = 0;						\
+	r3 = addr_space_cast(r3, 0, 1);			\
+1:	r3 += 1;					\
+	r0 = 0;						\
+	exit;						\
+"	:
+	: __imm_addr(arena),
+	  __imm(bpf_get_prandom_u32)
+	: __clobber_all);
 }
 
+/*
+ * As mixed_arena_scalar_alu64_scalar_first(), including the r9 load, with
+ * the arena pointer established first.
+ */
 SEC("syscall")
 __failure __msg("same insn cannot be used with and without arena pointer")
-int mixed_arena_scalar_alu64_arena_first(void *ctx)
+__load_if_JITed()
+__naked void mixed_arena_scalar_alu64_arena_first(void)
 {
-	volatile register __u64 reg asm("r3");
-	__u32 pick_scalar = bpf_get_prandom_u32();
-
-	asm volatile (
-		"r9 = %[arena] ll;"
-		"%[reg] = 0;"
-		"%[reg] = addr_space_cast(%[reg], 0x0, 0x1);"
-		: [reg] "=r"(reg)
-		: __imm_addr(arena)
-		: "r9"
-	);
-
-	if (pick_scalar)
-		reg = 1ULL << 32;
-
-	reg += 1;
-
-	return 0;
+	asm volatile ("					\
+	call %[bpf_get_prandom_u32];			\
+	r6 = r0;					\
+	r9 = %[arena] ll;				\
+	r3 = 0;						\
+	r3 = addr_space_cast(r3, 0, 1);			\
+	if w6 == 0 goto 1f;				\
+	r3 = 1;						\
+	r3 <<= 32;					\
+1:	r3 += 1;					\
+	r0 = 0;						\
+	exit;						\
+"	:
+	: __imm_addr(arena),
+	  __imm(bpf_get_prandom_u32)
+	: __clobber_all);
 }
 
 SEC("syscall")
-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH bpf-next v3 8/8] selftests/bpf: skip the struct_ops arena tests without compiler support
  2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
                   ` (6 preceding siblings ...)
  2026-11-02 22:07 ` [PATCH bpf-next v3 7/8] selftests/bpf: write the mixed arena/scalar ALU tests in asm Vineet Gupta
@ 2026-11-02 22:07 ` Vineet Gupta
  2026-11-02 22:39   ` Alexei Starovoitov
  7 siblings, 1 reply; 15+ messages in thread
From: Vineet Gupta @ 2026-11-02 22:07 UTC (permalink / raw)
  To: bpf
  Cc: ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
	yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend, shuah,
	linux-kernel, linux-kselftest, jose.marchesi, david.faust,
	Vineet Gupta

trigger() in struct_ops_arena.c and its three siblings puts the
__BPF_FEATURE_ADDR_SPACE_CAST guard inside the function, so without
arena support the body is gone and the program falls through to
"return 0".  The host side then does

  err = bpf_prog_test_run_opts(bpf_program__fd(trigger), &topts);
  ASSERT_OK(err, "test_run");
  ASSERT_EQ(topts.retval, 0, "trigger_retval");

and passes, having run a program that did nothing.  Two tests report OK
under a stock bpf-gcc on that basis: arena_arg and arena_autobind.  The
other two, arena_member and arena_member_render, need a testmod BTF
carrying the arena type tag and are not reached without one, but are
fixed the same way.

These are not driven by test_loader, so __skip_without_arena does not
reach them.  Use the flag-in-.data pattern linked_externs.c already
uses for the same situation: the program exports skip_tests, and the
host checks it before attaching and reports SKIP.

Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
---
 .../bpf/prog_tests/test_struct_ops_arena.c    | 27 +++++++++++++++++++
 .../selftests/bpf/progs/struct_ops_arena.c    | 10 +++++++
 .../bpf/progs/struct_ops_arena_autobind.c     | 10 +++++++
 .../bpf/progs/struct_ops_arena_member.c       | 10 +++++++
 .../progs/struct_ops_arena_member_render.c    | 10 +++++++
 5 files changed, 67 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/test_struct_ops_arena.c b/tools/testing/selftests/bpf/prog_tests/test_struct_ops_arena.c
index e7580b9f0fc2..11b7dab77ff7 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_struct_ops_arena.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_struct_ops_arena.c
@@ -31,6 +31,12 @@ static void arena_arg(void)
 	if (!ASSERT_OK_PTR(skel, "struct_ops_arena__open_and_load"))
 		return;
 
+	if (skel->data->skip_tests) {
+		printf("%s:SKIP: no addr_space_cast support in the BPF compiler\n", __func__);
+		test__skip();
+		goto out;
+	}
+
 	link = bpf_map__attach_struct_ops(skel->maps.testmod_arena);
 	if (!ASSERT_OK_PTR(link, "attach_struct_ops"))
 		goto out;
@@ -142,6 +148,13 @@ static void arena_member(void)
 	if (!ASSERT_OK_PTR(skel, "struct_ops_arena_member__open_and_load"))
 		return;
 
+	if (skel->data->skip_tests) {
+		printf("%s:SKIP: no addr_space_cast support in the BPF compiler\n", __func__);
+		test__skip();
+		struct_ops_arena_member__destroy(skel);
+		return;
+	}
+
 	attach_and_trigger(skel->maps.testmod_arena_member, skel->progs.trigger);
 	struct_ops_arena_member__destroy(skel);
 }
@@ -186,6 +199,13 @@ static void arena_autobind(void)
 	assert_prog_map(bpf_program__fd(skel->progs.test_arena_cb), info.id, "test_arena_cb");
 	assert_prog_map(bpf_program__fd(skel->progs.unrelated), info.id, "unrelated");
 
+	if (skel->data->skip_tests) {
+		printf("%s:SKIP: no addr_space_cast support in the BPF compiler\n", __func__);
+		test__skip();
+		struct_ops_arena_autobind__destroy(skel);
+		return;
+	}
+
 	attach_and_trigger(skel->maps.testmod_arena_autobind, skel->progs.trigger);
 out:
 	struct_ops_arena_autobind__destroy(skel);
@@ -268,6 +288,13 @@ static void arena_member_render(void)
 	if (!ASSERT_OK_PTR(skel, "struct_ops_arena_member_render__open_and_load"))
 		return;
 
+	if (skel->data->skip_tests) {
+		printf("%s:SKIP: no addr_space_cast support in the BPF compiler\n", __func__);
+		test__skip();
+		struct_ops_arena_member_render__destroy(skel);
+		return;
+	}
+
 	attach_and_trigger(skel->maps.testmod_arena_member_render, skel->progs.trigger);
 	struct_ops_arena_member_render__destroy(skel);
 }
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena.c b/tools/testing/selftests/bpf/progs/struct_ops_arena.c
index 8aa8639df91f..612ca868c8fe 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_arena.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_arena.c
@@ -83,6 +83,16 @@ struct bpf_testmod_ops3 testmod_arena = {
 	.test_arena_multislot = (void *)test_arena_multislot_cb,
 };
 
+/*
+ * These tests are not driven by test_loader, so __skip_without_arena
+ * cannot reach them; the host side reads this flag and skips instead.
+ */
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
+bool skip_tests __attribute((__section__(".data"))) = false;
+#else
+bool skip_tests = true;
+#endif
+
 SEC("syscall")
 int trigger(void *ctx)
 {
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
index 495faa0f4a8b..de026d901dcb 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
@@ -42,6 +42,16 @@ int unrelated(void *ctx)
 	return 0;
 }
 
+/*
+ * These tests are not driven by test_loader, so __skip_without_arena
+ * cannot reach them; the host side reads this flag and skips instead.
+ */
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
+bool skip_tests __attribute((__section__(".data"))) = false;
+#else
+bool skip_tests = true;
+#endif
+
 SEC("syscall")
 int trigger(void *ctx)
 {
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
index a2218cd81619..4ec0aead3e95 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
@@ -77,6 +77,16 @@ struct bpf_testmod_ops3 testmod_arena_member = {
 	.test_arena_member = (void *)test_arena_member_cb,
 };
 
+/*
+ * These tests are not driven by test_loader, so __skip_without_arena
+ * cannot reach them; the host side reads this flag and skips instead.
+ */
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
+bool skip_tests __attribute((__section__(".data"))) = false;
+#else
+bool skip_tests = true;
+#endif
+
 SEC("syscall")
 int trigger(void *ctx)
 {
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
index 09b4c740bdca..3ccbc6e71626 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
@@ -60,6 +60,16 @@ struct bpf_testmod_ops3 testmod_arena_member_render = {
 	.test_arena_member = (void *)test_arena_member_render_cb,
 };
 
+/*
+ * These tests are not driven by test_loader, so __skip_without_arena
+ * cannot reach them; the host side reads this flag and skips instead.
+ */
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
+bool skip_tests __attribute((__section__(".data"))) = false;
+#else
+bool skip_tests = true;
+#endif
+
 SEC("syscall")
 int trigger(void *ctx)
 {
-- 
2.53.0-Meta


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next v3 3/8] selftests/bpf: report SKIP for arena tests a compiler cannot build
  2026-11-02 22:07 ` [PATCH bpf-next v3 3/8] selftests/bpf: report SKIP for arena tests a compiler cannot build Vineet Gupta
@ 2026-11-02 22:36   ` Alexei Starovoitov
  2026-11-03  0:24     ` Vineet Gupta
  0 siblings, 1 reply; 15+ messages in thread
From: Alexei Starovoitov @ 2026-11-02 22:36 UTC (permalink / raw)
  To: Vineet Gupta, bpf
  Cc: daniel, andrii, eddyz87, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, john.fastabend, shuah, linux-kernel,
	linux-kselftest, jose.marchesi, david.faust

On Mon, Nov 02, 2026 at 02:07 PM Vineet Gupta <vineet.gupta@linux.dev> wrote:
> Give each guard an #else with a dummy marked __skip(), so the skip gap is
> reported rather than invisible.  Add __skip_without_arena for it, which
> expands to __skip() with a fixed reason when the compiler cannot do arena.

How about the following approach instead...
looks much simpler to me...

pw-bot: cr

diff --git a/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c b/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
index b5a01cb..16c3dd9 100644
--- a/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
+++ b/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
@@ -23,8 +23,6 @@ struct {
 /* volatile to force the scalar reloads below */
 volatile u64 stash;

-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
-
 SEC("syscall")
 __arch_x86_64
 __jited("...")
@@ -93,6 +91,7 @@ __jited("	cbz	w4, L0")
 __jited("	add	x4, x28, w4, uxtw")
 __jited("L0:	{{.*}}")
 __success
+__skip_without_arena
 int arena_arg_jit_args5(void *ctx)
 {
 	u64 __arena *val;
@@ -113,6 +112,4 @@ int arena_arg_jit_args5(void *ctx)
 	return 0;
 }

-#endif /* __BPF_FEATURE_ADDR_SPACE_CAST */
-
 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index d7f706c..4ec840b 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -116,6 +116,10 @@
  *                   feature the toolchain or JIT cannot provide, so a run does
  *                   not report OK for coverage it never executed.
  *
+ * __skip_without_arena
+ *                   __skip() when the compiler does not support the arena
+ *                   address space, nothing otherwise.
+ *
  * __log_level       Log level to use for the program, numeric value expected.
  *
  * __flag            Adds one flag use for the program, the following values are valid:
@@ -156,6 +160,11 @@
 #define __success		__test_tag("test_expect_success")
 #define __description(desc)	__test_tag("test_description=" desc)
 #define __skip(reason)		__test_tag("test_skip=" reason)
+#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
+#define __skip_without_arena
+#else
+#define __skip_without_arena	__skip("compiler does not support the arena address space")
+#endif
 #define __msg_unpriv(msg)	__test_tag("test_expect_msg_unpriv=" msg)
 #define __not_msg_unpriv(msg)	__test_tag("test_expect_not_msg_unpriv=" msg)
 #define __msg_next_unpriv(msg)	__test_tag("test_expect_msg_next_unpriv=" msg)
diff --git a/tools/testing/selftests/bpf/progs/jit_insns_arena.c b/tools/testing/selftests/bpf/progs/jit_insns_arena.c
index 95736ea..77d135a 100644
--- a/tools/testing/selftests/bpf/progs/jit_insns_arena.c
+++ b/tools/testing/selftests/bpf/progs/jit_insns_arena.c
@@ -106,6 +106,14 @@ int cast_to_user(void *ctx)
 	: "r1", "r2", "r7", "r9");
 	return res != 0;
 }
+#else
+SEC("socket")
+__skip_without_arena
+__success
+int arena_unsupported(void)
+{
+	return 0;
+}
 #endif

 char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_arena_large.c b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
index dbdea14..428b984 100644
--- a/tools/testing/selftests/bpf/progs/verifier_arena_large.c
+++ b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
@@ -181,7 +181,6 @@ int free_reserved(void *ctx)
 	return 0;
 }

-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 #define PAGE_CNT 100
 __u8 __arena * __arena page[PAGE_CNT]; /* occupies the first page */
 __u8 __arena *base;
@@ -220,6 +219,7 @@ __noinline int alloc_pages(int page_cnt, int pages_atonce, bool first_pass,

 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int big_alloc2(void *ctx)
 {
 	__u8 __arena *pg;
@@ -290,9 +290,9 @@ int big_alloc2(void *ctx)
 /* Nonsleepable because it binds to a socket program. */
 SEC("socket")
 __success __retval(0)
+__skip_without_arena
 int big_alloc3(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *pages;
 	u64 i;
 	int err = 0;
@@ -314,16 +314,14 @@ int big_alloc3(void *ctx)

 	bpf_arena_free_pages(&arena, pages, LARGE_PAGE_CNT);
 	return err;
-#endif
-	return 0;
 }

 /* SYSCALL programs are always sleepable. */
 SEC("syscall")
 __success __retval(0)
+__skip_without_arena
 int big_alloc4(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	char __arena *pages;
 	u64 i;
 	int err = 0;
@@ -345,8 +343,6 @@ int big_alloc4(void *ctx)

 	bpf_arena_free_pages(&arena, pages, LARGE_PAGE_CNT);
 	return err;
-#endif
-	return 0;
 }
-#endif
+
 char _license[] SEC("license") = "GPL";

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next v3 4/8] selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds
  2026-11-02 22:07 ` [PATCH bpf-next v3 4/8] selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds Vineet Gupta
@ 2026-11-02 22:38   ` Alexei Starovoitov
  2026-11-03  0:15     ` Vineet Gupta
  0 siblings, 1 reply; 15+ messages in thread
From: Alexei Starovoitov @ 2026-11-02 22:38 UTC (permalink / raw)
  To: Vineet Gupta, bpf
  Cc: daniel, andrii, eddyz87, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, john.fastabend, shuah, linux-kernel,
	linux-kselftest, jose.marchesi, david.faust

On Mon, Nov 02, 2026 at 02:07 PM Vineet Gupta <vineet.gupta@linux.dev> wrote:
> The barrier is behind #ifdef __clang__ so clang keeps the plain macro.
> It does not need it, and the barrier is not free: it blocks reuse of
> the map address, so each call site reloads it.  Across the five progs
> and 20 call sites that is +35 instructions under GCC
> (2528 -> 2563), about 1.4% on those objects and nothing elsewhere.
> Clang output is unchanged, bit for bit.

stream.c already has barrier_var() for both compilers.

How about this one instead:

diff --git a/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h b/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
index 82aafe8..0eba529 100644
--- a/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
+++ b/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
@@ -49,7 +49,16 @@ void __arena* bpf_arena_alloc_pages(void *map, void __arena *addr, __u32 page_cn
 int bpf_arena_reserve_pages(void *map, void __arena *addr, __u32 page_cnt) __ksym __weak;
 void bpf_arena_free_pages(void *map, void __arena *ptr, __u32 page_cnt) __ksym __weak;

-#define arena_base(map) ((void __arena *)((struct bpf_arena *)(map))->user_vm_start)
+/*
+ * The map definition is smaller than struct bpf_arena.
+ * barrier_var() hides that from -Warray-bounds of GCC.
+ */
+#define arena_base(map)							\
+	({								\
+		struct bpf_arena *___arena = (void *)(map);		\
+		barrier_var(___arena);					\
+		(void __arena *)___arena->user_vm_start;		\
+	})

 #else /* when compiled as user space code */

diff --git a/tools/testing/selftests/bpf/progs/stream.c b/tools/testing/selftests/bpf/progs/stream.c
index 1ae015c..b4d88d0 100644
--- a/tools/testing/selftests/bpf/progs/stream.c
+++ b/tools/testing/selftests/bpf/progs/stream.c
@@ -178,16 +178,8 @@ __stderr("Call trace:\n"
 "|[ \t]+[^\n]+\n)*}}")
 int stream_arena_write_fault(void *ctx)
 {
-	struct bpf_arena *ptr = (void *)&arena;
-	u64 user_vm_start;
+	u64 user_vm_start = (u64)arena_base(&arena);

-	/* Prevent GCC bounds warning: casting &arena to struct bpf_arena *
-	 * triggers bounds checking since the map definition is smaller than struct
-	 * bpf_arena. barrier_var() makes the pointer opaque to GCC, preventing the
-	 * bounds analysis
-	 */
-	barrier_var(ptr);
-	user_vm_start = ptr->user_vm_start;
 	fault_addr = user_vm_start + 0x7fff;
 	bpf_addr_space_cast(user_vm_start, 0, 1);
 	asm volatile (
@@ -212,16 +204,8 @@ __stderr("Call trace:\n"
 "|[ \t]+[^\n]+\n)*}}")
 int stream_arena_read_fault(void *ctx)
 {
-	struct bpf_arena *ptr = (void *)&arena;
-	u64 user_vm_start;
+	u64 user_vm_start = (u64)arena_base(&arena);

-	/* Prevent GCC bounds warning: casting &arena to struct bpf_arena *
-	 * triggers bounds checking since the map definition is smaller than struct
-	 * bpf_arena. barrier_var() makes the pointer opaque to GCC, preventing the
-	 * bounds analysis
-	 */
-	barrier_var(ptr);
-	user_vm_start = ptr->user_vm_start;
 	fault_addr = user_vm_start + 0x7fff;
 	bpf_addr_space_cast(user_vm_start, 0, 1);
 	asm volatile (
@@ -252,17 +236,9 @@ int stream_arena_load_acquire_fault(void *ctx)
 		.off	 = 0x7fff,
 		.imm	 = 0x100,	/* BPF_LOAD_ACQ */
 	};
-	struct bpf_arena *ptr = (void *)&arena;
-	u64 user_vm_start, val;
+	u64 user_vm_start = (u64)arena_base(&arena);
+	u64 val;

-	/*
-	 * Prevent GCC bounds warning: casting &arena to struct bpf_arena *
-	 * triggers bounds checking since the map definition is smaller than
-	 * struct bpf_arena. barrier_var() makes the pointer opaque to GCC,
-	 * preventing the bounds analysis.
-	 */
-	barrier_var(ptr);
-	user_vm_start = ptr->user_vm_start;
 	fault_addr = user_vm_start + 0x7fff;
 	bpf_addr_space_cast(user_vm_start, 0, 1);
 	asm volatile (
@@ -296,17 +272,9 @@ int stream_arena_xchg_fault(void *ctx)
 		.off	 = 0x7fff,
 		.imm	 = 0xe1,	/* BPF_XCHG */
 	};
-	struct bpf_arena *ptr = (void *)&arena;
-	u64 user_vm_start, val;
+	u64 user_vm_start = (u64)arena_base(&arena);
+	u64 val;

-	/*
-	 * Prevent GCC bounds warning: casting &arena to struct bpf_arena *
-	 * triggers bounds checking since the map definition is smaller than
-	 * struct bpf_arena. barrier_var() makes the pointer opaque to GCC,
-	 * preventing the bounds analysis.
-	 */
-	barrier_var(ptr);
-	user_vm_start = ptr->user_vm_start;
 	fault_addr = user_vm_start + 0x7fff;
 	bpf_addr_space_cast(user_vm_start, 0, 1);
 	/*
@@ -346,17 +314,9 @@ int stream_arena_cmpxchg_fault(void *ctx)
 		.off	 = 0x7fff,
 		.imm	 = 0xf1,	/* BPF_CMPXCHG */
 	};
-	struct bpf_arena *ptr = (void *)&arena;
-	u64 user_vm_start, val;
+	u64 user_vm_start = (u64)arena_base(&arena);
+	u64 val;

-	/*
-	 * Prevent GCC bounds warning: casting &arena to struct bpf_arena *
-	 * triggers bounds checking since the map definition is smaller than
-	 * struct bpf_arena. barrier_var() makes the pointer opaque to GCC,
-	 * preventing the bounds analysis.
-	 */
-	barrier_var(ptr);
-	user_vm_start = ptr->user_vm_start;
 	fault_addr = user_vm_start + 0x7fff;
 	bpf_addr_space_cast(user_vm_start, 0, 1);
 	/*

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next v3 8/8] selftests/bpf: skip the struct_ops arena tests without compiler support
  2026-11-02 22:07 ` [PATCH bpf-next v3 8/8] selftests/bpf: skip the struct_ops arena tests without compiler support Vineet Gupta
@ 2026-11-02 22:39   ` Alexei Starovoitov
  2026-11-03  0:17     ` Vineet Gupta
  0 siblings, 1 reply; 15+ messages in thread
From: Alexei Starovoitov @ 2026-11-02 22:39 UTC (permalink / raw)
  To: Vineet Gupta, bpf
  Cc: daniel, andrii, eddyz87, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, john.fastabend, shuah, linux-kernel,
	linux-kselftest, jose.marchesi, david.faust

On Mon, Nov 02, 2026 at 02:07 PM Vineet Gupta <vineet.gupta@linux.dev> wrote:
> These are not driven by test_loader, so __skip_without_arena does not
> reach them.  Use the flag-in-.data pattern linked_externs.c already
> uses for the same situation: the program exports skip_tests, and the
> host checks it before attaching and reports SKIP.

cast_kern() is cleaner...
It's a nop when the compiler supports arena.

diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena.c b/tools/testing/selftests/bpf/progs/struct_ops_arena.c
index 8aa8639..3fffa24 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_arena.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_arena.c
@@ -86,7 +86,6 @@ struct bpf_testmod_ops3 testmod_arena = {
 SEC("syscall")
 int trigger(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 	int ret;

@@ -94,6 +93,7 @@ int trigger(void *ctx)
 	if (!val)
 		return 1;

+	cast_kern(val);
 	*val = 41;
 	ret = bpf_testmod_ops3_call_test_arena((u64 *)val);
 	if (ret)
@@ -134,6 +134,5 @@ int trigger(void *ctx)
 		return 11;

 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
index 495faa0..3455ca9 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
@@ -45,13 +45,13 @@ int unrelated(void *ctx)
 SEC("syscall")
 int trigger(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;

 	val = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
 	if (!val)
 		return 1;

+	cast_kern(val);
 	*val = 41;
 	if (bpf_testmod_ops3_call_test_arena((u64 *)val))
 		return 2;
@@ -59,6 +59,5 @@ int trigger(void *ctx)
 		return 3;

 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
index a2218cd..afbe59f 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
@@ -80,7 +80,6 @@ struct bpf_testmod_ops3 testmod_arena_member = {
 SEC("syscall")
 int trigger(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 	int ret;

@@ -88,6 +87,7 @@ int trigger(void *ctx)
 	if (!val)
 		return 1;

+	cast_kern(val);
 	*val = 41;
 	ret = bpf_testmod_ops3_call_test_arena_member((u64 *)val);
 	if (ret)
@@ -104,6 +104,5 @@ int trigger(void *ctx)
 		return 4;

 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }
diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
index 09b4c74..c4e134e 100644
--- a/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
+++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
@@ -63,7 +63,6 @@ struct bpf_testmod_ops3 testmod_arena_member_render = {
 SEC("syscall")
 int trigger(void *ctx)
 {
-#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
 	u64 __arena *val;
 	int ret;

@@ -71,6 +70,7 @@ int trigger(void *ctx)
 	if (!val)
 		return 1;

+	cast_kern(val);
 	*val = 41;
 	ret = bpf_testmod_ops3_call_test_arena_member((u64 *)val);
 	if (ret)
@@ -80,6 +80,5 @@ int trigger(void *ctx)
 		return 3;

 	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
-#endif
 	return 0;
 }

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next v3 4/8] selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds
  2026-11-02 22:38   ` Alexei Starovoitov
@ 2026-11-03  0:15     ` Vineet Gupta
  0 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-03  0:15 UTC (permalink / raw)
  To: Alexei Starovoitov, bpf
  Cc: daniel, andrii, eddyz87, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, john.fastabend, shuah, linux-kernel,
	linux-kselftest, jose.marchesi, david.faust

On 11/2/26 2:38 PM, Alexei Starovoitov wrote:
> On Mon, Nov 02, 2026 at 02:07 PM Vineet Gupta <vineet.gupta@linux.dev> wrote:
>> The barrier is behind #ifdef __clang__ so clang keeps the plain macro.
>> It does not need it, and the barrier is not free: it blocks reuse of
>> the map address, so each call site reloads it.  Across the five progs
>> and 20 call sites that is +35 instructions under GCC
>> (2528 -> 2563), about 1.4% on those objects and nothing elsewhere.
>> Clang output is unchanged, bit for bit.
> stream.c already has barrier_var() for both compilers.
>
> How about this one instead:

Yeah definitely much better. Just to be clear the intent of series is to 
not make current compiler look better o anything. As I mentioned in the 
cover, this was during in my in-works arena compiler testing, ....

Thx for the quick feedback.
-Vineet


> diff --git a/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h b/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
> index 82aafe8..0eba529 100644
> --- a/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
> +++ b/tools/testing/selftests/bpf/libarena/include/bpf_arena_common.h
> @@ -49,7 +49,16 @@ void __arena* bpf_arena_alloc_pages(void *map, void __arena *addr, __u32 page_cn
>   int bpf_arena_reserve_pages(void *map, void __arena *addr, __u32 page_cnt) __ksym __weak;
>   void bpf_arena_free_pages(void *map, void __arena *ptr, __u32 page_cnt) __ksym __weak;
>
> -#define arena_base(map) ((void __arena *)((struct bpf_arena *)(map))->user_vm_start)
> +/*
> + * The map definition is smaller than struct bpf_arena.
> + * barrier_var() hides that from -Warray-bounds of GCC.
> + */
> +#define arena_base(map)							\
> +	({								\
> +		struct bpf_arena *___arena = (void *)(map);		\
> +		barrier_var(___arena);					\
> +		(void __arena *)___arena->user_vm_start;		\
> +	})
>
>   #else /* when compiled as user space code */
>
> diff --git a/tools/testing/selftests/bpf/progs/stream.c b/tools/testing/selftests/bpf/progs/stream.c
> index 1ae015c..b4d88d0 100644
> --- a/tools/testing/selftests/bpf/progs/stream.c
> +++ b/tools/testing/selftests/bpf/progs/stream.c
> @@ -178,16 +178,8 @@ __stderr("Call trace:\n"
>   "|[ \t]+[^\n]+\n)*}}")
>   int stream_arena_write_fault(void *ctx)
>   {
> -	struct bpf_arena *ptr = (void *)&arena;
> -	u64 user_vm_start;
> +	u64 user_vm_start = (u64)arena_base(&arena);
>
> -	/* Prevent GCC bounds warning: casting &arena to struct bpf_arena *
> -	 * triggers bounds checking since the map definition is smaller than struct
> -	 * bpf_arena. barrier_var() makes the pointer opaque to GCC, preventing the
> -	 * bounds analysis
> -	 */
> -	barrier_var(ptr);
> -	user_vm_start = ptr->user_vm_start;
>   	fault_addr = user_vm_start + 0x7fff;
>   	bpf_addr_space_cast(user_vm_start, 0, 1);
>   	asm volatile (
> @@ -212,16 +204,8 @@ __stderr("Call trace:\n"
>   "|[ \t]+[^\n]+\n)*}}")
>   int stream_arena_read_fault(void *ctx)
>   {
> -	struct bpf_arena *ptr = (void *)&arena;
> -	u64 user_vm_start;
> +	u64 user_vm_start = (u64)arena_base(&arena);
>
> -	/* Prevent GCC bounds warning: casting &arena to struct bpf_arena *
> -	 * triggers bounds checking since the map definition is smaller than struct
> -	 * bpf_arena. barrier_var() makes the pointer opaque to GCC, preventing the
> -	 * bounds analysis
> -	 */
> -	barrier_var(ptr);
> -	user_vm_start = ptr->user_vm_start;
>   	fault_addr = user_vm_start + 0x7fff;
>   	bpf_addr_space_cast(user_vm_start, 0, 1);
>   	asm volatile (
> @@ -252,17 +236,9 @@ int stream_arena_load_acquire_fault(void *ctx)
>   		.off	 = 0x7fff,
>   		.imm	 = 0x100,	/* BPF_LOAD_ACQ */
>   	};
> -	struct bpf_arena *ptr = (void *)&arena;
> -	u64 user_vm_start, val;
> +	u64 user_vm_start = (u64)arena_base(&arena);
> +	u64 val;
>
> -	/*
> -	 * Prevent GCC bounds warning: casting &arena to struct bpf_arena *
> -	 * triggers bounds checking since the map definition is smaller than
> -	 * struct bpf_arena. barrier_var() makes the pointer opaque to GCC,
> -	 * preventing the bounds analysis.
> -	 */
> -	barrier_var(ptr);
> -	user_vm_start = ptr->user_vm_start;
>   	fault_addr = user_vm_start + 0x7fff;
>   	bpf_addr_space_cast(user_vm_start, 0, 1);
>   	asm volatile (
> @@ -296,17 +272,9 @@ int stream_arena_xchg_fault(void *ctx)
>   		.off	 = 0x7fff,
>   		.imm	 = 0xe1,	/* BPF_XCHG */
>   	};
> -	struct bpf_arena *ptr = (void *)&arena;
> -	u64 user_vm_start, val;
> +	u64 user_vm_start = (u64)arena_base(&arena);
> +	u64 val;
>
> -	/*
> -	 * Prevent GCC bounds warning: casting &arena to struct bpf_arena *
> -	 * triggers bounds checking since the map definition is smaller than
> -	 * struct bpf_arena. barrier_var() makes the pointer opaque to GCC,
> -	 * preventing the bounds analysis.
> -	 */
> -	barrier_var(ptr);
> -	user_vm_start = ptr->user_vm_start;
>   	fault_addr = user_vm_start + 0x7fff;
>   	bpf_addr_space_cast(user_vm_start, 0, 1);
>   	/*
> @@ -346,17 +314,9 @@ int stream_arena_cmpxchg_fault(void *ctx)
>   		.off	 = 0x7fff,
>   		.imm	 = 0xf1,	/* BPF_CMPXCHG */
>   	};
> -	struct bpf_arena *ptr = (void *)&arena;
> -	u64 user_vm_start, val;
> +	u64 user_vm_start = (u64)arena_base(&arena);
> +	u64 val;
>
> -	/*
> -	 * Prevent GCC bounds warning: casting &arena to struct bpf_arena *
> -	 * triggers bounds checking since the map definition is smaller than
> -	 * struct bpf_arena. barrier_var() makes the pointer opaque to GCC,
> -	 * preventing the bounds analysis.
> -	 */
> -	barrier_var(ptr);
> -	user_vm_start = ptr->user_vm_start;
>   	fault_addr = user_vm_start + 0x7fff;
>   	bpf_addr_space_cast(user_vm_start, 0, 1);
>   	/*


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next v3 8/8] selftests/bpf: skip the struct_ops arena tests without compiler support
  2026-11-02 22:39   ` Alexei Starovoitov
@ 2026-11-03  0:17     ` Vineet Gupta
  0 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-03  0:17 UTC (permalink / raw)
  To: Alexei Starovoitov, bpf
  Cc: daniel, andrii, eddyz87, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, john.fastabend, shuah, linux-kernel,
	linux-kselftest, jose.marchesi, david.faust

On 11/2/26 2:39 PM, Alexei Starovoitov wrote:
> On Mon, Nov 02, 2026 at 02:07 PM Vineet Gupta <vineet.gupta@linux.dev> wrote:
>> These are not driven by test_loader, so __skip_without_arena does not
>> reach them.  Use the flag-in-.data pattern linked_externs.c already
>> uses for the same situation: the program exports skip_tests, and the
>> host checks it before attaching and reports SKIP.
> cast_kern() is cleaner...
> It's a nop when the compiler supports arena.

Nice, definitely better than what I had since now more code is exercised 
than being skipped.

Thx,
-Vineet

> diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena.c b/tools/testing/selftests/bpf/progs/struct_ops_arena.c
> index 8aa8639..3fffa24 100644
> --- a/tools/testing/selftests/bpf/progs/struct_ops_arena.c
> +++ b/tools/testing/selftests/bpf/progs/struct_ops_arena.c
> @@ -86,7 +86,6 @@ struct bpf_testmod_ops3 testmod_arena = {
>   SEC("syscall")
>   int trigger(void *ctx)
>   {
> -#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
>   	u64 __arena *val;
>   	int ret;
>
> @@ -94,6 +93,7 @@ int trigger(void *ctx)
>   	if (!val)
>   		return 1;
>
> +	cast_kern(val);
>   	*val = 41;
>   	ret = bpf_testmod_ops3_call_test_arena((u64 *)val);
>   	if (ret)
> @@ -134,6 +134,5 @@ int trigger(void *ctx)
>   		return 11;
>
>   	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
> -#endif
>   	return 0;
>   }
> diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
> index 495faa0..3455ca9 100644
> --- a/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
> +++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_autobind.c
> @@ -45,13 +45,13 @@ int unrelated(void *ctx)
>   SEC("syscall")
>   int trigger(void *ctx)
>   {
> -#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
>   	u64 __arena *val;
>
>   	val = bpf_arena_alloc_pages(&arena, NULL, 1, NUMA_NO_NODE, 0);
>   	if (!val)
>   		return 1;
>
> +	cast_kern(val);
>   	*val = 41;
>   	if (bpf_testmod_ops3_call_test_arena((u64 *)val))
>   		return 2;
> @@ -59,6 +59,5 @@ int trigger(void *ctx)
>   		return 3;
>
>   	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
> -#endif
>   	return 0;
>   }
> diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
> index a2218cd..afbe59f 100644
> --- a/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
> +++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_member.c
> @@ -80,7 +80,6 @@ struct bpf_testmod_ops3 testmod_arena_member = {
>   SEC("syscall")
>   int trigger(void *ctx)
>   {
> -#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
>   	u64 __arena *val;
>   	int ret;
>
> @@ -88,6 +87,7 @@ int trigger(void *ctx)
>   	if (!val)
>   		return 1;
>
> +	cast_kern(val);
>   	*val = 41;
>   	ret = bpf_testmod_ops3_call_test_arena_member((u64 *)val);
>   	if (ret)
> @@ -104,6 +104,5 @@ int trigger(void *ctx)
>   		return 4;
>
>   	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
> -#endif
>   	return 0;
>   }
> diff --git a/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c b/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
> index 09b4c74..c4e134e 100644
> --- a/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
> +++ b/tools/testing/selftests/bpf/progs/struct_ops_arena_member_render.c
> @@ -63,7 +63,6 @@ struct bpf_testmod_ops3 testmod_arena_member_render = {
>   SEC("syscall")
>   int trigger(void *ctx)
>   {
> -#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
>   	u64 __arena *val;
>   	int ret;
>
> @@ -71,6 +70,7 @@ int trigger(void *ctx)
>   	if (!val)
>   		return 1;
>
> +	cast_kern(val);
>   	*val = 41;
>   	ret = bpf_testmod_ops3_call_test_arena_member((u64 *)val);
>   	if (ret)
> @@ -80,6 +80,5 @@ int trigger(void *ctx)
>   		return 3;
>
>   	bpf_arena_free_pages(&arena, (void __arena *)val, 1);
> -#endif
>   	return 0;
>   }


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH bpf-next v3 3/8] selftests/bpf: report SKIP for arena tests a compiler cannot build
  2026-11-02 22:36   ` Alexei Starovoitov
@ 2026-11-03  0:24     ` Vineet Gupta
  0 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2026-11-03  0:24 UTC (permalink / raw)
  To: Alexei Starovoitov, bpf
  Cc: daniel, andrii, eddyz87, memxor, martin.lau, song, yonghong.song,
	jolsa, emil, ihor.solodrai, john.fastabend, shuah, linux-kernel,
	linux-kselftest, jose.marchesi, david.faust

On 11/2/26 2:36 PM, Alexei Starovoitov wrote:
> On Mon, Nov 02, 2026 at 02:07 PM Vineet Gupta <vineet.gupta@linux.dev> wrote:
>> Give each guard an #else with a dummy marked __skip(), so the skip gap is
>> reported rather than invisible.  Add __skip_without_arena for it, which
>> expands to __skip() with a fixed reason when the compiler cannot do arena.
> How about the following approach instead...
> looks much simpler to me...

Agree: it does look simpler and they uncover more code to be tested now 
than being skipped.

Thx,
-Vineet

> pw-bot: cr
>
> diff --git a/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c b/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
> index b5a01cb..16c3dd9 100644
> --- a/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
> +++ b/tools/testing/selftests/bpf/progs/arena_kfunc_jit.c
> @@ -23,8 +23,6 @@ struct {
>   /* volatile to force the scalar reloads below */
>   volatile u64 stash;
>
> -#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
> -
>   SEC("syscall")
>   __arch_x86_64
>   __jited("...")
> @@ -93,6 +91,7 @@ __jited("	cbz	w4, L0")
>   __jited("	add	x4, x28, w4, uxtw")
>   __jited("L0:	{{.*}}")
>   __success
> +__skip_without_arena
>   int arena_arg_jit_args5(void *ctx)
>   {
>   	u64 __arena *val;
> @@ -113,6 +112,4 @@ int arena_arg_jit_args5(void *ctx)
>   	return 0;
>   }
>
> -#endif /* __BPF_FEATURE_ADDR_SPACE_CAST */
> -
>   char _license[] SEC("license") = "GPL";
> diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
> index d7f706c..4ec840b 100644
> --- a/tools/testing/selftests/bpf/progs/bpf_misc.h
> +++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
> @@ -116,6 +116,10 @@
>    *                   feature the toolchain or JIT cannot provide, so a run does
>    *                   not report OK for coverage it never executed.
>    *
> + * __skip_without_arena
> + *                   __skip() when the compiler does not support the arena
> + *                   address space, nothing otherwise.
> + *
>    * __log_level       Log level to use for the program, numeric value expected.
>    *
>    * __flag            Adds one flag use for the program, the following values are valid:
> @@ -156,6 +160,11 @@
>   #define __success		__test_tag("test_expect_success")
>   #define __description(desc)	__test_tag("test_description=" desc)
>   #define __skip(reason)		__test_tag("test_skip=" reason)
> +#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
> +#define __skip_without_arena
> +#else
> +#define __skip_without_arena	__skip("compiler does not support the arena address space")
> +#endif
>   #define __msg_unpriv(msg)	__test_tag("test_expect_msg_unpriv=" msg)
>   #define __not_msg_unpriv(msg)	__test_tag("test_expect_not_msg_unpriv=" msg)
>   #define __msg_next_unpriv(msg)	__test_tag("test_expect_msg_next_unpriv=" msg)
> diff --git a/tools/testing/selftests/bpf/progs/jit_insns_arena.c b/tools/testing/selftests/bpf/progs/jit_insns_arena.c
> index 95736ea..77d135a 100644
> --- a/tools/testing/selftests/bpf/progs/jit_insns_arena.c
> +++ b/tools/testing/selftests/bpf/progs/jit_insns_arena.c
> @@ -106,6 +106,14 @@ int cast_to_user(void *ctx)
>   	: "r1", "r2", "r7", "r9");
>   	return res != 0;
>   }
> +#else
> +SEC("socket")
> +__skip_without_arena
> +__success
> +int arena_unsupported(void)
> +{
> +	return 0;
> +}
>   #endif
>
>   char _license[] SEC("license") = "GPL";
> diff --git a/tools/testing/selftests/bpf/progs/verifier_arena_large.c b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
> index dbdea14..428b984 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_arena_large.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_arena_large.c
> @@ -181,7 +181,6 @@ int free_reserved(void *ctx)
>   	return 0;
>   }
>
> -#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
>   #define PAGE_CNT 100
>   __u8 __arena * __arena page[PAGE_CNT]; /* occupies the first page */
>   __u8 __arena *base;
> @@ -220,6 +219,7 @@ __noinline int alloc_pages(int page_cnt, int pages_atonce, bool first_pass,
>
>   SEC("syscall")
>   __success __retval(0)
> +__skip_without_arena
>   int big_alloc2(void *ctx)
>   {
>   	__u8 __arena *pg;
> @@ -290,9 +290,9 @@ int big_alloc2(void *ctx)
>   /* Nonsleepable because it binds to a socket program. */
>   SEC("socket")
>   __success __retval(0)
> +__skip_without_arena
>   int big_alloc3(void *ctx)
>   {
> -#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
>   	char __arena *pages;
>   	u64 i;
>   	int err = 0;
> @@ -314,16 +314,14 @@ int big_alloc3(void *ctx)
>
>   	bpf_arena_free_pages(&arena, pages, LARGE_PAGE_CNT);
>   	return err;
> -#endif
> -	return 0;
>   }
>
>   /* SYSCALL programs are always sleepable. */
>   SEC("syscall")
>   __success __retval(0)
> +__skip_without_arena
>   int big_alloc4(void *ctx)
>   {
> -#if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
>   	char __arena *pages;
>   	u64 i;
>   	int err = 0;
> @@ -345,8 +343,6 @@ int big_alloc4(void *ctx)
>
>   	bpf_arena_free_pages(&arena, pages, LARGE_PAGE_CNT);
>   	return err;
> -#endif
> -	return 0;
>   }
> -#endif
> +
>   char _license[] SEC("license") = "GPL";


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2026-11-03  0:25 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-02 22:07 [PATCH bpf-next v3 0/8] selftests/bpf: cleanup bpf-gcc runs Vineet Gupta
2026-11-02 22:07 ` [PATCH bpf-next v3 1/8] selftests/bpf: Build callx tests with GCC that defines __BPF_FEATURE_CALLX Vineet Gupta
2026-11-02 22:07 ` [PATCH bpf-next v3 2/8] selftests/bpf: don't pass clang-only warning flags to GCC Vineet Gupta
2026-11-02 22:07 ` [PATCH bpf-next v3 3/8] selftests/bpf: report SKIP for arena tests a compiler cannot build Vineet Gupta
2026-11-02 22:36   ` Alexei Starovoitov
2026-11-03  0:24     ` Vineet Gupta
2026-11-02 22:07 ` [PATCH bpf-next v3 4/8] selftests/bpf: make arena_base() opaque to GCC's -Warray-bounds Vineet Gupta
2026-11-02 22:38   ` Alexei Starovoitov
2026-11-03  0:15     ` Vineet Gupta
2026-11-02 22:07 ` [PATCH bpf-next v3 5/8] selftests/bpf: don't report arena tests as passing with an empty body Vineet Gupta
2026-11-02 22:07 ` [PATCH bpf-next v3 6/8] selftests/bpf: cast explicitly in the arena subprog and callback faults Vineet Gupta
2026-11-02 22:07 ` [PATCH bpf-next v3 7/8] selftests/bpf: write the mixed arena/scalar ALU tests in asm Vineet Gupta
2026-11-02 22:07 ` [PATCH bpf-next v3 8/8] selftests/bpf: skip the struct_ops arena tests without compiler support Vineet Gupta
2026-11-02 22:39   ` Alexei Starovoitov
2026-11-03  0:17     ` Vineet Gupta

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®