xref: /linux/tools/testing/selftests/bpf/libarena/include/libarena/common.h (revision 5a8cd539ac19f7a68e68e1d25ef9ca2ff55b8500)
1 // SPDX-License-Identifier: LGPL-2.1 OR BSD-2-Clause
2 /* Copyright (c) 2026 Meta Platforms, Inc. and affiliates. */
3 #pragma once
4 
5 #ifdef __BPF__
6 
7 #include <vmlinux.h>
8 
9 #include <bpf_arena_common.h>
10 #include <bpf_arena_spin_lock.h>
11 
12 #include <asm-generic/errno.h>
13 
14 #ifndef __BPF_FEATURE_ADDR_SPACE_CAST
15 #error "Arena allocators require bpf_addr_space_cast feature"
16 #endif
17 
18 #define arena_stdout(fmt, ...) bpf_stream_printk(1, (fmt), ##__VA_ARGS__)
19 #define arena_stderr(fmt, ...) bpf_stream_printk(2, (fmt), ##__VA_ARGS__)
20 
21 #ifndef __maybe_unused
22 #define __maybe_unused __attribute__((__unused__))
23 #endif
24 
25 #define private(name) SEC(".data." #name) __hidden __attribute__((aligned(8)))
26 
27 #define ARENA_PAGES (1UL << (32 - __builtin_ffs(__PAGE_SIZE) + 1))
28 
29 struct {
30 	__uint(type, BPF_MAP_TYPE_ARENA);
31 	__uint(map_flags, BPF_F_MMAPABLE);
32 	__uint(max_entries, ARENA_PAGES); /* number of pages */
33 #if defined(__TARGET_ARCH_arm64) || defined(__aarch64__)
34 	__ulong(map_extra, (1ull << 32)); /* start of mmap() region */
35 #else
36 	__ulong(map_extra, (1ull << 44)); /* start of mmap() region */
37 #endif
38 } arena __weak SEC(".maps");
39 
40 /*
41  * This is a variable used to aid verification. The may_goto directive
42  * permits open-coded for loops, but requires that the index variable is
43  * imprecise. To force the variable to be imprecise, initialize it with
44  * the opaque volatile variable 0 instead of the constant 0.
45  */
46 volatile u32 zero __weak;
47 extern volatile u64 asan_violated;
48 
49 int arena_fls(__u64 word);
50 
51 void __arena *arena_malloc(size_t size);
52 void arena_free(void __arena *ptr);
53 
54 /*
55  * The verifier associates arenas with programs by checking LD.IMM
56  * instruction operands for an arena and populating the program state
57  * with the first instance it finds. This requires accessing our global
58  * arena variable, but subprogs do not necessarily do so while still
59  * using pointers from that arena. Insert an LD.IMM instruction  to
60  * access the arena and help the verifier.
61  */
62 #define arena_subprog_init() do { asm volatile ("" :: "r"(&arena)); } while (0)
63 
64 #else /* ! __BPF__ */
65 
66 #include <stdint.h>
67 
68 #define __arena
69 
70 typedef uint8_t u8;
71 typedef uint16_t u16;
72 typedef uint32_t u32;
73 typedef uint64_t u64;
74 typedef int8_t s8;
75 typedef int16_t s16;
76 typedef int32_t s32;
77 typedef int64_t s64;
78 
79 /* Dummy "definition" for userspace. */
80 #define arena_spinlock_t int
81 
82 #endif /* __BPF__ */
83 
84 struct arena_get_info_args {
85 	void __arena *arena_base;
86 };
87 
88 struct arena_alloc_reserve_args {
89 	u64 nr_pages;
90 };
91 
92 /* Reasonable default number of pages reserved by arena_alloc_reserve. */
93 #define ARENA_RESERVE_PAGES_DFL (8)
94