Skip to content

Commit 42fdbbd

Browse files
Martin KaFai LauAlexei Starovoitov
authored andcommitted
selftests/bpf: A pro/epilogue test when the main prog jumps back to the 1st insn
This patch adds a pro/epilogue test when the main prog has a goto insn that goes back to the very first instruction of the prog. It is to test the correctness of the adjust_jmp_off(prog, 0, delta) after the verifier has applied the prologue and/or epilogue patch. Acked-by: Eduard Zingerman <[email protected]> Signed-off-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent b191b0f commit 42fdbbd

File tree

2 files changed

+151
-0
lines changed

2 files changed

+151
-0
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <test_progs.h>
55
#include "pro_epilogue.skel.h"
66
#include "epilogue_tailcall.skel.h"
7+
#include "pro_epilogue_goto_start.skel.h"
78

89
struct st_ops_args {
910
__u64 a;
@@ -51,6 +52,7 @@ static void test_tailcall(void)
5152
void test_pro_epilogue(void)
5253
{
5354
RUN_TESTS(pro_epilogue);
55+
RUN_TESTS(pro_epilogue_goto_start);
5456
if (test__start_subtest("tailcall"))
5557
test_tailcall();
5658
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3+
4+
#include <vmlinux.h>
5+
#include <bpf/bpf_tracing.h>
6+
#include "bpf_misc.h"
7+
#include "../bpf_testmod/bpf_testmod.h"
8+
#include "../bpf_testmod/bpf_testmod_kfunc.h"
9+
10+
char _license[] SEC("license") = "GPL";
11+
12+
__success
13+
/* prologue */
14+
__xlated("0: r6 = *(u64 *)(r1 +0)")
15+
__xlated("1: r7 = *(u64 *)(r6 +0)")
16+
__xlated("2: r7 += 1000")
17+
__xlated("3: *(u64 *)(r6 +0) = r7")
18+
/* main prog */
19+
__xlated("4: if r1 == 0x0 goto pc+5")
20+
__xlated("5: if r1 == 0x1 goto pc+2")
21+
__xlated("6: r1 = 1")
22+
__xlated("7: goto pc-3")
23+
__xlated("8: r1 = 0")
24+
__xlated("9: goto pc-6")
25+
__xlated("10: r0 = 0")
26+
__xlated("11: exit")
27+
SEC("struct_ops/test_prologue_goto_start")
28+
__naked int test_prologue_goto_start(void)
29+
{
30+
asm volatile (
31+
"if r1 == 0 goto +5;"
32+
"if r1 == 1 goto +2;"
33+
"r1 = 1;"
34+
"goto -3;"
35+
"r1 = 0;"
36+
"goto -6;"
37+
"r0 = 0;"
38+
"exit;"
39+
::: __clobber_all);
40+
}
41+
42+
__success
43+
/* save __u64 *ctx to stack */
44+
__xlated("0: *(u64 *)(r10 -8) = r1")
45+
/* main prog */
46+
__xlated("1: if r1 == 0x0 goto pc+5")
47+
__xlated("2: if r1 == 0x1 goto pc+2")
48+
__xlated("3: r1 = 1")
49+
__xlated("4: goto pc-3")
50+
__xlated("5: r1 = 0")
51+
__xlated("6: goto pc-6")
52+
__xlated("7: r0 = 0")
53+
/* epilogue */
54+
__xlated("8: r1 = *(u64 *)(r10 -8)")
55+
__xlated("9: r1 = *(u64 *)(r1 +0)")
56+
__xlated("10: r6 = *(u64 *)(r1 +0)")
57+
__xlated("11: r6 += 10000")
58+
__xlated("12: *(u64 *)(r1 +0) = r6")
59+
__xlated("13: r0 = r6")
60+
__xlated("14: r0 *= 2")
61+
__xlated("15: exit")
62+
SEC("struct_ops/test_epilogue_goto_start")
63+
__naked int test_epilogue_goto_start(void)
64+
{
65+
asm volatile (
66+
"if r1 == 0 goto +5;"
67+
"if r1 == 1 goto +2;"
68+
"r1 = 1;"
69+
"goto -3;"
70+
"r1 = 0;"
71+
"goto -6;"
72+
"r0 = 0;"
73+
"exit;"
74+
::: __clobber_all);
75+
}
76+
77+
__success
78+
/* prologue */
79+
__xlated("0: r6 = *(u64 *)(r1 +0)")
80+
__xlated("1: r7 = *(u64 *)(r6 +0)")
81+
__xlated("2: r7 += 1000")
82+
__xlated("3: *(u64 *)(r6 +0) = r7")
83+
/* save __u64 *ctx to stack */
84+
__xlated("4: *(u64 *)(r10 -8) = r1")
85+
/* main prog */
86+
__xlated("5: if r1 == 0x0 goto pc+5")
87+
__xlated("6: if r1 == 0x1 goto pc+2")
88+
__xlated("7: r1 = 1")
89+
__xlated("8: goto pc-3")
90+
__xlated("9: r1 = 0")
91+
__xlated("10: goto pc-6")
92+
__xlated("11: r0 = 0")
93+
/* epilogue */
94+
__xlated("12: r1 = *(u64 *)(r10 -8)")
95+
__xlated("13: r1 = *(u64 *)(r1 +0)")
96+
__xlated("14: r6 = *(u64 *)(r1 +0)")
97+
__xlated("15: r6 += 10000")
98+
__xlated("16: *(u64 *)(r1 +0) = r6")
99+
__xlated("17: r0 = r6")
100+
__xlated("18: r0 *= 2")
101+
__xlated("19: exit")
102+
SEC("struct_ops/test_pro_epilogue_goto_start")
103+
__naked int test_pro_epilogue_goto_start(void)
104+
{
105+
asm volatile (
106+
"if r1 == 0 goto +5;"
107+
"if r1 == 1 goto +2;"
108+
"r1 = 1;"
109+
"goto -3;"
110+
"r1 = 0;"
111+
"goto -6;"
112+
"r0 = 0;"
113+
"exit;"
114+
::: __clobber_all);
115+
}
116+
117+
SEC(".struct_ops.link")
118+
struct bpf_testmod_st_ops epilogue_goto_start = {
119+
.test_prologue = (void *)test_prologue_goto_start,
120+
.test_epilogue = (void *)test_epilogue_goto_start,
121+
.test_pro_epilogue = (void *)test_pro_epilogue_goto_start,
122+
};
123+
124+
SEC("syscall")
125+
__retval(0)
126+
int syscall_prologue_goto_start(void *ctx)
127+
{
128+
struct st_ops_args args = {};
129+
130+
return bpf_kfunc_st_ops_test_prologue(&args);
131+
}
132+
133+
SEC("syscall")
134+
__retval(20000) /* (EPILOGUE_A [10000]) * 2 */
135+
int syscall_epilogue_goto_start(void *ctx)
136+
{
137+
struct st_ops_args args = {};
138+
139+
return bpf_kfunc_st_ops_test_epilogue(&args);
140+
}
141+
142+
SEC("syscall")
143+
__retval(22000) /* (PROLOGUE_A [1000] + EPILOGUE_A [10000]) * 2 */
144+
int syscall_pro_epilogue_goto_start(void *ctx)
145+
{
146+
struct st_ops_args args = {};
147+
148+
return bpf_kfunc_st_ops_test_pro_epilogue(&args);
149+
}

0 commit comments

Comments
 (0)