Skip to content

Commit 7fbe199

Browse files
committed
selftests/bpf: test cases for compute_live_registers()
Cover instructions from each kind: - assignment - arithmetic - store/load - endian conversion - atomics - branches, conditional branches, may_goto, calls - LD_ABS/LD_IND - address_space_cast Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
1 parent fda8adf commit 7fbe199

File tree

5 files changed

+384
-10
lines changed

5 files changed

+384
-10
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include "compute_live_registers.skel.h"
4+
#include "test_progs.h"
5+
6+
void test_compute_live_registers(void)
7+
{
8+
RUN_TESTS(compute_live_registers);
9+
}

tools/testing/selftests/bpf/progs/bpf_misc.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,16 @@
208208
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
209209
#endif
210210

211+
#if (defined(__TARGET_ARCH_arm64) || defined(__TARGET_ARCH_x86) || \
212+
(defined(__TARGET_ARCH_riscv) && __riscv_xlen == 64) || \
213+
defined(__TARGET_ARCH_arm) || defined(__TARGET_ARCH_s390) || \
214+
defined(__TARGET_ARCH_loongarch)) && \
215+
__clang_major__ >= 18
216+
#define CAN_USE_GOTOL
217+
#endif
218+
219+
#if _clang_major__ >= 18
220+
#define CAN_USE_BPF_ST
221+
#endif
222+
211223
#endif
Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/bpf.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include "../../../include/linux/filter.h"
6+
#include "bpf_arena_common.h"
7+
#include "bpf_misc.h"
8+
9+
struct {
10+
__uint(type, BPF_MAP_TYPE_ARRAY);
11+
__uint(max_entries, 1);
12+
__type(key, __u32);
13+
__type(value, __u64);
14+
} test_map SEC(".maps");
15+
16+
struct {
17+
__uint(type, BPF_MAP_TYPE_ARENA);
18+
__uint(map_flags, BPF_F_MMAPABLE);
19+
__uint(max_entries, 1);
20+
} arena SEC(".maps");
21+
22+
SEC("socket")
23+
__log_level(2)
24+
__msg(" 0: .......... (b7) r0 = 42")
25+
__msg(" 1: 0......... (bf) r1 = r0")
26+
__msg(" 2: .1........ (bf) r2 = r1")
27+
__msg(" 3: ..2....... (bf) r3 = r2")
28+
__msg(" 4: ...3...... (bf) r4 = r3")
29+
__msg(" 5: ....4..... (bf) r5 = r4")
30+
__msg(" 6: .....5.... (bf) r6 = r5")
31+
__msg(" 7: ......6... (bf) r7 = r6")
32+
__msg(" 8: .......7.. (bf) r8 = r7")
33+
__msg(" 9: ........8. (bf) r9 = r8")
34+
__msg("10: .........9 (bf) r0 = r9")
35+
__msg("11: 0......... (95) exit")
36+
__naked void assign_chain(void)
37+
{
38+
asm volatile (
39+
"r0 = 42;"
40+
"r1 = r0;"
41+
"r2 = r1;"
42+
"r3 = r2;"
43+
"r4 = r3;"
44+
"r5 = r4;"
45+
"r6 = r5;"
46+
"r7 = r6;"
47+
"r8 = r7;"
48+
"r9 = r8;"
49+
"r0 = r9;"
50+
"exit;"
51+
::: __clobber_all);
52+
}
53+
54+
SEC("socket")
55+
__log_level(2)
56+
__msg("0: .......... (b7) r1 = 7")
57+
__msg("1: .1........ (07) r1 += 7")
58+
__msg("2: .......... (b7) r2 = 7")
59+
__msg("3: ..2....... (b7) r3 = 42")
60+
__msg("4: ..23...... (0f) r2 += r3")
61+
__msg("5: .......... (b7) r0 = 0")
62+
__msg("6: 0......... (95) exit")
63+
__naked void arithmetics(void)
64+
{
65+
asm volatile (
66+
"r1 = 7;"
67+
"r1 += 7;"
68+
"r2 = 7;"
69+
"r3 = 42;"
70+
"r2 += r3;"
71+
"r0 = 0;"
72+
"exit;"
73+
::: __clobber_all);
74+
}
75+
76+
#ifdef CAN_USE_BPF_ST
77+
SEC("socket")
78+
__log_level(2)
79+
__msg(" 1: .1........ (07) r1 += -8")
80+
__msg(" 2: .1........ (7a) *(u64 *)(r1 +0) = 7")
81+
__msg(" 3: .1........ (b7) r2 = 42")
82+
__msg(" 4: .12....... (7b) *(u64 *)(r1 +0) = r2")
83+
__msg(" 5: .12....... (7b) *(u64 *)(r1 +0) = r2")
84+
__msg(" 6: .......... (b7) r0 = 0")
85+
__naked void store(void)
86+
{
87+
asm volatile (
88+
"r1 = r10;"
89+
"r1 += -8;"
90+
"*(u64 *)(r1 +0) = 7;"
91+
"r2 = 42;"
92+
"*(u64 *)(r1 +0) = r2;"
93+
"*(u64 *)(r1 +0) = r2;"
94+
"r0 = 0;"
95+
"exit;"
96+
::: __clobber_all);
97+
}
98+
#endif
99+
100+
SEC("socket")
101+
__log_level(2)
102+
__msg("1: ....4..... (07) r4 += -8")
103+
__msg("2: ....4..... (79) r5 = *(u64 *)(r4 +0)")
104+
__msg("3: ....45.... (07) r4 += -8")
105+
__naked void load(void)
106+
{
107+
asm volatile (
108+
"r4 = r10;"
109+
"r4 += -8;"
110+
"r5 = *(u64 *)(r4 +0);"
111+
"r4 += -8;"
112+
"r0 = r5;"
113+
"exit;"
114+
::: __clobber_all);
115+
}
116+
117+
SEC("socket")
118+
__log_level(2)
119+
__msg("0: .1........ (61) r2 = *(u32 *)(r1 +0)")
120+
__msg("1: ..2....... (d4) r2 = le64 r2")
121+
__msg("2: ..2....... (bf) r0 = r2")
122+
__naked void endian(void)
123+
{
124+
asm volatile (
125+
"r2 = *(u32 *)(r1 +0);"
126+
"r2 = le64 r2;"
127+
"r0 = r2;"
128+
"exit;"
129+
::: __clobber_all);
130+
}
131+
132+
SEC("socket")
133+
__log_level(2)
134+
__msg(" 8: 0......... (b7) r1 = 1")
135+
__msg(" 9: 01........ (db) r1 = atomic64_fetch_add((u64 *)(r0 +0), r1)")
136+
__msg("10: 01........ (c3) lock *(u32 *)(r0 +0) += r1")
137+
__msg("11: 01........ (db) r1 = atomic64_xchg((u64 *)(r0 +0), r1)")
138+
__msg("12: 01........ (bf) r2 = r0")
139+
__msg("13: .12....... (bf) r0 = r1")
140+
__msg("14: .12....... (db) r0 = atomic64_cmpxchg((u64 *)(r2 +0), r0, r1)")
141+
__naked void atomic(void)
142+
{
143+
asm volatile (
144+
"r2 = r10;"
145+
"r2 += -8;"
146+
"r1 = 0;"
147+
"*(u64 *)(r2 +0) = r1;"
148+
"r1 = %[test_map] ll;"
149+
"call %[bpf_map_lookup_elem];"
150+
"if r0 == 0 goto 1f;"
151+
"r1 = 1;"
152+
"r1 = atomic_fetch_add((u64 *)(r0 +0), r1);"
153+
"lock *(u32 *)(r0 +0) += r1;"
154+
"r1 = xchg_64(r0 + 0, r1);"
155+
"r2 = r0;"
156+
"r0 = r1;"
157+
"r0 = cmpxchg_64(r2 + 0, r0, r1);"
158+
"1: exit;"
159+
:
160+
: __imm(bpf_map_lookup_elem),
161+
__imm_addr(test_map)
162+
: __clobber_all);
163+
}
164+
165+
SEC("socket")
166+
__log_level(2)
167+
__msg("4: .12345.7.. (85) call bpf_trace_printk#6")
168+
__msg("5: 0......7.. (0f) r0 += r7")
169+
__naked void regular_call(void)
170+
{
171+
asm volatile (
172+
"r7 = 1;"
173+
"r1 = r10;"
174+
"r1 += -8;"
175+
"r2 = 1;"
176+
"call %[bpf_trace_printk];"
177+
"r0 += r7;"
178+
"exit;"
179+
:
180+
: __imm(bpf_trace_printk)
181+
: __clobber_all);
182+
}
183+
184+
SEC("socket")
185+
__log_level(2)
186+
__msg("2: 012....... (25) if r1 > 0x7 goto pc+1")
187+
__msg("3: ..2....... (bf) r0 = r2")
188+
__naked void if1(void)
189+
{
190+
asm volatile (
191+
"r0 = 1;"
192+
"r2 = 2;"
193+
"if r1 > 0x7 goto +1;"
194+
"r0 = r2;"
195+
"exit;"
196+
::: __clobber_all);
197+
}
198+
199+
SEC("socket")
200+
__log_level(2)
201+
__msg("3: 0123...... (2d) if r1 > r3 goto pc+1")
202+
__msg("4: ..2....... (bf) r0 = r2")
203+
__naked void if2(void)
204+
{
205+
asm volatile (
206+
"r0 = 1;"
207+
"r2 = 2;"
208+
"r3 = 7;"
209+
"if r1 > r3 goto +1;"
210+
"r0 = r2;"
211+
"exit;"
212+
::: __clobber_all);
213+
}
214+
215+
SEC("socket")
216+
__log_level(2)
217+
__msg("0: .......... (b7) r1 = 0")
218+
__msg("1: .1........ (b7) r2 = 7")
219+
__msg("2: .12....... (25) if r1 > 0x7 goto pc+4")
220+
__msg("3: .12....... (07) r1 += 1")
221+
__msg("4: .12....... (27) r2 *= 2")
222+
__msg("5: .12....... (05) goto pc+0")
223+
__msg("6: .12....... (05) goto pc-5")
224+
__msg("7: .......... (b7) r0 = 0")
225+
__msg("8: 0......... (95) exit")
226+
__naked void loop(void)
227+
{
228+
asm volatile (
229+
"r1 = 0;"
230+
"r2 = 7;"
231+
"if r1 > 0x7 goto +4;"
232+
"r1 += 1;"
233+
"r2 *= 2;"
234+
"goto +0;"
235+
"goto -5;"
236+
"r0 = 0;"
237+
"exit;"
238+
:
239+
: __imm(bpf_trace_printk)
240+
: __clobber_all);
241+
}
242+
243+
#ifdef CAN_USE_GOTOL
244+
SEC("socket")
245+
__log_level(2)
246+
__msg("2: .123...... (25) if r1 > 0x7 goto pc+2")
247+
__msg("3: ..2....... (bf) r0 = r2")
248+
__msg("4: 0......... (06) gotol pc+1")
249+
__msg("5: ...3...... (bf) r0 = r3")
250+
__msg("6: 0......... (95) exit")
251+
__naked void gotol(void)
252+
{
253+
asm volatile (
254+
"r2 = 42;"
255+
"r3 = 24;"
256+
"if r1 > 0x7 goto +2;"
257+
"r0 = r2;"
258+
"gotol +1;"
259+
"r0 = r3;"
260+
"exit;"
261+
:
262+
: __imm(bpf_trace_printk)
263+
: __clobber_all);
264+
}
265+
#endif
266+
267+
SEC("socket")
268+
__log_level(2)
269+
__msg("0: 0......... (b7) r1 = 1")
270+
__msg("1: 01........ (e5) may_goto pc+1")
271+
__msg("2: 0......... (05) goto pc-3")
272+
__msg("3: .1........ (bf) r0 = r1")
273+
__msg("4: 0......... (95) exit")
274+
__naked void may_goto(void)
275+
{
276+
asm volatile (
277+
"1: r1 = 1;"
278+
".8byte %[may_goto];"
279+
"goto 1b;"
280+
"r0 = r1;"
281+
"exit;"
282+
:
283+
: __imm(bpf_get_smp_processor_id),
284+
__imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0))
285+
: __clobber_all);
286+
}
287+
288+
SEC("socket")
289+
__log_level(2)
290+
__msg("1: 0......... (18) r2 = 0x7")
291+
__msg("3: 0.2....... (0f) r0 += r2")
292+
__naked void ldimm64(void)
293+
{
294+
asm volatile (
295+
"r0 = 0;"
296+
"r2 = 0x7 ll;"
297+
"r0 += r2;"
298+
"exit;"
299+
:
300+
:: __clobber_all);
301+
}
302+
303+
/* No rules specific for LD_ABS/LD_IND, default behaviour kicks in */
304+
SEC("socket")
305+
__log_level(2)
306+
__msg("2: 0123456789 (30) r0 = *(u8 *)skb[42]")
307+
__msg("3: 012.456789 (0f) r7 += r0")
308+
__msg("4: 012.456789 (b7) r3 = 42")
309+
__msg("5: 0123456789 (50) r0 = *(u8 *)skb[r3 + 0]")
310+
__msg("6: 0......7.. (0f) r7 += r0")
311+
__naked void ldabs(void)
312+
{
313+
asm volatile (
314+
"r6 = r1;"
315+
"r7 = 0;"
316+
"r0 = *(u8 *)skb[42];"
317+
"r7 += r0;"
318+
"r3 = 42;"
319+
"r0 = *(u8 *)skb[r3];"
320+
"r7 += r0;"
321+
"r0 = r7;"
322+
"exit;"
323+
:
324+
:: __clobber_all);
325+
}
326+
327+
328+
#ifdef __BPF_FEATURE_ADDR_SPACE_CAST
329+
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
330+
__log_level(2)
331+
__msg(" 6: .12345.... (85) call bpf_arena_alloc_pages")
332+
__msg(" 7: 0......... (bf) r1 = addr_space_cast(r0, 0, 1)")
333+
__msg(" 8: .1........ (b7) r2 = 42")
334+
__naked void addr_space_cast(void)
335+
{
336+
asm volatile (
337+
"r1 = %[arena] ll;"
338+
"r2 = 0;"
339+
"r3 = 1;"
340+
"r4 = 0;"
341+
"r5 = 0;"
342+
"call %[bpf_arena_alloc_pages];"
343+
"r1 = addr_space_cast(r0, 0, 1);"
344+
"r2 = 42;"
345+
"*(u64 *)(r1 +0) = r2;"
346+
"r0 = 0;"
347+
"exit;"
348+
:
349+
: __imm(bpf_arena_alloc_pages),
350+
__imm_addr(arena)
351+
: __clobber_all);
352+
}
353+
#endif
354+
355+
/* to retain debug info for BTF generation */
356+
void kfunc_root(void)
357+
{
358+
bpf_arena_alloc_pages(0, 0, 0, 0, 0);
359+
}
360+
361+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)