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 12 static int sys_membarrier(int cmd, int flags) 13 { 14 return syscall(__NR_membarrier, cmd, flags); 15 } 16 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 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 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 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 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 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 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 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 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 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 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 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 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 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