-
Notifications
You must be signed in to change notification settings - Fork 120
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 <[email protected]>
- Loading branch information
Showing
5 changed files
with
385 additions
and
10 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
tools/testing/selftests/bpf/prog_tests/compute_live_registers.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
#include "compute_live_registers.skel.h" | ||
#include "test_progs.h" | ||
|
||
void test_compute_live_registers(void) | ||
{ | ||
RUN_TESTS(compute_live_registers); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
362 changes: 362 additions & 0 deletions
362
tools/testing/selftests/bpf/progs/compute_live_registers.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,362 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
|
||
#include <linux/bpf.h> | ||
#include <bpf/bpf_helpers.h> | ||
#include "../../../include/linux/filter.h" | ||
#include "bpf_arena_common.h" | ||
#include "bpf_misc.h" | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_ARRAY); | ||
__uint(max_entries, 1); | ||
__type(key, __u32); | ||
__type(value, __u64); | ||
} test_map SEC(".maps"); | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_ARENA); | ||
__uint(map_flags, BPF_F_MMAPABLE); | ||
__uint(max_entries, 1); | ||
} arena SEC(".maps"); | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg(" 0: .......... (b7) r0 = 42") | ||
__msg(" 1: 0......... (bf) r1 = r0") | ||
__msg(" 2: .1........ (bf) r2 = r1") | ||
__msg(" 3: ..2....... (bf) r3 = r2") | ||
__msg(" 4: ...3...... (bf) r4 = r3") | ||
__msg(" 5: ....4..... (bf) r5 = r4") | ||
__msg(" 6: .....5.... (bf) r6 = r5") | ||
__msg(" 7: ......6... (bf) r7 = r6") | ||
__msg(" 8: .......7.. (bf) r8 = r7") | ||
__msg(" 9: ........8. (bf) r9 = r8") | ||
__msg("10: .........9 (bf) r0 = r9") | ||
__msg("11: 0......... (95) exit") | ||
__naked void assign_chain(void) | ||
{ | ||
asm volatile ( | ||
"r0 = 42;" | ||
"r1 = r0;" | ||
"r2 = r1;" | ||
"r3 = r2;" | ||
"r4 = r3;" | ||
"r5 = r4;" | ||
"r6 = r5;" | ||
"r7 = r6;" | ||
"r8 = r7;" | ||
"r9 = r8;" | ||
"r0 = r9;" | ||
"exit;" | ||
::: __clobber_all); | ||
} | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("0: .......... (b7) r1 = 7") | ||
__msg("1: .1........ (07) r1 += 7") | ||
__msg("2: .......... (b7) r2 = 7") | ||
__msg("3: ..2....... (b7) r3 = 42") | ||
__msg("4: ..23...... (0f) r2 += r3") | ||
__msg("5: .......... (b7) r0 = 0") | ||
__msg("6: 0......... (95) exit") | ||
__naked void arithmetics(void) | ||
{ | ||
asm volatile ( | ||
"r1 = 7;" | ||
"r1 += 7;" | ||
"r2 = 7;" | ||
"r3 = 42;" | ||
"r2 += r3;" | ||
"r0 = 0;" | ||
"exit;" | ||
::: __clobber_all); | ||
} | ||
|
||
#ifdef CAN_USE_BPF_ST | ||
SEC("socket") | ||
__log_level(2) | ||
__msg(" 1: .1........ (07) r1 += -8") | ||
__msg(" 2: .1........ (7a) *(u64 *)(r1 +0) = 7") | ||
__msg(" 3: .1........ (b7) r2 = 42") | ||
__msg(" 4: .12....... (7b) *(u64 *)(r1 +0) = r2") | ||
__msg(" 5: .12....... (7b) *(u64 *)(r1 +0) = r2") | ||
__msg(" 6: .......... (b7) r0 = 0") | ||
__naked void store(void) | ||
{ | ||
asm volatile ( | ||
"r1 = r10;" | ||
"r1 += -8;" | ||
"*(u64 *)(r1 +0) = 7;" | ||
"r2 = 42;" | ||
"*(u64 *)(r1 +0) = r2;" | ||
"*(u64 *)(r1 +0) = r2;" | ||
"r0 = 0;" | ||
"exit;" | ||
::: __clobber_all); | ||
} | ||
#endif | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("1: ....4..... (07) r4 += -8") | ||
__msg("2: ....4..... (79) r5 = *(u64 *)(r4 +0)") | ||
__msg("3: ....45.... (07) r4 += -8") | ||
__naked void load(void) | ||
{ | ||
asm volatile ( | ||
"r4 = r10;" | ||
"r4 += -8;" | ||
"r5 = *(u64 *)(r4 +0);" | ||
"r4 += -8;" | ||
"r0 = r5;" | ||
"exit;" | ||
::: __clobber_all); | ||
} | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("0: .1........ (61) r2 = *(u32 *)(r1 +0)") | ||
__msg("1: ..2....... (d4) r2 = le64 r2") | ||
__msg("2: ..2....... (bf) r0 = r2") | ||
__naked void endian(void) | ||
{ | ||
asm volatile ( | ||
"r2 = *(u32 *)(r1 +0);" | ||
"r2 = le64 r2;" | ||
"r0 = r2;" | ||
"exit;" | ||
::: __clobber_all); | ||
} | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg(" 8: 0......... (b7) r1 = 1") | ||
__msg(" 9: 01........ (db) r1 = atomic64_fetch_add((u64 *)(r0 +0), r1)") | ||
__msg("10: 01........ (c3) lock *(u32 *)(r0 +0) += r1") | ||
__msg("11: 01........ (db) r1 = atomic64_xchg((u64 *)(r0 +0), r1)") | ||
__msg("12: 01........ (bf) r2 = r0") | ||
__msg("13: .12....... (bf) r0 = r1") | ||
__msg("14: .12....... (db) r0 = atomic64_cmpxchg((u64 *)(r2 +0), r0, r1)") | ||
__naked void atomic(void) | ||
{ | ||
asm volatile ( | ||
"r2 = r10;" | ||
"r2 += -8;" | ||
"r1 = 0;" | ||
"*(u64 *)(r2 +0) = r1;" | ||
"r1 = %[test_map] ll;" | ||
"call %[bpf_map_lookup_elem];" | ||
"if r0 == 0 goto 1f;" | ||
"r1 = 1;" | ||
"r1 = atomic_fetch_add((u64 *)(r0 +0), r1);" | ||
"lock *(u32 *)(r0 +0) += r1;" | ||
"r1 = xchg_64(r0 + 0, r1);" | ||
"r2 = r0;" | ||
"r0 = r1;" | ||
"r0 = cmpxchg_64(r2 + 0, r0, r1);" | ||
"1: exit;" | ||
: | ||
: __imm(bpf_map_lookup_elem), | ||
__imm_addr(test_map) | ||
: __clobber_all); | ||
} | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("5: .12345.7.. (85) call bpf_trace_printk#6") | ||
__msg("6: 0......7.. (0f) r0 += r7") | ||
__naked void regular_call(void) | ||
{ | ||
asm volatile ( | ||
"r7 = 1;" | ||
"r1 = r10;" | ||
"r1 += -8;" | ||
"*(u8 *)(r1 +0) = 0;" | ||
"r2 = 1;" | ||
"call %[bpf_trace_printk];" | ||
"r0 += r7;" | ||
"exit;" | ||
: | ||
: __imm(bpf_trace_printk) | ||
: __clobber_all); | ||
} | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("2: 012....... (25) if r1 > 0x7 goto pc+1") | ||
__msg("3: ..2....... (bf) r0 = r2") | ||
__naked void if1(void) | ||
{ | ||
asm volatile ( | ||
"r0 = 1;" | ||
"r2 = 2;" | ||
"if r1 > 0x7 goto +1;" | ||
"r0 = r2;" | ||
"exit;" | ||
::: __clobber_all); | ||
} | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("3: 0123...... (2d) if r1 > r3 goto pc+1") | ||
__msg("4: ..2....... (bf) r0 = r2") | ||
__naked void if2(void) | ||
{ | ||
asm volatile ( | ||
"r0 = 1;" | ||
"r2 = 2;" | ||
"r3 = 7;" | ||
"if r1 > r3 goto +1;" | ||
"r0 = r2;" | ||
"exit;" | ||
::: __clobber_all); | ||
} | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("0: .......... (b7) r1 = 0") | ||
__msg("1: .1........ (b7) r2 = 7") | ||
__msg("2: .12....... (25) if r1 > 0x7 goto pc+4") | ||
__msg("3: .12....... (07) r1 += 1") | ||
__msg("4: .12....... (27) r2 *= 2") | ||
__msg("5: .12....... (05) goto pc+0") | ||
__msg("6: .12....... (05) goto pc-5") | ||
__msg("7: .......... (b7) r0 = 0") | ||
__msg("8: 0......... (95) exit") | ||
__naked void loop(void) | ||
{ | ||
asm volatile ( | ||
"r1 = 0;" | ||
"r2 = 7;" | ||
"if r1 > 0x7 goto +4;" | ||
"r1 += 1;" | ||
"r2 *= 2;" | ||
"goto +0;" | ||
"goto -5;" | ||
"r0 = 0;" | ||
"exit;" | ||
: | ||
: __imm(bpf_trace_printk) | ||
: __clobber_all); | ||
} | ||
|
||
#ifdef CAN_USE_GOTOL | ||
SEC("socket") | ||
__log_level(2) | ||
__msg("2: .123...... (25) if r1 > 0x7 goto pc+2") | ||
__msg("3: ..2....... (bf) r0 = r2") | ||
__msg("4: 0......... (06) gotol pc+1") | ||
__msg("5: ...3...... (bf) r0 = r3") | ||
__msg("6: 0......... (95) exit") | ||
__naked void gotol(void) | ||
{ | ||
asm volatile ( | ||
"r2 = 42;" | ||
"r3 = 24;" | ||
"if r1 > 0x7 goto +2;" | ||
"r0 = r2;" | ||
"gotol +1;" | ||
"r0 = r3;" | ||
"exit;" | ||
: | ||
: __imm(bpf_trace_printk) | ||
: __clobber_all); | ||
} | ||
#endif | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("0: 0......... (b7) r1 = 1") | ||
__msg("1: 01........ (e5) may_goto pc+1") | ||
__msg("2: 0......... (05) goto pc-3") | ||
__msg("3: .1........ (bf) r0 = r1") | ||
__msg("4: 0......... (95) exit") | ||
__naked void may_goto(void) | ||
{ | ||
asm volatile ( | ||
"1: r1 = 1;" | ||
".8byte %[may_goto];" | ||
"goto 1b;" | ||
"r0 = r1;" | ||
"exit;" | ||
: | ||
: __imm(bpf_get_smp_processor_id), | ||
__imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0)) | ||
: __clobber_all); | ||
} | ||
|
||
SEC("socket") | ||
__log_level(2) | ||
__msg("1: 0......... (18) r2 = 0x7") | ||
__msg("3: 0.2....... (0f) r0 += r2") | ||
__naked void ldimm64(void) | ||
{ | ||
asm volatile ( | ||
"r0 = 0;" | ||
"r2 = 0x7 ll;" | ||
"r0 += r2;" | ||
"exit;" | ||
: | ||
:: __clobber_all); | ||
} | ||
|
||
/* No rules specific for LD_ABS/LD_IND, default behaviour kicks in */ | ||
SEC("socket") | ||
__log_level(2) | ||
__msg("2: 0123456789 (30) r0 = *(u8 *)skb[42]") | ||
__msg("3: 012.456789 (0f) r7 += r0") | ||
__msg("4: 012.456789 (b7) r3 = 42") | ||
__msg("5: 0123456789 (50) r0 = *(u8 *)skb[r3 + 0]") | ||
__msg("6: 0......7.. (0f) r7 += r0") | ||
__naked void ldabs(void) | ||
{ | ||
asm volatile ( | ||
"r6 = r1;" | ||
"r7 = 0;" | ||
"r0 = *(u8 *)skb[42];" | ||
"r7 += r0;" | ||
"r3 = 42;" | ||
"r0 = *(u8 *)skb[r3];" | ||
"r7 += r0;" | ||
"r0 = r7;" | ||
"exit;" | ||
: | ||
:: __clobber_all); | ||
} | ||
|
||
|
||
#ifdef __BPF_FEATURE_ADDR_SPACE_CAST | ||
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid") | ||
__log_level(2) | ||
__msg(" 6: .12345.... (85) call bpf_arena_alloc_pages") | ||
__msg(" 7: 0......... (bf) r1 = addr_space_cast(r0, 0, 1)") | ||
__msg(" 8: .1........ (b7) r2 = 42") | ||
__naked void addr_space_cast(void) | ||
{ | ||
asm volatile ( | ||
"r1 = %[arena] ll;" | ||
"r2 = 0;" | ||
"r3 = 1;" | ||
"r4 = 0;" | ||
"r5 = 0;" | ||
"call %[bpf_arena_alloc_pages];" | ||
"r1 = addr_space_cast(r0, 0, 1);" | ||
"r2 = 42;" | ||
"*(u64 *)(r1 +0) = r2;" | ||
"r0 = 0;" | ||
"exit;" | ||
: | ||
: __imm(bpf_arena_alloc_pages), | ||
__imm_addr(arena) | ||
: __clobber_all); | ||
} | ||
#endif | ||
|
||
/* to retain debug info for BTF generation */ | ||
void kfunc_root(void) | ||
{ | ||
bpf_arena_alloc_pages(0, 0, 0, 0, 0); | ||
} | ||
|
||
char _license[] SEC("license") = "GPL"; |
Oops, something went wrong.