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