BPF List
 help / color / mirror / Atom feed
From: Yonghong Song <yonghong.song@linux.dev>
To: bot+bpf-ci@kernel.org, bpf@vger.kernel.org
Cc: ast@kernel.org, andrii@kernel.org, daniel@iogearbox.net,
	eddyz87@gmail.com, kernel-team@fb.com, martin.lau@kernel.org,
	clm@meta.com, ihor.solodrai@linux.dev
Subject: Re: [PATCH bpf-next v2 10/10] selftests/bpf: Test kfuncs returning arena pointers by value
Date: Wed, 26 Aug 2026 20:58:33 -0700	[thread overview]
Message-ID: <d479c649-9ced-4053-8aa0-ea8b74b09088@linux.dev> (raw)
In-Reply-To: <77c79917dc8a9d299cfa0725c5bf278a32d9563915878546fe394650eeade3d8@mail.kernel.org>



On 8/25/26 2:59 PM, bot+bpf-ci@kernel.org wrote:
>> diff --git a/tools/testing/selftests/bpf/prog_tests/aggregate_ret.c b/tools/testing/selftests/bpf/prog_tests/aggregate_ret.c
>> index e0b94ed10f941..07d9d6e1d6b88 100644
>> --- a/tools/testing/selftests/bpf/prog_tests/aggregate_ret.c
>> +++ b/tools/testing/selftests/bpf/prog_tests/aggregate_ret.c
>> @@ -1,11 +1,53 @@
>>   // SPDX-License-Identifier: GPL-2.0
>>   /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
>>   #include <test_progs.h>
>> +#include <bpf/btf.h>
>>   #include "aggregate_ret_func.skel.h"
>>   #include "aggregate_ret_kfunc.skel.h"
>> +#include "aggregate_ret_kfunc_arena.skel.h"
>> +
>> +static bool testmod_has_arena_tagged_member(void)
>> +{
>> +	struct btf *vmlinux_btf, *module_btf = NULL;
>> +	const struct btf_type *t;
>> +	bool tagged = false;
>> +	__s32 id;
>> +
>> +	vmlinux_btf = btf__load_vmlinux_btf();
>> +	if (!vmlinux_btf)
>> +		return false;
>> +
>> +	module_btf = btf__load_module_btf("bpf_testmod", vmlinux_btf);
>> +	if (!module_btf)
>> +		goto out;
>> +
>> +	/* prog_test_ret_arena::a is 'void __arena_tag *': PTR -> TYPE_TAG -> void */
>> +	id = btf__find_by_name_kind(module_btf, "prog_test_ret_arena", BTF_KIND_STRUCT);
>> +	if (id <= 0)
>> +		goto out;
>> +
>> +	t = btf__type_by_id(module_btf, btf_members(btf__type_by_id(module_btf, id))[0].type);
>> +	if (!t || !btf_is_ptr(t))
>> +		goto out;
>> +
>> +	t = btf__type_by_id(module_btf, t->type);
>> +	tagged = t && btf_is_type_tag(t) &&
>> +		 !strcmp(btf__name_by_offset(module_btf, t->name_off), "arena");
>> +
>> +out:
>> +	btf__free(module_btf);
>> +	btf__free(vmlinux_btf);
>> +
>> +	return tagged;
>> +}
>>
>>   void test_aggregate_ret(void)
>>   {
>>   	RUN_TESTS(aggregate_ret_func);
>>   	RUN_TESTS(aggregate_ret_kfunc);
>> +
>> +	if (testmod_has_arena_tagged_member())
>> +		RUN_TESTS(aggregate_ret_kfunc_arena);
>> +	else
>> +		test__skip();
> A subsystem pattern flags this as potentially concerning:
> testmod_has_arena_tagged_member() collapses four distinct outcomes
> into the same 'false' return: environment broken (no vmlinux BTF),
> testmod absent or BTF missing, stale bpf_testmod.ko, or the actual
> capability probe (btf_type_tag attribute absent). When test__skip()
> is called without a reason string, the run shows 'aggregate_ret:OK
> (SKIP: 1/N)' with no indication of what was skipped or why.
>
> Since PAHOLE_HAS_BTF_TAG depends on CC_IS_CLANG (lib/Kconfig.debug)
> and GCC does not implement btf_type_tag, the skip branch is the normal
> outcome on a GCC-built kernel, which makes a permanently-skipped test
> easy to miss. The test appears to pass but the new coverage never runs.
>
> The BPF selftests/bpf/prog_tests/btf_tag.c establishes a precedent:
> it checks env.has_testmod, uses ASSERT_OK_PTR() so a BTF-load failure
> is a real FAIL, and prints a reason string before test__skip():
>
>      printf("%s:SKIP: btf_type_tag attribute not in %s", __func__, module_name)
>
> Should testmod_has_arena_tagged_member() distinguish a broken environment
> (ASSERT_OK_PTR on the vmlinux BTF) from a missing capability, and should
> the test__skip() carry a reason string?

It is already very clear for SKIP which is due to btf_type_tag attribute
is not available. The checking for e.g. vmlinux, load_module etc is
normal checking. It is to prevent potential environment issue but does not
mean the environment is broken.

>
>>   }
>> diff --git a/tools/testing/selftests/bpf/progs/aggregate_ret_kfunc_arena.c b/tools/testing/selftests/bpf/progs/aggregate_ret_kfunc_arena.c
>> new file mode 100644
>> index 0000000000000..f68deae6c900e
>> --- /dev/null
>> +++ b/tools/testing/selftests/bpf/progs/aggregate_ret_kfunc_arena.c
>> @@ -0,0 +1,47 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
>> +#include <vmlinux.h>
>> +#include <bpf/bpf_helpers.h>
>> +#include "bpf_misc.h"
>> +#include "../test_kmods/bpf_testmod_kfunc.h"
>> +
>> +void __kfunc_btf_root(void)
>> +{
>> +	asm volatile (""
>> +	:
>> +	: "r"(&bpf_kfunc_call_test_ret_arena),
>> +	  "r"(&bpf_kfunc_call_test_ret_arena_mixed));
>> +}
> A subsystem pattern flags this as potentially concerning: a new BPF
> prog file is added for two test cases, but progs/aggregate_ret_kfunc.c
> in the same directory already covers by-value kfunc returns
> (aggregate_ret_kfunc_precise, _fastcall_fail, _ptr_fail,
> _nested_ptr_fail, _too_deep_fail, _small_no_r2, _too_big_fail). The
> new file duplicates the header includes, the license string, the
> SEC("tc")/__arch_x86_64/__arch_arm64/__load_if_JITed() preamble and
> __kfunc_btf_root() itself, for two subtests.
>
> RUN_TESTS() operates on a whole skeleton (test_progs.h:546 ->
> test_loader__run_subtests(&tester, #skel, skel##__elf_bytes)), and
> these two subtests must be gated on whether the running bpf_testmod's
> BTF carries the 'arena' type tag - a per-toolchain condition that has
> no per-subtest expression in bpf_misc.h (__arch_*/__load_if_JITed
> cover architecture and JIT only). Putting them in
> aggregate_ret_kfunc.c would force the whole existing matrix behind
> the same gate.
>
> Is the separate file justified by the per-skeleton gating requirement,
> or could the new cases be added to aggregate_ret_kfunc.c?

Yes, I would like to be in aggregate_ret_kfunc_arena.c as
we want to test kfunc with arena's.

>
>> +
>> +SEC("tc")
>> +__arch_x86_64 __arch_arm64
>> +__load_if_JITed()
>> +__success __retval(0)
>> +__naked int aggregate_ret_kfunc_arena(void)
>> +{
>> +	asm volatile (
>> +	"call %[bpf_kfunc_call_test_ret_arena];"
>> +	"r0 = 0;"
>> +	"exit;"
>> +	:
>> +	: __imm(bpf_kfunc_call_test_ret_arena)
>> +	: __clobber_all);
>> +}
>> +
>> +SEC("tc")
>> +__arch_x86_64 __arch_arm64
>> +__load_if_JITed()
>> +__success __retval(0)
>> +__naked int aggregate_ret_kfunc_arena_mixed(void)
>> +{
>> +	asm volatile (
>> +	"r1 = 0;"
>> +	"call %[bpf_kfunc_call_test_ret_arena_mixed];"
>> +	"r0 = 0;"
>> +	"exit;"
>> +	:
>> +	: __imm(bpf_kfunc_call_test_ret_arena_mixed)
>> +	: __clobber_all);
>> +}
> The changelog claims this patch covers 'two arena pointers filling
> R0:R2', but neither new program ever reads R2. Both bodies are
> 'call <kfunc>; r0 = 0; exit;' with __success __retval(0), which only
> proves that check_kfunc_call() accepted the return type - i.e. that
> btf_struct_member_walk(..., BTF_MEMBER_SCALAR | BTF_MEMBER_ARENA_PTR, ...)
> returned true (kernel/bpf/verifier.c:14097). The number of return
> registers is decided separately by mark_kfunc_ret_regs() -> ret_regs_cnt(size)
> (kernel/bpf/verifier.c:11351, :413); if that path regressed to a
> single register for a 16-byte STRUCT return, both new tests would
> still pass, because R2 is never read.
>
> The file this patch sits beside already establishes the idiom for
> pinning this: aggregate_ret_kfunc_small_no_r2 asserts __failure
> __msg("R2 !read_ok") to prove R2 is *not* a return register for an
> 8-byte struct, and aggregate_ret_kfunc_precise reads 'r6 = r2' after
> the __int128 kfunc to prove R2 *is*.
>
> Should at least one of the arena tests read R2 back to verify the
> two-register return path?

Yes, this is a problem. I will try to come up with better tests.

>
>> +
>> +char _license[] SEC("license") = "GPL";
> [ ... ]
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/32899532405


      reply	other threads:[~2026-08-27  3:58 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-25 20:54 [PATCH bpf-next v2 00/10] bpf: Allow arena pointers in by-value returns Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 01/10] bpf: Record each half of a paired return value in verifier diagnostics Yonghong Song
2026-08-25 21:59   ` bot+bpf-ci
2026-08-26 17:08     ` Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 02/10] bpf: Drop the recursion depth argument of btf_type_is_scalar_struct() Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 03/10] bpf: Add btf_type_is_arena_ptr() Yonghong Song
2026-08-25 21:59   ` bot+bpf-ci
2026-08-26 17:28     ` Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 04/10] bpf: Let the by-value struct walk take the kinds of member it accepts Yonghong Song
2026-08-25 21:59   ` bot+bpf-ci
2026-08-26 17:39     ` Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 05/10] bpf: Report which member makes a kfunc return type unsupported Yonghong Song
2026-08-25 21:59   ` bot+bpf-ci
2026-08-26 17:59     ` Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 06/10] bpf: Allow a global function to return arena pointers by value Yonghong Song
2026-08-25 21:12   ` sashiko-bot
2026-08-26 18:40     ` Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 07/10] bpf: Allow arena pointers in a by-value kfunc return Yonghong Song
2026-08-25 22:13   ` bot+bpf-ci
2026-08-26 18:57     ` Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 08/10] selftests/bpf: Check the member named for an unsupported kfunc return type Yonghong Song
2026-08-25 20:54 ` [PATCH bpf-next v2 09/10] selftests/bpf: Test global functions returning arena pointers by value Yonghong Song
2026-08-25 21:59   ` bot+bpf-ci
2026-08-27  3:46     ` Yonghong Song
2026-08-25 20:55 ` [PATCH bpf-next v2 10/10] selftests/bpf: Test kfuncs " Yonghong Song
2026-08-25 21:59   ` bot+bpf-ci
2026-08-27  3:58     ` Yonghong Song [this message]

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=d479c649-9ced-4053-8aa0-ea8b74b09088@linux.dev \
    --to=yonghong.song@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bot+bpf-ci@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=clm@meta.com \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=kernel-team@fb.com \
    --cc=martin.lau@kernel.org \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox