Skip to content

Commit 4bebb99

Browse files
author
Alexei Starovoitov
committed
Merge branch 'bpf-arm64-add-fsession-support'
Leon Hwang says: ==================== Similar to commit 98770bd ("bpf,x86: add fsession support for x86_64"), add fsession support on arm64. Patch #1 adds bpf_jit_supports_fsession() to prevent fsession loading on architectures that do not implement fsession support. Patch #2 implements fsession support in the arm64 BPF JIT trampoline. Patch #3 enables the relevant selftests on arm64, including get_func_ip, and get_func_args. All enabled tests pass on arm64: cd tools/testing/selftests/bpf ./test_progs -t fsession #136/1 fsession_test/fsession_test:OK #136/2 fsession_test/fsession_reattach:OK #136/3 fsession_test/fsession_cookie:OK #136 fsession_test:OK Summary: 1/3 PASSED, 0 SKIPPED, 0 FAILED ./test_progs -t get_func #138 get_func_args_test:OK #139 get_func_ip_test:OK Summary: 2/0 PASSED, 0 SKIPPED, 0 FAILED Changes: v4 -> v5: * Address comment from Alexei: * Rename helper bpf_link_prog_session_cookie() to bpf_prog_calls_session_cookie(). * v4: https://lore.kernel.org/bpf/20260129154953.66915-1-leon.hwang@linux.dev/ v3 -> v4: * Add a log when !bpf_jit_supports_fsession() in patch #1 (per AI). * v3: https://lore.kernel.org/bpf/20260129142536.48637-1-leon.hwang@linux.dev/ v2 -> v3: * Fix typo in subject and patch message of patch #1 (per AI and Chris). * Collect Acked-by, and Tested-by from Puranjay, thanks. * v2: https://lore.kernel.org/bpf/20260128150112.8873-1-leon.hwang@linux.dev/ v1 -> v2: * Add bpf_jit_supports_fsession(). * v1: https://lore.kernel.org/bpf/20260127163344.92819-1-leon.hwang@linux.dev/ ==================== Link: https://patch.msgid.link/20260131144950.16294-1-leon.hwang@linux.dev Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2 parents f0b5b3d + 7f10da2 commit 4bebb99

9 files changed

Lines changed: 110 additions & 20 deletions

File tree

arch/arm64/net/bpf_jit_comp.c

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,6 +2510,12 @@ static bool is_struct_ops_tramp(const struct bpf_tramp_links *fentry_links)
25102510
fentry_links->links[0]->link.type == BPF_LINK_TYPE_STRUCT_OPS;
25112511
}
25122512

2513+
static void store_func_meta(struct jit_ctx *ctx, u64 func_meta, int func_meta_off)
2514+
{
2515+
emit_a64_mov_i64(A64_R(10), func_meta, ctx);
2516+
emit(A64_STR64I(A64_R(10), A64_SP, func_meta_off), ctx);
2517+
}
2518+
25132519
/* Based on the x86's implementation of arch_prepare_bpf_trampoline().
25142520
*
25152521
* bpf prog and function entry before bpf trampoline hooked:
@@ -2533,7 +2539,7 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
25332539
int regs_off;
25342540
int retval_off;
25352541
int bargs_off;
2536-
int nfuncargs_off;
2542+
int func_meta_off;
25372543
int ip_off;
25382544
int run_ctx_off;
25392545
int oargs_off;
@@ -2544,6 +2550,9 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
25442550
bool save_ret;
25452551
__le32 **branches = NULL;
25462552
bool is_struct_ops = is_struct_ops_tramp(fentry);
2553+
int cookie_off, cookie_cnt, cookie_bargs_off;
2554+
int fsession_cnt = bpf_fsession_cnt(tlinks);
2555+
u64 func_meta;
25472556

25482557
/* trampoline stack layout:
25492558
* [ parent ip ]
@@ -2562,10 +2571,14 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
25622571
* [ ... ]
25632572
* SP + bargs_off [ arg reg 1 ] for bpf
25642573
*
2565-
* SP + nfuncargs_off [ arg regs count ]
2574+
* SP + func_meta_off [ regs count, etc ]
25662575
*
25672576
* SP + ip_off [ traced function ] BPF_TRAMP_F_IP_ARG flag
25682577
*
2578+
* [ stack cookie N ]
2579+
* [ ... ]
2580+
* SP + cookie_off [ stack cookie 1 ]
2581+
*
25692582
* SP + run_ctx_off [ bpf_tramp_run_ctx ]
25702583
*
25712584
* [ stack arg N ]
@@ -2582,13 +2595,18 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
25822595
/* room for bpf_tramp_run_ctx */
25832596
stack_size += round_up(sizeof(struct bpf_tramp_run_ctx), 8);
25842597

2598+
cookie_off = stack_size;
2599+
/* room for session cookies */
2600+
cookie_cnt = bpf_fsession_cookie_cnt(tlinks);
2601+
stack_size += cookie_cnt * 8;
2602+
25852603
ip_off = stack_size;
25862604
/* room for IP address argument */
25872605
if (flags & BPF_TRAMP_F_IP_ARG)
25882606
stack_size += 8;
25892607

2590-
nfuncargs_off = stack_size;
2591-
/* room for args count */
2608+
func_meta_off = stack_size;
2609+
/* room for function metadata, such as regs count */
25922610
stack_size += 8;
25932611

25942612
bargs_off = stack_size;
@@ -2646,9 +2664,9 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
26462664
emit(A64_STR64I(A64_R(10), A64_SP, ip_off), ctx);
26472665
}
26482666

2649-
/* save arg regs count*/
2650-
emit(A64_MOVZ(1, A64_R(10), nfuncargs, 0), ctx);
2651-
emit(A64_STR64I(A64_R(10), A64_SP, nfuncargs_off), ctx);
2667+
/* save function metadata */
2668+
func_meta = nfuncargs;
2669+
store_func_meta(ctx, func_meta, func_meta_off);
26522670

26532671
/* save args for bpf */
26542672
save_args(ctx, bargs_off, oargs_off, m, a, false);
@@ -2666,10 +2684,27 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
26662684
emit_call((const u64)__bpf_tramp_enter, ctx);
26672685
}
26682686

2669-
for (i = 0; i < fentry->nr_links; i++)
2687+
if (fsession_cnt) {
2688+
/* clear all the session cookies' value */
2689+
emit(A64_MOVZ(1, A64_R(10), 0, 0), ctx);
2690+
for (int i = 0; i < cookie_cnt; i++)
2691+
emit(A64_STR64I(A64_R(10), A64_SP, cookie_off + 8 * i), ctx);
2692+
/* clear the return value to make sure fentry always gets 0 */
2693+
emit(A64_STR64I(A64_R(10), A64_SP, retval_off), ctx);
2694+
}
2695+
2696+
cookie_bargs_off = (bargs_off - cookie_off) / 8;
2697+
for (i = 0; i < fentry->nr_links; i++) {
2698+
if (bpf_prog_calls_session_cookie(fentry->links[i])) {
2699+
u64 meta = func_meta | (cookie_bargs_off << BPF_TRAMP_COOKIE_INDEX_SHIFT);
2700+
2701+
store_func_meta(ctx, meta, func_meta_off);
2702+
cookie_bargs_off--;
2703+
}
26702704
invoke_bpf_prog(ctx, fentry->links[i], bargs_off,
26712705
retval_off, run_ctx_off,
26722706
flags & BPF_TRAMP_F_RET_FENTRY_RET);
2707+
}
26732708

26742709
if (fmod_ret->nr_links) {
26752710
branches = kcalloc(fmod_ret->nr_links, sizeof(__le32 *),
@@ -2701,9 +2736,22 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
27012736
*branches[i] = cpu_to_le32(A64_CBNZ(1, A64_R(10), offset));
27022737
}
27032738

2704-
for (i = 0; i < fexit->nr_links; i++)
2739+
/* set the "is_return" flag for fsession */
2740+
func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
2741+
if (fsession_cnt)
2742+
store_func_meta(ctx, func_meta, func_meta_off);
2743+
2744+
cookie_bargs_off = (bargs_off - cookie_off) / 8;
2745+
for (i = 0; i < fexit->nr_links; i++) {
2746+
if (bpf_prog_calls_session_cookie(fexit->links[i])) {
2747+
u64 meta = func_meta | (cookie_bargs_off << BPF_TRAMP_COOKIE_INDEX_SHIFT);
2748+
2749+
store_func_meta(ctx, meta, func_meta_off);
2750+
cookie_bargs_off--;
2751+
}
27052752
invoke_bpf_prog(ctx, fexit->links[i], bargs_off, retval_off,
27062753
run_ctx_off, false);
2754+
}
27072755

27082756
if (flags & BPF_TRAMP_F_CALL_ORIG) {
27092757
im->ip_epilogue = ctx->ro_image + ctx->idx;
@@ -2753,6 +2801,11 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
27532801
return ctx->idx;
27542802
}
27552803

2804+
bool bpf_jit_supports_fsession(void)
2805+
{
2806+
return true;
2807+
}
2808+
27562809
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
27572810
struct bpf_tramp_links *tlinks, void *func_addr)
27582811
{

arch/x86/net/bpf_jit_comp.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4112,3 +4112,8 @@ bool bpf_jit_supports_timed_may_goto(void)
41124112
{
41134113
return true;
41144114
}
4115+
4116+
bool bpf_jit_supports_fsession(void)
4117+
{
4118+
return true;
4119+
}

include/linux/bpf.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2196,13 +2196,18 @@ static inline int bpf_fsession_cnt(struct bpf_tramp_links *links)
21962196
return cnt;
21972197
}
21982198

2199+
static inline bool bpf_prog_calls_session_cookie(struct bpf_tramp_link *link)
2200+
{
2201+
return link->link.prog->call_session_cookie;
2202+
}
2203+
21992204
static inline int bpf_fsession_cookie_cnt(struct bpf_tramp_links *links)
22002205
{
22012206
struct bpf_tramp_links fentries = links[BPF_TRAMP_FENTRY];
22022207
int cnt = 0;
22032208

22042209
for (int i = 0; i < links[BPF_TRAMP_FENTRY].nr_links; i++) {
2205-
if (fentries.links[i]->link.prog->call_session_cookie)
2210+
if (bpf_prog_calls_session_cookie(fentries.links[i]))
22062211
cnt++;
22072212
}
22082213

include/linux/filter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,7 @@ bool bpf_jit_supports_arena(void);
11671167
bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena);
11681168
bool bpf_jit_supports_private_stack(void);
11691169
bool bpf_jit_supports_timed_may_goto(void);
1170+
bool bpf_jit_supports_fsession(void);
11701171
u64 bpf_arch_uaddress_limit(void);
11711172
void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie);
11721173
u64 arch_bpf_timed_may_goto(void);

kernel/bpf/core.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3144,6 +3144,11 @@ bool __weak bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena)
31443144
return false;
31453145
}
31463146

3147+
bool __weak bpf_jit_supports_fsession(void)
3148+
{
3149+
return false;
3150+
}
3151+
31473152
u64 __weak bpf_arch_uaddress_limit(void)
31483153
{
31493154
#if defined(CONFIG_64BIT) && defined(CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE)

kernel/bpf/verifier.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24828,6 +24828,11 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
2482824828
case BPF_TRACE_FENTRY:
2482924829
case BPF_TRACE_FEXIT:
2483024830
case BPF_TRACE_FSESSION:
24831+
if (prog->expected_attach_type == BPF_TRACE_FSESSION &&
24832+
!bpf_jit_supports_fsession()) {
24833+
bpf_log(log, "JIT does not support fsession\n");
24834+
return -EOPNOTSUPP;
24835+
}
2483124836
if (!btf_type_is_func(t)) {
2483224837
bpf_log(log, "attach_btf_id %u is not a function\n",
2483324838
btf_id);

tools/testing/selftests/bpf/prog_tests/fsession_test.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,16 @@ static void test_fsession_basic(void)
2929
struct fsession_test *skel = NULL;
3030
int err;
3131

32-
skel = fsession_test__open_and_load();
33-
if (!ASSERT_OK_PTR(skel, "fsession_test__open_and_load"))
32+
skel = fsession_test__open();
33+
if (!ASSERT_OK_PTR(skel, "fsession_test__open"))
34+
return;
35+
36+
err = fsession_test__load(skel);
37+
if (err == -EOPNOTSUPP) {
38+
test__skip();
39+
goto cleanup;
40+
}
41+
if (!ASSERT_OK(err, "fsession_test__load"))
3442
goto cleanup;
3543

3644
err = fsession_test__attach(skel);
@@ -47,8 +55,16 @@ static void test_fsession_reattach(void)
4755
struct fsession_test *skel = NULL;
4856
int err;
4957

50-
skel = fsession_test__open_and_load();
51-
if (!ASSERT_OK_PTR(skel, "fsession_test__open_and_load"))
58+
skel = fsession_test__open();
59+
if (!ASSERT_OK_PTR(skel, "fsession_test__open"))
60+
return;
61+
62+
err = fsession_test__load(skel);
63+
if (err == -EOPNOTSUPP) {
64+
test__skip();
65+
goto cleanup;
66+
}
67+
if (!ASSERT_OK(err, "fsession_test__load"))
5268
goto cleanup;
5369

5470
/* first attach */
@@ -94,6 +110,10 @@ static void test_fsession_cookie(void)
94110
bpf_program__set_autoload(skel->progs.test6, false);
95111

96112
err = fsession_test__load(skel);
113+
if (err == -EOPNOTSUPP) {
114+
test__skip();
115+
goto cleanup;
116+
}
97117
if (!ASSERT_OK(err, "fsession_test__load"))
98118
goto cleanup;
99119

@@ -111,10 +131,6 @@ static void test_fsession_cookie(void)
111131

112132
void test_fsession_test(void)
113133
{
114-
#if !defined(__x86_64__)
115-
test__skip();
116-
return;
117-
#endif
118134
if (test__start_subtest("fsession_test"))
119135
test_fsession_basic();
120136
if (test__start_subtest("fsession_reattach"))

tools/testing/selftests/bpf/progs/get_func_args_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ int BPF_PROG(tp_test2)
167167
}
168168

169169
__u64 test7_result = 0;
170-
#ifdef __TARGET_ARCH_x86
170+
#if defined(bpf_target_x86) || defined(bpf_target_arm64)
171171
SEC("fsession/bpf_fentry_test1")
172172
int BPF_PROG(test7)
173173
{

tools/testing/selftests/bpf/progs/get_func_ip_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ int BPF_URETPROBE(test8, int ret)
106106

107107
__u64 test9_entry_result = 0;
108108
__u64 test9_exit_result = 0;
109-
#ifdef __TARGET_ARCH_x86
109+
#if defined(bpf_target_x86) || defined(bpf_target_arm64)
110110
SEC("fsession/bpf_fentry_test1")
111111
int BPF_PROG(test9, int a)
112112
{

0 commit comments

Comments
 (0)