xref: /linux/tools/testing/selftests/bpf/libarena/src/common.bpf.c (revision 283cb6513c881ccc6ff81f3da75d55e1ab1fe6fc)
1 // SPDX-License-Identifier: LGPL-2.1 OR BSD-2-Clause
2 /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
3 #include <limits.h>
4 
5 #include <libarena/common.h>
6 #include <libarena/asan.h>
7 #include <libarena/buddy.h>
8 
9 struct buddy __arena buddy;
10 volatile u32 zero = 0;
11 
12 /*
13  * Storage for the queue nodes declared by bpf_arena_spin_lock.h. Each program
14  * linking the arena spinlock provides exactly one definition, so that the array
15  * is emitted once rather than once per translation unit.
16  */
17 struct arena_qnode __arena __hidden qnodes[_Q_MAX_CPUS][_Q_MAX_NODES];
18 
19 int arena_fls(__u64 word)
20 {
21 	if (!word)
22 		return 0;
23 
24 	return 64 - __builtin_clzll(word);
25 }
26 
27 SEC("syscall")
28 __weak int arena_get_info(struct arena_get_info_args *args)
29 {
30 	args->arena_base = arena_base(&arena);
31 
32 	return 0;
33 }
34 
35 SEC("syscall")
36 __weak int arena_alloc_reserve(struct arena_alloc_reserve_args *args)
37 {
38 	return bpf_arena_reserve_pages(&arena, NULL, args->nr_pages);
39 }
40 
41 SEC("syscall")
42 __weak int arena_buddy_reset(void)
43 {
44 	buddy_destroy(&buddy);
45 
46 	return buddy_init(&buddy);
47 }
48 
49 SEC("syscall")
50 __weak int arena_buddy_destroy(void)
51 {
52 	return buddy_destroy(&buddy);
53 }
54 
55 __weak void __arena *arena_malloc(size_t size)
56 {
57 	return buddy_alloc(&buddy, size);
58 }
59 
60 __weak void __arena *arena_calloc(size_t ncount, size_t size)
61 {
62 	void __arena *mem;
63 	size_t total;
64 
65 	/*
66 	 * Ideally we'd be using __builtin_mul_overflow here,
67 	 * but the BPF compiler backend doesn't implement __multi3.
68 	 * There are ways to optimize the division away from the
69 	 * overflow check, but any costs are dwarfed by the
70 	 * buddy_alloc() call. Keep it simple for now.
71 	 */
72 	if (unlikely(ncount && size >= ULLONG_MAX / ncount))
73 		return NULL;
74 
75 	total = ncount * size;
76 
77 	mem = buddy_alloc(&buddy, total);
78 	if (likely(mem))
79 		arena_memset(mem, 0, total);
80 
81 	return mem;
82 }
83 
84 __weak void arena_free(void __arena *ptr)
85 {
86 	buddy_free(&buddy, ptr);
87 }
88 
89 char _license[] SEC("license") = "GPL";
90