xref: /linux/tools/testing/selftests/bpf/progs/arena_list.c (revision 6f7e6393d1ce636bb7ec77a7fe7b77458fddf701)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3 #define BPF_NO_KFUNC_PROTOTYPES
4 #include <vmlinux.h>
5 #include <bpf/bpf_helpers.h>
6 #include <bpf/bpf_tracing.h>
7 #include <bpf/bpf_core_read.h>
8 #include "bpf_experimental.h"
9 
10 struct {
11 	__uint(type, BPF_MAP_TYPE_ARENA);
12 	__uint(map_flags, BPF_F_MMAPABLE);
13 	__uint(max_entries, 100); /* number of pages */
14 #ifdef __TARGET_ARCH_arm64
15 	__ulong(map_extra, 0x1ull << 32); /* start of mmap() region */
16 #else
17 	__ulong(map_extra, 0x1ull << 44); /* start of mmap() region */
18 #endif
19 } arena SEC(".maps");
20 
21 #include "bpf_arena_alloc.h"
22 #include "bpf_arena_list.h"
23 
24 struct elem {
25 	struct arena_list_node node;
26 	__u64 value;
27 };
28 
29 struct arena_list_head __arena *list_head;
30 int list_sum;
31 int cnt;
32 bool skip = false;
33 const volatile bool nonsleepable = false;
34 
35 #ifdef __BPF_FEATURE_ADDR_SPACE_CAST
36 long __arena arena_sum;
37 int __arena test_val = 1;
38 struct arena_list_head __arena global_head;
39 #else
40 long arena_sum SEC(".addr_space.1");
41 int test_val SEC(".addr_space.1");
42 #endif
43 
44 int zero;
45 
46 void bpf_rcu_read_lock(void) __ksym;
47 void bpf_rcu_read_unlock(void) __ksym;
48 
49 SEC("syscall")
50 int arena_list_add(void *ctx)
51 {
52 #ifdef __BPF_FEATURE_ADDR_SPACE_CAST
53 	__u64 i;
54 
55 	list_head = &global_head;
56 
57 	for (i = zero; i < cnt && can_loop; i++) {
58 		struct elem __arena *n = bpf_alloc(sizeof(*n));
59 
60 		test_val++;
61 		n->value = i;
62 		arena_sum += i;
63 		list_add_head(&n->node, list_head);
64 	}
65 #else
66 	skip = true;
67 #endif
68 	return 0;
69 }
70 
71 SEC("syscall")
72 int arena_list_del(void *ctx)
73 {
74 #ifdef __BPF_FEATURE_ADDR_SPACE_CAST
75 	struct elem __arena *n;
76 	int sum = 0;
77 
78 	/* Take rcu_read_lock to test non-sleepable context */
79 	if (nonsleepable)
80 		bpf_rcu_read_lock();
81 
82 	arena_sum = 0;
83 	list_for_each_entry(n, list_head, node) {
84 		sum += n->value;
85 		arena_sum += n->value;
86 		list_del(&n->node);
87 		bpf_free(n);
88 	}
89 	list_sum = sum;
90 
91 	if (nonsleepable)
92 		bpf_rcu_read_unlock();
93 #else
94 	skip = true;
95 #endif
96 	return 0;
97 }
98 
99 char _license[] SEC("license") = "GPL";
100