From: Takeru Hayasaka <hayatake396@gmail.com>
To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org
Cc: bpf@vger.kernel.org, x86@kernel.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH bpf-next 2/2] selftests/bpf: cover fentry on tailcalled programs
Date: Fri, 27 Mar 2026 14:16:02 +0000 [thread overview]
Message-ID: <20260327141616.1961457-3-hayatake396@gmail.com> (raw)
In-Reply-To: <20260327141616.1961457-1-hayatake396@gmail.com>
Add a small tailcall target/probe pair and a tailcalls subtest that
attaches fentry to the callee program.
The test first runs the callee directly and checks that fentry fires
exactly once, then runs the entry program, tail-calls into the callee
and checks that the same fentry also fires exactly once on the tail-call
path.
This covers both sides of the x86 change: direct entry must not
double-fire, while tail-called entry must now be observable.
Signed-off-by: Takeru Hayasaka <hayatake396@gmail.com>
---
.../selftests/bpf/prog_tests/tailcalls.c | 110 ++++++++++++++++++
.../bpf/progs/tailcall_fentry_probe.c | 16 +++
.../bpf/progs/tailcall_fentry_target.c | 27 +++++
3 files changed, 153 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/tailcall_fentry_probe.c
create mode 100644 tools/testing/selftests/bpf/progs/tailcall_fentry_target.c
diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
index 7d534fde0af9..ac05df65b666 100644
--- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c
+++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c
@@ -1113,6 +1113,114 @@ static void test_tailcall_bpf2bpf_fentry_entry(void)
bpf_object__close(tgt_obj);
}
+static void test_tailcall_fentry_tailcallee(void)
+{
+ struct bpf_object *tgt_obj = NULL, *fentry_obj = NULL;
+ struct bpf_map *prog_array, *data_map;
+ struct bpf_link *fentry_link = NULL;
+ struct bpf_program *prog;
+ int err, map_fd, callee_fd, main_fd, data_fd, i, val;
+ char buff[128] = {};
+
+ LIBBPF_OPTS(bpf_test_run_opts, topts,
+ .data_in = buff,
+ .data_size_in = sizeof(buff),
+ .repeat = 1,
+ );
+
+ err = bpf_prog_test_load("tailcall_fentry_target.bpf.o",
+ BPF_PROG_TYPE_SCHED_CLS,
+ &tgt_obj, &main_fd);
+ if (!ASSERT_OK(err, "load tgt_obj"))
+ return;
+
+ prog_array = bpf_object__find_map_by_name(tgt_obj, "jmp_table");
+ if (!ASSERT_OK_PTR(prog_array, "find jmp_table map"))
+ goto out;
+
+ map_fd = bpf_map__fd(prog_array);
+ if (!ASSERT_FALSE(map_fd < 0, "find jmp_table map fd"))
+ goto out;
+
+ prog = bpf_object__find_program_by_name(tgt_obj, "entry");
+ if (!ASSERT_OK_PTR(prog, "find entry prog"))
+ goto out;
+
+ main_fd = bpf_program__fd(prog);
+ if (!ASSERT_FALSE(main_fd < 0, "find entry prog fd"))
+ goto out;
+
+ prog = bpf_object__find_program_by_name(tgt_obj, "callee");
+ if (!ASSERT_OK_PTR(prog, "find callee prog"))
+ goto out;
+
+ callee_fd = bpf_program__fd(prog);
+ if (!ASSERT_FALSE(callee_fd < 0, "find callee prog fd"))
+ goto out;
+
+ i = 0;
+ err = bpf_map_update_elem(map_fd, &i, &callee_fd, BPF_ANY);
+ if (!ASSERT_OK(err, "update jmp_table"))
+ goto out;
+
+ fentry_obj = bpf_object__open_file("tailcall_fentry_probe.bpf.o", NULL);
+ if (!ASSERT_OK_PTR(fentry_obj, "open fentry_obj file"))
+ goto out;
+
+ prog = bpf_object__find_program_by_name(fentry_obj, "fentry_callee");
+ if (!ASSERT_OK_PTR(prog, "find fentry prog"))
+ goto out;
+
+ err = bpf_program__set_attach_target(prog, callee_fd, "callee");
+ if (!ASSERT_OK(err, "set_attach_target callee"))
+ goto out;
+
+ err = bpf_object__load(fentry_obj);
+ if (!ASSERT_OK(err, "load fentry_obj"))
+ goto out;
+
+ fentry_link = bpf_program__attach_trace(prog);
+ if (!ASSERT_OK_PTR(fentry_link, "attach_trace"))
+ goto out;
+
+ data_map = bpf_object__find_map_by_name(fentry_obj, ".bss");
+ if (!ASSERT_FALSE(!data_map || !bpf_map__is_internal(data_map),
+ "find tailcall_fentry_probe.bss map"))
+ goto out;
+
+ data_fd = bpf_map__fd(data_map);
+ if (!ASSERT_FALSE(data_fd < 0,
+ "find tailcall_fentry_probe.bss map fd"))
+ goto out;
+
+ err = bpf_prog_test_run_opts(callee_fd, &topts);
+ ASSERT_OK(err, "direct callee");
+ ASSERT_EQ(topts.retval, 7, "direct callee retval");
+
+ i = 0;
+ err = bpf_map_lookup_elem(data_fd, &i, &val);
+ ASSERT_OK(err, "direct fentry count");
+ ASSERT_EQ(val, 1, "direct fentry count");
+
+ val = 0;
+ err = bpf_map_update_elem(data_fd, &i, &val, BPF_ANY);
+ ASSERT_OK(err, "reset fentry count");
+
+ err = bpf_prog_test_run_opts(main_fd, &topts);
+ ASSERT_OK(err, "tailcall");
+ ASSERT_EQ(topts.retval, 7, "tailcall retval");
+
+ i = 0;
+ err = bpf_map_lookup_elem(data_fd, &i, &val);
+ ASSERT_OK(err, "fentry count");
+ ASSERT_EQ(val, 1, "fentry count");
+
+out:
+ bpf_link__destroy(fentry_link);
+ bpf_object__close(fentry_obj);
+ bpf_object__close(tgt_obj);
+}
+
#define JMP_TABLE "/sys/fs/bpf/jmp_table"
static int poke_thread_exit;
@@ -1759,6 +1867,8 @@ void test_tailcalls(void)
test_tailcall_bpf2bpf_fentry_fexit();
if (test__start_subtest("tailcall_bpf2bpf_fentry_entry"))
test_tailcall_bpf2bpf_fentry_entry();
+ if (test__start_subtest("tailcall_fentry_tailcallee"))
+ test_tailcall_fentry_tailcallee();
if (test__start_subtest("tailcall_poke"))
test_tailcall_poke();
if (test__start_subtest("tailcall_bpf2bpf_hierarchy_1"))
diff --git a/tools/testing/selftests/bpf/progs/tailcall_fentry_probe.c b/tools/testing/selftests/bpf/progs/tailcall_fentry_probe.c
new file mode 100644
index 000000000000..b784aeffb316
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/tailcall_fentry_probe.c
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "vmlinux.h"
+
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+int count = 0;
+
+SEC("fentry/callee")
+int BPF_PROG(fentry_callee, struct sk_buff *skb)
+{
+ count++;
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/tailcall_fentry_target.c b/tools/testing/selftests/bpf/progs/tailcall_fentry_target.c
new file mode 100644
index 000000000000..46da06ce323c
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/tailcall_fentry_target.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+
+#include <bpf/bpf_helpers.h>
+#include "bpf_legacy.h"
+
+struct {
+ __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
+ __uint(max_entries, 1);
+ __uint(key_size, sizeof(__u32));
+ __uint(value_size, sizeof(__u32));
+} jmp_table SEC(".maps");
+
+SEC("tc")
+int callee(struct __sk_buff *skb)
+{
+ return 7;
+}
+
+SEC("tc")
+int entry(struct __sk_buff *skb)
+{
+ bpf_tail_call_static(skb, &jmp_table, 0);
+ return 0;
+}
+
+char __license[] SEC("license") = "GPL";
--
2.43.0
prev parent reply other threads:[~2026-03-27 14:16 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-27 14:16 [PATCH bpf-next 0/2] bpf: enable x86 fentry on tail-called programs Takeru Hayasaka
2026-03-27 14:16 ` [PATCH bpf-next 1/2] bpf, x86: patch tail-call fentry slot on non-IBT JITs Takeru Hayasaka
2026-03-27 14:24 ` Alexei Starovoitov
2026-03-27 15:12 ` Takeru Hayasaka
2026-03-27 15:21 ` Alexei Starovoitov
2026-03-27 15:44 ` Takeru Hayasaka
2026-03-27 15:58 ` Alexei Starovoitov
2026-03-27 16:06 ` Takeru Hayasaka
2026-03-27 16:09 ` Alexei Starovoitov
2026-03-27 16:30 ` Takeru Hayasaka
2026-03-30 9:07 ` Leon Hwang
2026-03-30 16:46 ` Takeru Hayasaka
2026-03-31 2:24 ` Leon Hwang
2026-03-31 4:53 ` Takeru Hayasaka
2026-03-27 14:16 ` Takeru Hayasaka [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=20260327141616.1961457-3-hayatake396@gmail.com \
--to=hayatake396@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=x86@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
all inboxes | Powered by JetHome®