xref: /linux/tools/testing/selftests/bpf/progs/arena_atomics.c (revision 89aa02edaa30e4327ebc8fca9b80795bbfd4ce9b)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
3 #include <linux/bpf.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 #include <stdbool.h>
7 #include "bpf_arena_common.h"
8 
9 struct {
10 	__uint(type, BPF_MAP_TYPE_ARENA);
11 	__uint(map_flags, BPF_F_MMAPABLE);
12 	__uint(max_entries, 10); /* number of pages */
13 #ifdef __TARGET_ARCH_arm64
14 	__ulong(map_extra, 0x1ull << 32); /* start of mmap() region */
15 #else
16 	__ulong(map_extra, 0x1ull << 44); /* start of mmap() region */
17 #endif
18 } arena SEC(".maps");
19 
20 #if defined(ENABLE_ATOMICS_TESTS) && defined(__BPF_FEATURE_ADDR_SPACE_CAST)
21 bool skip_tests __attribute((__section__(".data"))) = false;
22 #else
23 bool skip_tests = true;
24 #endif
25 
26 __u32 pid = 0;
27 
28 #undef __arena
29 #if defined(__BPF_FEATURE_ADDR_SPACE_CAST)
30 #define __arena __attribute__((address_space(1)))
31 #else
32 #define __arena SEC(".addr_space.1")
33 #endif
34 
35 __u64 __arena add64_value = 1;
36 __u64 __arena add64_result = 0;
37 __u32 __arena add32_value = 1;
38 __u32 __arena add32_result = 0;
39 __u64 __arena add_stack_value_copy = 0;
40 __u64 __arena add_stack_result = 0;
41 __u64 __arena add_noreturn_value = 1;
42 
43 SEC("raw_tp/sys_enter")
44 int add(const void *ctx)
45 {
46 	if (pid != (bpf_get_current_pid_tgid() >> 32))
47 		return 0;
48 #ifdef ENABLE_ATOMICS_TESTS
49 	__u64 add_stack_value = 1;
50 
51 	add64_result = __sync_fetch_and_add(&add64_value, 2);
52 	add32_result = __sync_fetch_and_add(&add32_value, 2);
53 	add_stack_result = __sync_fetch_and_add(&add_stack_value, 2);
54 	add_stack_value_copy = add_stack_value;
55 	__sync_fetch_and_add(&add_noreturn_value, 2);
56 #endif
57 
58 	return 0;
59 }
60 
61 __s64 __arena sub64_value = 1;
62 __s64 __arena sub64_result = 0;
63 __s32 __arena sub32_value = 1;
64 __s32 __arena sub32_result = 0;
65 __s64 __arena sub_stack_value_copy = 0;
66 __s64 __arena sub_stack_result = 0;
67 __s64 __arena sub_noreturn_value = 1;
68 
69 SEC("raw_tp/sys_enter")
70 int sub(const void *ctx)
71 {
72 	if (pid != (bpf_get_current_pid_tgid() >> 32))
73 		return 0;
74 #ifdef ENABLE_ATOMICS_TESTS
75 	__u64 sub_stack_value = 1;
76 
77 	sub64_result = __sync_fetch_and_sub(&sub64_value, 2);
78 	sub32_result = __sync_fetch_and_sub(&sub32_value, 2);
79 	sub_stack_result = __sync_fetch_and_sub(&sub_stack_value, 2);
80 	sub_stack_value_copy = sub_stack_value;
81 	__sync_fetch_and_sub(&sub_noreturn_value, 2);
82 #endif
83 
84 	return 0;
85 }
86 
87 __u64 __arena and64_value = (0x110ull << 32);
88 __u32 __arena and32_value = 0x110;
89 
90 SEC("raw_tp/sys_enter")
91 int and(const void *ctx)
92 {
93 	if (pid != (bpf_get_current_pid_tgid() >> 32))
94 		return 0;
95 #ifdef ENABLE_ATOMICS_TESTS
96 
97 	__sync_fetch_and_and(&and64_value, 0x011ull << 32);
98 	__sync_fetch_and_and(&and32_value, 0x011);
99 #endif
100 
101 	return 0;
102 }
103 
104 __u32 __arena or32_value = 0x110;
105 __u64 __arena or64_value = (0x110ull << 32);
106 
107 SEC("raw_tp/sys_enter")
108 int or(const void *ctx)
109 {
110 	if (pid != (bpf_get_current_pid_tgid() >> 32))
111 		return 0;
112 #ifdef ENABLE_ATOMICS_TESTS
113 	__sync_fetch_and_or(&or64_value, 0x011ull << 32);
114 	__sync_fetch_and_or(&or32_value, 0x011);
115 #endif
116 
117 	return 0;
118 }
119 
120 __u64 __arena xor64_value = (0x110ull << 32);
121 __u32 __arena xor32_value = 0x110;
122 
123 SEC("raw_tp/sys_enter")
124 int xor(const void *ctx)
125 {
126 	if (pid != (bpf_get_current_pid_tgid() >> 32))
127 		return 0;
128 #ifdef ENABLE_ATOMICS_TESTS
129 	__sync_fetch_and_xor(&xor64_value, 0x011ull << 32);
130 	__sync_fetch_and_xor(&xor32_value, 0x011);
131 #endif
132 
133 	return 0;
134 }
135 
136 __u32 __arena cmpxchg32_value = 1;
137 __u32 __arena cmpxchg32_result_fail = 0;
138 __u32 __arena cmpxchg32_result_succeed = 0;
139 __u64 __arena cmpxchg64_value = 1;
140 __u64 __arena cmpxchg64_result_fail = 0;
141 __u64 __arena cmpxchg64_result_succeed = 0;
142 
143 SEC("raw_tp/sys_enter")
144 int cmpxchg(const void *ctx)
145 {
146 	if (pid != (bpf_get_current_pid_tgid() >> 32))
147 		return 0;
148 #ifdef ENABLE_ATOMICS_TESTS
149 	cmpxchg64_result_fail = __sync_val_compare_and_swap(&cmpxchg64_value, 0, 3);
150 	cmpxchg64_result_succeed = __sync_val_compare_and_swap(&cmpxchg64_value, 1, 2);
151 
152 	cmpxchg32_result_fail = __sync_val_compare_and_swap(&cmpxchg32_value, 0, 3);
153 	cmpxchg32_result_succeed = __sync_val_compare_and_swap(&cmpxchg32_value, 1, 2);
154 #endif
155 
156 	return 0;
157 }
158 
159 __u64 __arena xchg64_value = 1;
160 __u64 __arena xchg64_result = 0;
161 __u32 __arena xchg32_value = 1;
162 __u32 __arena xchg32_result = 0;
163 
164 SEC("raw_tp/sys_enter")
165 int xchg(const void *ctx)
166 {
167 	if (pid != (bpf_get_current_pid_tgid() >> 32))
168 		return 0;
169 #ifdef ENABLE_ATOMICS_TESTS
170 	__u64 val64 = 2;
171 	__u32 val32 = 2;
172 
173 	xchg64_result = __sync_lock_test_and_set(&xchg64_value, val64);
174 	xchg32_result = __sync_lock_test_and_set(&xchg32_value, val32);
175 #endif
176 
177 	return 0;
178 }
179