1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (C) 2023. Huawei Technologies Co., Ltd */ 3 #include <vmlinux.h> 4 #include <bpf/bpf_tracing.h> 5 #include <bpf/bpf_helpers.h> 6 7 #include "bpf_experimental.h" 8 #include "bpf_misc.h" 9 10 #ifndef ARRAY_SIZE 11 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 12 #endif 13 14 struct generic_map_value { 15 void *data; 16 }; 17 18 char _license[] SEC("license") = "GPL"; 19 20 const unsigned int data_sizes[] = {8, 16, 32, 64, 96, 128, 192, 256, 512, 1024, 2048, 4096}; 21 const volatile unsigned int data_btf_ids[ARRAY_SIZE(data_sizes)] = {}; 22 23 int err = 0; 24 int pid = 0; 25 26 #define DEFINE_ARRAY_WITH_KPTR(_size) \ 27 struct bin_data_##_size { \ 28 char data[_size - sizeof(void *)]; \ 29 }; \ 30 struct map_value_##_size { \ 31 struct bin_data_##_size __kptr * data; \ 32 /* To emit BTF info for bin_data_xx */ \ 33 struct bin_data_##_size not_used; \ 34 }; \ 35 struct { \ 36 __uint(type, BPF_MAP_TYPE_ARRAY); \ 37 __type(key, int); \ 38 __type(value, struct map_value_##_size); \ 39 __uint(max_entries, 128); \ 40 } array_##_size SEC(".maps"); 41 42 static __always_inline void batch_alloc_free(struct bpf_map *map, unsigned int batch, 43 unsigned int idx) 44 { 45 struct generic_map_value *value; 46 unsigned int i, key; 47 void *old, *new; 48 49 for (i = 0; i < batch; i++) { 50 key = i; 51 value = bpf_map_lookup_elem(map, &key); 52 if (!value) { 53 err = 1; 54 return; 55 } 56 new = bpf_obj_new_impl(data_btf_ids[idx], NULL); 57 if (!new) { 58 err = 2; 59 return; 60 } 61 old = bpf_kptr_xchg(&value->data, new); 62 if (old) { 63 bpf_obj_drop(old); 64 err = 3; 65 return; 66 } 67 } 68 for (i = 0; i < batch; i++) { 69 key = i; 70 value = bpf_map_lookup_elem(map, &key); 71 if (!value) { 72 err = 4; 73 return; 74 } 75 old = bpf_kptr_xchg(&value->data, NULL); 76 if (!old) { 77 err = 5; 78 return; 79 } 80 bpf_obj_drop(old); 81 } 82 } 83 84 #define CALL_BATCH_ALLOC_FREE(size, batch, idx) \ 85 batch_alloc_free((struct bpf_map *)(&array_##size), batch, idx) 86 87 DEFINE_ARRAY_WITH_KPTR(8); 88 DEFINE_ARRAY_WITH_KPTR(16); 89 DEFINE_ARRAY_WITH_KPTR(32); 90 DEFINE_ARRAY_WITH_KPTR(64); 91 DEFINE_ARRAY_WITH_KPTR(96); 92 DEFINE_ARRAY_WITH_KPTR(128); 93 DEFINE_ARRAY_WITH_KPTR(192); 94 DEFINE_ARRAY_WITH_KPTR(256); 95 DEFINE_ARRAY_WITH_KPTR(512); 96 DEFINE_ARRAY_WITH_KPTR(1024); 97 DEFINE_ARRAY_WITH_KPTR(2048); 98 DEFINE_ARRAY_WITH_KPTR(4096); 99 100 SEC("fentry/" SYS_PREFIX "sys_nanosleep") 101 int test_bpf_mem_alloc_free(void *ctx) 102 { 103 if ((u32)bpf_get_current_pid_tgid() != pid) 104 return 0; 105 106 /* Alloc 128 8-bytes objects in batch to trigger refilling, 107 * then free 128 8-bytes objects in batch to trigger freeing. 108 */ 109 CALL_BATCH_ALLOC_FREE(8, 128, 0); 110 CALL_BATCH_ALLOC_FREE(16, 128, 1); 111 CALL_BATCH_ALLOC_FREE(32, 128, 2); 112 CALL_BATCH_ALLOC_FREE(64, 128, 3); 113 CALL_BATCH_ALLOC_FREE(96, 128, 4); 114 CALL_BATCH_ALLOC_FREE(128, 128, 5); 115 CALL_BATCH_ALLOC_FREE(192, 128, 6); 116 CALL_BATCH_ALLOC_FREE(256, 128, 7); 117 CALL_BATCH_ALLOC_FREE(512, 64, 8); 118 CALL_BATCH_ALLOC_FREE(1024, 32, 9); 119 CALL_BATCH_ALLOC_FREE(2048, 16, 10); 120 CALL_BATCH_ALLOC_FREE(4096, 8, 11); 121 122 return 0; 123 } 124