Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rseq/selftests: Add support for arm64

Hook up arm64 support to the rseq selftests.

Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>

+616
+20
tools/testing/selftests/rseq/param_test.c
··· 114 114 "bne 222b\n\t" \ 115 115 "333:\n\t" 116 116 117 + #elif defined(__AARCH64EL__) 118 + 119 + #define RSEQ_INJECT_INPUT \ 120 + , [loop_cnt_1] "Qo" (loop_cnt[1]) \ 121 + , [loop_cnt_2] "Qo" (loop_cnt[2]) \ 122 + , [loop_cnt_3] "Qo" (loop_cnt[3]) \ 123 + , [loop_cnt_4] "Qo" (loop_cnt[4]) \ 124 + , [loop_cnt_5] "Qo" (loop_cnt[5]) \ 125 + , [loop_cnt_6] "Qo" (loop_cnt[6]) 126 + 127 + #define INJECT_ASM_REG RSEQ_ASM_TMP_REG32 128 + 129 + #define RSEQ_INJECT_ASM(n) \ 130 + " ldr " INJECT_ASM_REG ", %[loop_cnt_" #n "]\n" \ 131 + " cbz " INJECT_ASM_REG ", 333f\n" \ 132 + "222:\n" \ 133 + " sub " INJECT_ASM_REG ", " INJECT_ASM_REG ", #1\n" \ 134 + " cbnz " INJECT_ASM_REG ", 222b\n" \ 135 + "333:\n" 136 + 117 137 #elif __PPC__ 118 138 119 139 #define RSEQ_INJECT_INPUT \
+594
tools/testing/selftests/rseq/rseq-arm64.h
··· 1 + /* SPDX-License-Identifier: LGPL-2.1 OR MIT */ 2 + /* 3 + * rseq-arm64.h 4 + * 5 + * (C) Copyright 2016-2018 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> 6 + * (C) Copyright 2018 - Will Deacon <will.deacon@arm.com> 7 + */ 8 + 9 + #define RSEQ_SIG 0xd428bc00 /* BRK #0x45E0 */ 10 + 11 + #define rseq_smp_mb() __asm__ __volatile__ ("dmb ish" ::: "memory") 12 + #define rseq_smp_rmb() __asm__ __volatile__ ("dmb ishld" ::: "memory") 13 + #define rseq_smp_wmb() __asm__ __volatile__ ("dmb ishst" ::: "memory") 14 + 15 + #define rseq_smp_load_acquire(p) \ 16 + __extension__ ({ \ 17 + __typeof(*p) ____p1; \ 18 + switch (sizeof(*p)) { \ 19 + case 1: \ 20 + asm volatile ("ldarb %w0, %1" \ 21 + : "=r" (*(__u8 *)p) \ 22 + : "Q" (*p) : "memory"); \ 23 + break; \ 24 + case 2: \ 25 + asm volatile ("ldarh %w0, %1" \ 26 + : "=r" (*(__u16 *)p) \ 27 + : "Q" (*p) : "memory"); \ 28 + break; \ 29 + case 4: \ 30 + asm volatile ("ldar %w0, %1" \ 31 + : "=r" (*(__u32 *)p) \ 32 + : "Q" (*p) : "memory"); \ 33 + break; \ 34 + case 8: \ 35 + asm volatile ("ldar %0, %1" \ 36 + : "=r" (*(__u64 *)p) \ 37 + : "Q" (*p) : "memory"); \ 38 + break; \ 39 + } \ 40 + ____p1; \ 41 + }) 42 + 43 + #define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb() 44 + 45 + #define rseq_smp_store_release(p, v) \ 46 + do { \ 47 + switch (sizeof(*p)) { \ 48 + case 1: \ 49 + asm volatile ("stlrb %w1, %0" \ 50 + : "=Q" (*p) \ 51 + : "r" ((__u8)v) \ 52 + : "memory"); \ 53 + break; \ 54 + case 2: \ 55 + asm volatile ("stlrh %w1, %0" \ 56 + : "=Q" (*p) \ 57 + : "r" ((__u16)v) \ 58 + : "memory"); \ 59 + break; \ 60 + case 4: \ 61 + asm volatile ("stlr %w1, %0" \ 62 + : "=Q" (*p) \ 63 + : "r" ((__u32)v) \ 64 + : "memory"); \ 65 + break; \ 66 + case 8: \ 67 + asm volatile ("stlr %1, %0" \ 68 + : "=Q" (*p) \ 69 + : "r" ((__u64)v) \ 70 + : "memory"); \ 71 + break; \ 72 + } \ 73 + } while (0) 74 + 75 + #ifdef RSEQ_SKIP_FASTPATH 76 + #include "rseq-skip.h" 77 + #else /* !RSEQ_SKIP_FASTPATH */ 78 + 79 + #define RSEQ_ASM_TMP_REG32 "w15" 80 + #define RSEQ_ASM_TMP_REG "x15" 81 + #define RSEQ_ASM_TMP_REG_2 "x14" 82 + 83 + #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \ 84 + post_commit_offset, abort_ip) \ 85 + " .pushsection __rseq_table, \"aw\"\n" \ 86 + " .balign 32\n" \ 87 + __rseq_str(label) ":\n" \ 88 + " .long " __rseq_str(version) ", " __rseq_str(flags) "\n" \ 89 + " .quad " __rseq_str(start_ip) ", " \ 90 + __rseq_str(post_commit_offset) ", " \ 91 + __rseq_str(abort_ip) "\n" \ 92 + " .popsection\n" 93 + 94 + #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \ 95 + __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \ 96 + (post_commit_ip - start_ip), abort_ip) 97 + 98 + #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \ 99 + RSEQ_INJECT_ASM(1) \ 100 + " adrp " RSEQ_ASM_TMP_REG ", " __rseq_str(cs_label) "\n" \ 101 + " add " RSEQ_ASM_TMP_REG ", " RSEQ_ASM_TMP_REG \ 102 + ", :lo12:" __rseq_str(cs_label) "\n" \ 103 + " str " RSEQ_ASM_TMP_REG ", %[" __rseq_str(rseq_cs) "]\n" \ 104 + __rseq_str(label) ":\n" 105 + 106 + #define RSEQ_ASM_DEFINE_ABORT(label, abort_label) \ 107 + " b 222f\n" \ 108 + " .inst " __rseq_str(RSEQ_SIG) "\n" \ 109 + __rseq_str(label) ":\n" \ 110 + " b %l[" __rseq_str(abort_label) "]\n" \ 111 + "222:\n" 112 + 113 + #define RSEQ_ASM_OP_STORE(value, var) \ 114 + " str %[" __rseq_str(value) "], %[" __rseq_str(var) "]\n" 115 + 116 + #define RSEQ_ASM_OP_STORE_RELEASE(value, var) \ 117 + " stlr %[" __rseq_str(value) "], %[" __rseq_str(var) "]\n" 118 + 119 + #define RSEQ_ASM_OP_FINAL_STORE(value, var, post_commit_label) \ 120 + RSEQ_ASM_OP_STORE(value, var) \ 121 + __rseq_str(post_commit_label) ":\n" 122 + 123 + #define RSEQ_ASM_OP_FINAL_STORE_RELEASE(value, var, post_commit_label) \ 124 + RSEQ_ASM_OP_STORE_RELEASE(value, var) \ 125 + __rseq_str(post_commit_label) ":\n" 126 + 127 + #define RSEQ_ASM_OP_CMPEQ(var, expect, label) \ 128 + " ldr " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n" \ 129 + " sub " RSEQ_ASM_TMP_REG ", " RSEQ_ASM_TMP_REG \ 130 + ", %[" __rseq_str(expect) "]\n" \ 131 + " cbnz " RSEQ_ASM_TMP_REG ", " __rseq_str(label) "\n" 132 + 133 + #define RSEQ_ASM_OP_CMPEQ32(var, expect, label) \ 134 + " ldr " RSEQ_ASM_TMP_REG32 ", %[" __rseq_str(var) "]\n" \ 135 + " sub " RSEQ_ASM_TMP_REG32 ", " RSEQ_ASM_TMP_REG32 \ 136 + ", %w[" __rseq_str(expect) "]\n" \ 137 + " cbnz " RSEQ_ASM_TMP_REG32 ", " __rseq_str(label) "\n" 138 + 139 + #define RSEQ_ASM_OP_CMPNE(var, expect, label) \ 140 + " ldr " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n" \ 141 + " sub " RSEQ_ASM_TMP_REG ", " RSEQ_ASM_TMP_REG \ 142 + ", %[" __rseq_str(expect) "]\n" \ 143 + " cbz " RSEQ_ASM_TMP_REG ", " __rseq_str(label) "\n" 144 + 145 + #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \ 146 + RSEQ_INJECT_ASM(2) \ 147 + RSEQ_ASM_OP_CMPEQ32(current_cpu_id, cpu_id, label) 148 + 149 + #define RSEQ_ASM_OP_R_LOAD(var) \ 150 + " ldr " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n" 151 + 152 + #define RSEQ_ASM_OP_R_STORE(var) \ 153 + " str " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n" 154 + 155 + #define RSEQ_ASM_OP_R_LOAD_OFF(offset) \ 156 + " ldr " RSEQ_ASM_TMP_REG ", [" RSEQ_ASM_TMP_REG \ 157 + ", %[" __rseq_str(offset) "]]\n" 158 + 159 + #define RSEQ_ASM_OP_R_ADD(count) \ 160 + " add " RSEQ_ASM_TMP_REG ", " RSEQ_ASM_TMP_REG \ 161 + ", %[" __rseq_str(count) "]\n" 162 + 163 + #define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label) \ 164 + " str " RSEQ_ASM_TMP_REG ", %[" __rseq_str(var) "]\n" \ 165 + __rseq_str(post_commit_label) ":\n" 166 + 167 + #define RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len) \ 168 + " cbz %[" __rseq_str(len) "], 333f\n" \ 169 + " mov " RSEQ_ASM_TMP_REG_2 ", %[" __rseq_str(len) "]\n" \ 170 + "222: sub " RSEQ_ASM_TMP_REG_2 ", " RSEQ_ASM_TMP_REG_2 ", #1\n" \ 171 + " ldrb " RSEQ_ASM_TMP_REG32 ", [%[" __rseq_str(src) "]" \ 172 + ", " RSEQ_ASM_TMP_REG_2 "]\n" \ 173 + " strb " RSEQ_ASM_TMP_REG32 ", [%[" __rseq_str(dst) "]" \ 174 + ", " RSEQ_ASM_TMP_REG_2 "]\n" \ 175 + " cbnz " RSEQ_ASM_TMP_REG_2 ", 222b\n" \ 176 + "333:\n" 177 + 178 + static inline __attribute__((always_inline)) 179 + int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu) 180 + { 181 + RSEQ_INJECT_C(9) 182 + 183 + __asm__ __volatile__ goto ( 184 + RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 185 + RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 186 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 187 + RSEQ_INJECT_ASM(3) 188 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail]) 189 + RSEQ_INJECT_ASM(4) 190 + #ifdef RSEQ_COMPARE_TWICE 191 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 192 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2]) 193 + #endif 194 + RSEQ_ASM_OP_FINAL_STORE(newv, v, 3) 195 + RSEQ_INJECT_ASM(5) 196 + RSEQ_ASM_DEFINE_ABORT(4, abort) 197 + : /* gcc asm goto does not allow outputs */ 198 + : [cpu_id] "r" (cpu), 199 + [current_cpu_id] "Qo" (__rseq_abi.cpu_id), 200 + [rseq_cs] "m" (__rseq_abi.rseq_cs), 201 + [v] "Qo" (*v), 202 + [expect] "r" (expect), 203 + [newv] "r" (newv) 204 + RSEQ_INJECT_INPUT 205 + : "memory", RSEQ_ASM_TMP_REG 206 + : abort, cmpfail 207 + #ifdef RSEQ_COMPARE_TWICE 208 + , error1, error2 209 + #endif 210 + ); 211 + 212 + return 0; 213 + abort: 214 + RSEQ_INJECT_FAILED 215 + return -1; 216 + cmpfail: 217 + return 1; 218 + #ifdef RSEQ_COMPARE_TWICE 219 + error1: 220 + rseq_bug("cpu_id comparison failed"); 221 + error2: 222 + rseq_bug("expected value comparison failed"); 223 + #endif 224 + } 225 + 226 + static inline __attribute__((always_inline)) 227 + int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot, 228 + off_t voffp, intptr_t *load, int cpu) 229 + { 230 + RSEQ_INJECT_C(9) 231 + 232 + __asm__ __volatile__ goto ( 233 + RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 234 + RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 235 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 236 + RSEQ_INJECT_ASM(3) 237 + RSEQ_ASM_OP_CMPNE(v, expectnot, %l[cmpfail]) 238 + RSEQ_INJECT_ASM(4) 239 + #ifdef RSEQ_COMPARE_TWICE 240 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 241 + RSEQ_ASM_OP_CMPNE(v, expectnot, %l[error2]) 242 + #endif 243 + RSEQ_ASM_OP_R_LOAD(v) 244 + RSEQ_ASM_OP_R_STORE(load) 245 + RSEQ_ASM_OP_R_LOAD_OFF(voffp) 246 + RSEQ_ASM_OP_R_FINAL_STORE(v, 3) 247 + RSEQ_INJECT_ASM(5) 248 + RSEQ_ASM_DEFINE_ABORT(4, abort) 249 + : /* gcc asm goto does not allow outputs */ 250 + : [cpu_id] "r" (cpu), 251 + [current_cpu_id] "Qo" (__rseq_abi.cpu_id), 252 + [rseq_cs] "m" (__rseq_abi.rseq_cs), 253 + [v] "Qo" (*v), 254 + [expectnot] "r" (expectnot), 255 + [load] "Qo" (*load), 256 + [voffp] "r" (voffp) 257 + RSEQ_INJECT_INPUT 258 + : "memory", RSEQ_ASM_TMP_REG 259 + : abort, cmpfail 260 + #ifdef RSEQ_COMPARE_TWICE 261 + , error1, error2 262 + #endif 263 + ); 264 + return 0; 265 + abort: 266 + RSEQ_INJECT_FAILED 267 + return -1; 268 + cmpfail: 269 + return 1; 270 + #ifdef RSEQ_COMPARE_TWICE 271 + error1: 272 + rseq_bug("cpu_id comparison failed"); 273 + error2: 274 + rseq_bug("expected value comparison failed"); 275 + #endif 276 + } 277 + 278 + static inline __attribute__((always_inline)) 279 + int rseq_addv(intptr_t *v, intptr_t count, int cpu) 280 + { 281 + RSEQ_INJECT_C(9) 282 + 283 + __asm__ __volatile__ goto ( 284 + RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 285 + RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 286 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 287 + RSEQ_INJECT_ASM(3) 288 + #ifdef RSEQ_COMPARE_TWICE 289 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 290 + #endif 291 + RSEQ_ASM_OP_R_LOAD(v) 292 + RSEQ_ASM_OP_R_ADD(count) 293 + RSEQ_ASM_OP_R_FINAL_STORE(v, 3) 294 + RSEQ_INJECT_ASM(4) 295 + RSEQ_ASM_DEFINE_ABORT(4, abort) 296 + : /* gcc asm goto does not allow outputs */ 297 + : [cpu_id] "r" (cpu), 298 + [current_cpu_id] "Qo" (__rseq_abi.cpu_id), 299 + [rseq_cs] "m" (__rseq_abi.rseq_cs), 300 + [v] "Qo" (*v), 301 + [count] "r" (count) 302 + RSEQ_INJECT_INPUT 303 + : "memory", RSEQ_ASM_TMP_REG 304 + : abort 305 + #ifdef RSEQ_COMPARE_TWICE 306 + , error1 307 + #endif 308 + ); 309 + return 0; 310 + abort: 311 + RSEQ_INJECT_FAILED 312 + return -1; 313 + #ifdef RSEQ_COMPARE_TWICE 314 + error1: 315 + rseq_bug("cpu_id comparison failed"); 316 + #endif 317 + } 318 + 319 + static inline __attribute__((always_inline)) 320 + int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect, 321 + intptr_t *v2, intptr_t newv2, 322 + intptr_t newv, int cpu) 323 + { 324 + RSEQ_INJECT_C(9) 325 + 326 + __asm__ __volatile__ goto ( 327 + RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 328 + RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 329 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 330 + RSEQ_INJECT_ASM(3) 331 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail]) 332 + RSEQ_INJECT_ASM(4) 333 + #ifdef RSEQ_COMPARE_TWICE 334 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 335 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2]) 336 + #endif 337 + RSEQ_ASM_OP_STORE(newv2, v2) 338 + RSEQ_INJECT_ASM(5) 339 + RSEQ_ASM_OP_FINAL_STORE(newv, v, 3) 340 + RSEQ_INJECT_ASM(6) 341 + RSEQ_ASM_DEFINE_ABORT(4, abort) 342 + : /* gcc asm goto does not allow outputs */ 343 + : [cpu_id] "r" (cpu), 344 + [current_cpu_id] "Qo" (__rseq_abi.cpu_id), 345 + [rseq_cs] "m" (__rseq_abi.rseq_cs), 346 + [expect] "r" (expect), 347 + [v] "Qo" (*v), 348 + [newv] "r" (newv), 349 + [v2] "Qo" (*v2), 350 + [newv2] "r" (newv2) 351 + RSEQ_INJECT_INPUT 352 + : "memory", RSEQ_ASM_TMP_REG 353 + : abort, cmpfail 354 + #ifdef RSEQ_COMPARE_TWICE 355 + , error1, error2 356 + #endif 357 + ); 358 + 359 + return 0; 360 + abort: 361 + RSEQ_INJECT_FAILED 362 + return -1; 363 + cmpfail: 364 + return 1; 365 + #ifdef RSEQ_COMPARE_TWICE 366 + error1: 367 + rseq_bug("cpu_id comparison failed"); 368 + error2: 369 + rseq_bug("expected value comparison failed"); 370 + #endif 371 + } 372 + 373 + static inline __attribute__((always_inline)) 374 + int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect, 375 + intptr_t *v2, intptr_t newv2, 376 + intptr_t newv, int cpu) 377 + { 378 + RSEQ_INJECT_C(9) 379 + 380 + __asm__ __volatile__ goto ( 381 + RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 382 + RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 383 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 384 + RSEQ_INJECT_ASM(3) 385 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail]) 386 + RSEQ_INJECT_ASM(4) 387 + #ifdef RSEQ_COMPARE_TWICE 388 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 389 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2]) 390 + #endif 391 + RSEQ_ASM_OP_STORE(newv2, v2) 392 + RSEQ_INJECT_ASM(5) 393 + RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3) 394 + RSEQ_INJECT_ASM(6) 395 + RSEQ_ASM_DEFINE_ABORT(4, abort) 396 + : /* gcc asm goto does not allow outputs */ 397 + : [cpu_id] "r" (cpu), 398 + [current_cpu_id] "Qo" (__rseq_abi.cpu_id), 399 + [rseq_cs] "m" (__rseq_abi.rseq_cs), 400 + [expect] "r" (expect), 401 + [v] "Qo" (*v), 402 + [newv] "r" (newv), 403 + [v2] "Qo" (*v2), 404 + [newv2] "r" (newv2) 405 + RSEQ_INJECT_INPUT 406 + : "memory", RSEQ_ASM_TMP_REG 407 + : abort, cmpfail 408 + #ifdef RSEQ_COMPARE_TWICE 409 + , error1, error2 410 + #endif 411 + ); 412 + 413 + return 0; 414 + abort: 415 + RSEQ_INJECT_FAILED 416 + return -1; 417 + cmpfail: 418 + return 1; 419 + #ifdef RSEQ_COMPARE_TWICE 420 + error1: 421 + rseq_bug("cpu_id comparison failed"); 422 + error2: 423 + rseq_bug("expected value comparison failed"); 424 + #endif 425 + } 426 + 427 + static inline __attribute__((always_inline)) 428 + int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect, 429 + intptr_t *v2, intptr_t expect2, 430 + intptr_t newv, int cpu) 431 + { 432 + RSEQ_INJECT_C(9) 433 + 434 + __asm__ __volatile__ goto ( 435 + RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 436 + RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 437 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 438 + RSEQ_INJECT_ASM(3) 439 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail]) 440 + RSEQ_INJECT_ASM(4) 441 + RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[cmpfail]) 442 + RSEQ_INJECT_ASM(5) 443 + #ifdef RSEQ_COMPARE_TWICE 444 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 445 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2]) 446 + RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[error3]) 447 + #endif 448 + RSEQ_ASM_OP_FINAL_STORE(newv, v, 3) 449 + RSEQ_INJECT_ASM(6) 450 + RSEQ_ASM_DEFINE_ABORT(4, abort) 451 + : /* gcc asm goto does not allow outputs */ 452 + : [cpu_id] "r" (cpu), 453 + [current_cpu_id] "Qo" (__rseq_abi.cpu_id), 454 + [rseq_cs] "m" (__rseq_abi.rseq_cs), 455 + [v] "Qo" (*v), 456 + [expect] "r" (expect), 457 + [v2] "Qo" (*v2), 458 + [expect2] "r" (expect2), 459 + [newv] "r" (newv) 460 + RSEQ_INJECT_INPUT 461 + : "memory", RSEQ_ASM_TMP_REG 462 + : abort, cmpfail 463 + #ifdef RSEQ_COMPARE_TWICE 464 + , error1, error2, error3 465 + #endif 466 + ); 467 + 468 + return 0; 469 + abort: 470 + RSEQ_INJECT_FAILED 471 + return -1; 472 + cmpfail: 473 + return 1; 474 + #ifdef RSEQ_COMPARE_TWICE 475 + error1: 476 + rseq_bug("cpu_id comparison failed"); 477 + error2: 478 + rseq_bug("expected value comparison failed"); 479 + error3: 480 + rseq_bug("2nd expected value comparison failed"); 481 + #endif 482 + } 483 + 484 + static inline __attribute__((always_inline)) 485 + int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect, 486 + void *dst, void *src, size_t len, 487 + intptr_t newv, int cpu) 488 + { 489 + RSEQ_INJECT_C(9) 490 + 491 + __asm__ __volatile__ goto ( 492 + RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 493 + RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 494 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 495 + RSEQ_INJECT_ASM(3) 496 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail]) 497 + RSEQ_INJECT_ASM(4) 498 + #ifdef RSEQ_COMPARE_TWICE 499 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 500 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2]) 501 + #endif 502 + RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len) 503 + RSEQ_INJECT_ASM(5) 504 + RSEQ_ASM_OP_FINAL_STORE(newv, v, 3) 505 + RSEQ_INJECT_ASM(6) 506 + RSEQ_ASM_DEFINE_ABORT(4, abort) 507 + : /* gcc asm goto does not allow outputs */ 508 + : [cpu_id] "r" (cpu), 509 + [current_cpu_id] "Qo" (__rseq_abi.cpu_id), 510 + [rseq_cs] "m" (__rseq_abi.rseq_cs), 511 + [expect] "r" (expect), 512 + [v] "Qo" (*v), 513 + [newv] "r" (newv), 514 + [dst] "r" (dst), 515 + [src] "r" (src), 516 + [len] "r" (len) 517 + RSEQ_INJECT_INPUT 518 + : "memory", RSEQ_ASM_TMP_REG, RSEQ_ASM_TMP_REG_2 519 + : abort, cmpfail 520 + #ifdef RSEQ_COMPARE_TWICE 521 + , error1, error2 522 + #endif 523 + ); 524 + 525 + return 0; 526 + abort: 527 + RSEQ_INJECT_FAILED 528 + return -1; 529 + cmpfail: 530 + return 1; 531 + #ifdef RSEQ_COMPARE_TWICE 532 + error1: 533 + rseq_bug("cpu_id comparison failed"); 534 + error2: 535 + rseq_bug("expected value comparison failed"); 536 + #endif 537 + } 538 + 539 + static inline __attribute__((always_inline)) 540 + int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect, 541 + void *dst, void *src, size_t len, 542 + intptr_t newv, int cpu) 543 + { 544 + RSEQ_INJECT_C(9) 545 + 546 + __asm__ __volatile__ goto ( 547 + RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f) 548 + RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs) 549 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f) 550 + RSEQ_INJECT_ASM(3) 551 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail]) 552 + RSEQ_INJECT_ASM(4) 553 + #ifdef RSEQ_COMPARE_TWICE 554 + RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1]) 555 + RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2]) 556 + #endif 557 + RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len) 558 + RSEQ_INJECT_ASM(5) 559 + RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3) 560 + RSEQ_INJECT_ASM(6) 561 + RSEQ_ASM_DEFINE_ABORT(4, abort) 562 + : /* gcc asm goto does not allow outputs */ 563 + : [cpu_id] "r" (cpu), 564 + [current_cpu_id] "Qo" (__rseq_abi.cpu_id), 565 + [rseq_cs] "m" (__rseq_abi.rseq_cs), 566 + [expect] "r" (expect), 567 + [v] "Qo" (*v), 568 + [newv] "r" (newv), 569 + [dst] "r" (dst), 570 + [src] "r" (src), 571 + [len] "r" (len) 572 + RSEQ_INJECT_INPUT 573 + : "memory", RSEQ_ASM_TMP_REG, RSEQ_ASM_TMP_REG_2 574 + : abort, cmpfail 575 + #ifdef RSEQ_COMPARE_TWICE 576 + , error1, error2 577 + #endif 578 + ); 579 + 580 + return 0; 581 + abort: 582 + RSEQ_INJECT_FAILED 583 + return -1; 584 + cmpfail: 585 + return 1; 586 + #ifdef RSEQ_COMPARE_TWICE 587 + error1: 588 + rseq_bug("cpu_id comparison failed"); 589 + error2: 590 + rseq_bug("expected value comparison failed"); 591 + #endif 592 + } 593 + 594 + #endif /* !RSEQ_SKIP_FASTPATH */
+2
tools/testing/selftests/rseq/rseq.h
··· 71 71 #include <rseq-x86.h> 72 72 #elif defined(__ARMEL__) 73 73 #include <rseq-arm.h> 74 + #elif defined (__AARCH64EL__) 75 + #include <rseq-arm64.h> 74 76 #elif defined(__PPC__) 75 77 #include <rseq-ppc.h> 76 78 #elif defined(__mips__)