xref: /linux/tools/testing/selftests/bpf/bpf_arena_common.h (revision 40ccd6aa3e2e05be93394e3cd560c718dedfcc77)
1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3 #pragma once
4 
5 #ifndef WRITE_ONCE
6 #define WRITE_ONCE(x, val) ((*(volatile typeof(x) *) &(x)) = (val))
7 #endif
8 
9 #ifndef NUMA_NO_NODE
10 #define	NUMA_NO_NODE	(-1)
11 #endif
12 
13 #ifndef arena_container_of
14 #define arena_container_of(ptr, type, member)			\
15 	({							\
16 		void __arena *__mptr = (void __arena *)(ptr);	\
17 		((type *)(__mptr - offsetof(type, member)));	\
18 	})
19 #endif
20 
21 #ifdef __BPF__ /* when compiled as bpf program */
22 
23 #ifndef PAGE_SIZE
24 #define PAGE_SIZE __PAGE_SIZE
25 /*
26  * for older kernels try sizeof(struct genradix_node)
27  * or flexible:
28  * static inline long __bpf_page_size(void) {
29  *   return bpf_core_enum_value(enum page_size_enum___l, __PAGE_SIZE___l) ?: sizeof(struct genradix_node);
30  * }
31  * but generated code is not great.
32  */
33 #endif
34 
35 #if defined(__BPF_FEATURE_ADDR_SPACE_CAST) && !defined(BPF_ARENA_FORCE_ASM)
36 #define __arena __attribute__((address_space(1)))
37 #define cast_kern(ptr) /* nop for bpf prog. emitted by LLVM */
38 #define cast_user(ptr) /* nop for bpf prog. emitted by LLVM */
39 #else
40 #define __arena
41 #define cast_kern(ptr) bpf_addr_space_cast(ptr, 0, 1)
42 #define cast_user(ptr) bpf_addr_space_cast(ptr, 1, 0)
43 #endif
44 
45 void __arena* bpf_arena_alloc_pages(void *map, void __arena *addr, __u32 page_cnt,
46 				    int node_id, __u64 flags) __ksym __weak;
47 void bpf_arena_free_pages(void *map, void __arena *ptr, __u32 page_cnt) __ksym __weak;
48 
49 #else /* when compiled as user space code */
50 
51 #define __arena
52 #define __arg_arena
53 #define cast_kern(ptr) /* nop for user space */
54 #define cast_user(ptr) /* nop for user space */
55 __weak char arena[1];
56 
57 #ifndef offsetof
58 #define offsetof(type, member)  ((unsigned long)&((type *)0)->member)
59 #endif
60 
61 static inline void __arena* bpf_arena_alloc_pages(void *map, void *addr, __u32 page_cnt,
62 						  int node_id, __u64 flags)
63 {
64 	return NULL;
65 }
66 static inline void bpf_arena_free_pages(void *map, void __arena *ptr, __u32 page_cnt)
67 {
68 }
69 
70 #endif
71