1 /* SPDX-License-Identifier: GPL-2.0 */
2 #define _GNU_SOURCE
3 #include <linux/membarrier.h>
4 #include <syscall.h>
5 #include <stdio.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <pthread.h>
9
10 #include "../kselftest.h"
11
sys_membarrier(int cmd,int flags)12 static int sys_membarrier(int cmd, int flags)
13 {
14 return syscall(__NR_membarrier, cmd, flags);
15 }
16
test_membarrier_cmd_fail(void)17 static int test_membarrier_cmd_fail(void)
18 {
19 int cmd = -1, flags = 0;
20 const char *test_name = "sys membarrier invalid command";
21
22 if (sys_membarrier(cmd, flags) != -1) {
23 ksft_exit_fail_msg(
24 "%s test: command = %d, flags = %d. Should fail, but passed\n",
25 test_name, cmd, flags);
26 }
27 if (errno != EINVAL) {
28 ksft_exit_fail_msg(
29 "%s test: flags = %d. Should return (%d: \"%s\"), but returned (%d: \"%s\").\n",
30 test_name, flags, EINVAL, strerror(EINVAL),
31 errno, strerror(errno));
32 }
33
34 ksft_test_result_pass(
35 "%s test: command = %d, flags = %d, errno = %d. Failed as expected\n",
36 test_name, cmd, flags, errno);
37 return 0;
38 }
39
test_membarrier_flags_fail(void)40 static int test_membarrier_flags_fail(void)
41 {
42 int cmd = MEMBARRIER_CMD_QUERY, flags = 1;
43 const char *test_name = "sys membarrier MEMBARRIER_CMD_QUERY invalid flags";
44
45 if (sys_membarrier(cmd, flags) != -1) {
46 ksft_exit_fail_msg(
47 "%s test: flags = %d. Should fail, but passed\n",
48 test_name, flags);
49 }
50 if (errno != EINVAL) {
51 ksft_exit_fail_msg(
52 "%s test: flags = %d. Should return (%d: \"%s\"), but returned (%d: \"%s\").\n",
53 test_name, flags, EINVAL, strerror(EINVAL),
54 errno, strerror(errno));
55 }
56
57 ksft_test_result_pass(
58 "%s test: flags = %d, errno = %d. Failed as expected\n",
59 test_name, flags, errno);
60 return 0;
61 }
62
test_membarrier_global_success(void)63 static int test_membarrier_global_success(void)
64 {
65 int cmd = MEMBARRIER_CMD_GLOBAL, flags = 0;
66 const char *test_name = "sys membarrier MEMBARRIER_CMD_GLOBAL";
67
68 if (sys_membarrier(cmd, flags) != 0) {
69 ksft_exit_fail_msg(
70 "%s test: flags = %d, errno = %d\n",
71 test_name, flags, errno);
72 }
73
74 ksft_test_result_pass(
75 "%s test: flags = %d\n", test_name, flags);
76 return 0;
77 }
78
test_membarrier_private_expedited_fail(void)79 static int test_membarrier_private_expedited_fail(void)
80 {
81 int cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED, flags = 0;
82 const char *test_name = "sys membarrier MEMBARRIER_CMD_PRIVATE_EXPEDITED not registered failure";
83
84 if (sys_membarrier(cmd, flags) != -1) {
85 ksft_exit_fail_msg(
86 "%s test: flags = %d. Should fail, but passed\n",
87 test_name, flags);
88 }
89 if (errno != EPERM) {
90 ksft_exit_fail_msg(
91 "%s test: flags = %d. Should return (%d: \"%s\"), but returned (%d: \"%s\").\n",
92 test_name, flags, EPERM, strerror(EPERM),
93 errno, strerror(errno));
94 }
95
96 ksft_test_result_pass(
97 "%s test: flags = %d, errno = %d\n",
98 test_name, flags, errno);
99 return 0;
100 }
101
test_membarrier_register_private_expedited_success(void)102 static int test_membarrier_register_private_expedited_success(void)
103 {
104 int cmd = MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, flags = 0;
105 const char *test_name = "sys membarrier MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED";
106
107 if (sys_membarrier(cmd, flags) != 0) {
108 ksft_exit_fail_msg(
109 "%s test: flags = %d, errno = %d\n",
110 test_name, flags, errno);
111 }
112
113 ksft_test_result_pass(
114 "%s test: flags = %d\n",
115 test_name, flags);
116 return 0;
117 }
118
test_membarrier_private_expedited_success(void)119 static int test_membarrier_private_expedited_success(void)
120 {
121 int cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED, flags = 0;
122 const char *test_name = "sys membarrier MEMBARRIER_CMD_PRIVATE_EXPEDITED";
123
124 if (sys_membarrier(cmd, flags) != 0) {
125 ksft_exit_fail_msg(
126 "%s test: flags = %d, errno = %d\n",
127 test_name, flags, errno);
128 }
129
130 ksft_test_result_pass(
131 "%s test: flags = %d\n",
132 test_name, flags);
133 return 0;
134 }
135
test_membarrier_private_expedited_sync_core_fail(void)136 static int test_membarrier_private_expedited_sync_core_fail(void)
137 {
138 int cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE, flags = 0;
139 const char *test_name = "sys membarrier MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE not registered failure";
140
141 if (sys_membarrier(cmd, flags) != -1) {
142 ksft_exit_fail_msg(
143 "%s test: flags = %d. Should fail, but passed\n",
144 test_name, flags);
145 }
146 if (errno != EPERM) {
147 ksft_exit_fail_msg(
148 "%s test: flags = %d. Should return (%d: \"%s\"), but returned (%d: \"%s\").\n",
149 test_name, flags, EPERM, strerror(EPERM),
150 errno, strerror(errno));
151 }
152
153 ksft_test_result_pass(
154 "%s test: flags = %d, errno = %d\n",
155 test_name, flags, errno);
156 return 0;
157 }
158
test_membarrier_register_private_expedited_sync_core_success(void)159 static int test_membarrier_register_private_expedited_sync_core_success(void)
160 {
161 int cmd = MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE, flags = 0;
162 const char *test_name = "sys membarrier MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE";
163
164 if (sys_membarrier(cmd, flags) != 0) {
165 ksft_exit_fail_msg(
166 "%s test: flags = %d, errno = %d\n",
167 test_name, flags, errno);
168 }
169
170 ksft_test_result_pass(
171 "%s test: flags = %d\n",
172 test_name, flags);
173 return 0;
174 }
175
test_membarrier_private_expedited_sync_core_success(void)176 static int test_membarrier_private_expedited_sync_core_success(void)
177 {
178 int cmd = MEMBARRIER_CMD_PRIVATE_EXPEDITED, flags = 0;
179 const char *test_name = "sys membarrier MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE";
180
181 if (sys_membarrier(cmd, flags) != 0) {
182 ksft_exit_fail_msg(
183 "%s test: flags = %d, errno = %d\n",
184 test_name, flags, errno);
185 }
186
187 ksft_test_result_pass(
188 "%s test: flags = %d\n",
189 test_name, flags);
190 return 0;
191 }
192
test_membarrier_register_global_expedited_success(void)193 static int test_membarrier_register_global_expedited_success(void)
194 {
195 int cmd = MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED, flags = 0;
196 const char *test_name = "sys membarrier MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED";
197
198 if (sys_membarrier(cmd, flags) != 0) {
199 ksft_exit_fail_msg(
200 "%s test: flags = %d, errno = %d\n",
201 test_name, flags, errno);
202 }
203
204 ksft_test_result_pass(
205 "%s test: flags = %d\n",
206 test_name, flags);
207 return 0;
208 }
209
test_membarrier_global_expedited_success(void)210 static int test_membarrier_global_expedited_success(void)
211 {
212 int cmd = MEMBARRIER_CMD_GLOBAL_EXPEDITED, flags = 0;
213 const char *test_name = "sys membarrier MEMBARRIER_CMD_GLOBAL_EXPEDITED";
214
215 if (sys_membarrier(cmd, flags) != 0) {
216 ksft_exit_fail_msg(
217 "%s test: flags = %d, errno = %d\n",
218 test_name, flags, errno);
219 }
220
221 ksft_test_result_pass(
222 "%s test: flags = %d\n",
223 test_name, flags);
224 return 0;
225 }
226
test_membarrier_fail(void)227 static int test_membarrier_fail(void)
228 {
229 int status;
230
231 status = test_membarrier_cmd_fail();
232 if (status)
233 return status;
234 status = test_membarrier_flags_fail();
235 if (status)
236 return status;
237 status = test_membarrier_private_expedited_fail();
238 if (status)
239 return status;
240 status = sys_membarrier(MEMBARRIER_CMD_QUERY, 0);
241 if (status < 0) {
242 ksft_test_result_fail("sys_membarrier() failed\n");
243 return status;
244 }
245 if (status & MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE) {
246 status = test_membarrier_private_expedited_sync_core_fail();
247 if (status)
248 return status;
249 }
250 return 0;
251 }
252
test_membarrier_success(void)253 static int test_membarrier_success(void)
254 {
255 int status;
256
257 status = test_membarrier_global_success();
258 if (status)
259 return status;
260 status = test_membarrier_register_private_expedited_success();
261 if (status)
262 return status;
263 status = test_membarrier_private_expedited_success();
264 if (status)
265 return status;
266 status = sys_membarrier(MEMBARRIER_CMD_QUERY, 0);
267 if (status < 0) {
268 ksft_test_result_fail("sys_membarrier() failed\n");
269 return status;
270 }
271 if (status & MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE) {
272 status = test_membarrier_register_private_expedited_sync_core_success();
273 if (status)
274 return status;
275 status = test_membarrier_private_expedited_sync_core_success();
276 if (status)
277 return status;
278 }
279 /*
280 * It is valid to send a global membarrier from a non-registered
281 * process.
282 */
283 status = test_membarrier_global_expedited_success();
284 if (status)
285 return status;
286 status = test_membarrier_register_global_expedited_success();
287 if (status)
288 return status;
289 status = test_membarrier_global_expedited_success();
290 if (status)
291 return status;
292 return 0;
293 }
294
test_membarrier_query(void)295 static int test_membarrier_query(void)
296 {
297 int flags = 0, ret;
298
299 ret = sys_membarrier(MEMBARRIER_CMD_QUERY, flags);
300 if (ret < 0) {
301 if (errno == ENOSYS) {
302 /*
303 * It is valid to build a kernel with
304 * CONFIG_MEMBARRIER=n. However, this skips the tests.
305 */
306 ksft_exit_skip(
307 "sys membarrier (CONFIG_MEMBARRIER) is disabled.\n");
308 }
309 ksft_exit_fail_msg("sys_membarrier() failed\n");
310 }
311 if (!(ret & MEMBARRIER_CMD_GLOBAL))
312 ksft_exit_skip(
313 "sys_membarrier unsupported: CMD_GLOBAL not found.\n");
314
315 ksft_test_result_pass("sys_membarrier available\n");
316 return 0;
317 }
318