0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #define RSEQ_SIG 0x0fe5000b
0018
0019 #define rseq_smp_mb() __asm__ __volatile__ ("sync" ::: "memory", "cc")
0020 #define rseq_smp_lwsync() __asm__ __volatile__ ("lwsync" ::: "memory", "cc")
0021 #define rseq_smp_rmb() rseq_smp_lwsync()
0022 #define rseq_smp_wmb() rseq_smp_lwsync()
0023
0024 #define rseq_smp_load_acquire(p) \
0025 __extension__ ({ \
0026 __typeof(*p) ____p1 = RSEQ_READ_ONCE(*p); \
0027 rseq_smp_lwsync(); \
0028 ____p1; \
0029 })
0030
0031 #define rseq_smp_acquire__after_ctrl_dep() rseq_smp_lwsync()
0032
0033 #define rseq_smp_store_release(p, v) \
0034 do { \
0035 rseq_smp_lwsync(); \
0036 RSEQ_WRITE_ONCE(*p, v); \
0037 } while (0)
0038
0039 #ifdef RSEQ_SKIP_FASTPATH
0040 #include "rseq-skip.h"
0041 #else
0042
0043
0044
0045
0046
0047
0048 #ifdef __PPC64__
0049
0050 #define RSEQ_STORE_LONG(arg) "std%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "
0051 #define RSEQ_STORE_INT(arg) "stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "
0052 #define RSEQ_LOAD_LONG(arg) "ld%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "
0053 #define RSEQ_LOAD_INT(arg) "lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "
0054 #define RSEQ_LOADX_LONG "ldx "
0055 #define RSEQ_CMP_LONG "cmpd "
0056 #define RSEQ_CMP_LONG_INT "cmpdi "
0057
0058 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \
0059 start_ip, post_commit_offset, abort_ip) \
0060 ".pushsection __rseq_cs, \"aw\"\n\t" \
0061 ".balign 32\n\t" \
0062 __rseq_str(label) ":\n\t" \
0063 ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
0064 ".quad " __rseq_str(start_ip) ", " __rseq_str(post_commit_offset) ", " __rseq_str(abort_ip) "\n\t" \
0065 ".popsection\n\t" \
0066 ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \
0067 ".quad " __rseq_str(label) "b\n\t" \
0068 ".popsection\n\t"
0069
0070 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
0071 RSEQ_INJECT_ASM(1) \
0072 "lis %%r17, (" __rseq_str(cs_label) ")@highest\n\t" \
0073 "ori %%r17, %%r17, (" __rseq_str(cs_label) ")@higher\n\t" \
0074 "rldicr %%r17, %%r17, 32, 31\n\t" \
0075 "oris %%r17, %%r17, (" __rseq_str(cs_label) ")@high\n\t" \
0076 "ori %%r17, %%r17, (" __rseq_str(cs_label) ")@l\n\t" \
0077 "std %%r17, %[" __rseq_str(rseq_cs) "]\n\t" \
0078 __rseq_str(label) ":\n\t"
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \
0089 ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \
0090 ".quad " __rseq_str(start_ip) ", " __rseq_str(exit_ip) "\n\t" \
0091 ".popsection\n\t"
0092
0093 #else
0094
0095 #define RSEQ_STORE_LONG(arg) "stw%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "
0096 #define RSEQ_STORE_INT(arg) RSEQ_STORE_LONG(arg)
0097 #define RSEQ_LOAD_LONG(arg) "lwz%U[" __rseq_str(arg) "]%X[" __rseq_str(arg) "] "
0098 #define RSEQ_LOAD_INT(arg) RSEQ_LOAD_LONG(arg)
0099 #define RSEQ_LOADX_LONG "lwzx "
0100 #define RSEQ_CMP_LONG "cmpw "
0101 #define RSEQ_CMP_LONG_INT "cmpwi "
0102
0103 #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, \
0104 start_ip, post_commit_offset, abort_ip) \
0105 ".pushsection __rseq_cs, \"aw\"\n\t" \
0106 ".balign 32\n\t" \
0107 __rseq_str(label) ":\n\t" \
0108 ".long " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
0109 \
0110 ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(post_commit_offset) ", 0x0, " __rseq_str(abort_ip) "\n\t" \
0111 ".popsection\n\t" \
0112 ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \
0113 ".long 0x0, " __rseq_str(label) "b\n\t" \
0114 ".popsection\n\t"
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124 #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \
0125 ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \
0126 \
0127 ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n\t" \
0128 ".popsection\n\t"
0129
0130 #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
0131 RSEQ_INJECT_ASM(1) \
0132 "lis %%r17, (" __rseq_str(cs_label) ")@ha\n\t" \
0133 "addi %%r17, %%r17, (" __rseq_str(cs_label) ")@l\n\t" \
0134 RSEQ_STORE_INT(rseq_cs) "%%r17, %[" __rseq_str(rseq_cs) "]\n\t" \
0135 __rseq_str(label) ":\n\t"
0136
0137 #endif
0138
0139 #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
0140 __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \
0141 (post_commit_ip - start_ip), abort_ip)
0142
0143 #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \
0144 RSEQ_INJECT_ASM(2) \
0145 RSEQ_LOAD_INT(current_cpu_id) "%%r17, %[" __rseq_str(current_cpu_id) "]\n\t" \
0146 "cmpw cr7, %[" __rseq_str(cpu_id) "], %%r17\n\t" \
0147 "bne- cr7, " __rseq_str(label) "\n\t"
0148
0149 #define RSEQ_ASM_DEFINE_ABORT(label, abort_label) \
0150 ".pushsection __rseq_failure, \"ax\"\n\t" \
0151 ".long " __rseq_str(RSEQ_SIG) "\n\t" \
0152 __rseq_str(label) ":\n\t" \
0153 "b %l[" __rseq_str(abort_label) "]\n\t" \
0154 ".popsection\n\t"
0155
0156
0157
0158
0159
0160
0161 #define RSEQ_ASM_OP_CMPEQ(var, expect, label) \
0162 RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t" \
0163 RSEQ_CMP_LONG "cr7, %%r17, %[" __rseq_str(expect) "]\n\t" \
0164 "bne- cr7, " __rseq_str(label) "\n\t"
0165
0166 #define RSEQ_ASM_OP_CMPNE(var, expectnot, label) \
0167 RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t" \
0168 RSEQ_CMP_LONG "cr7, %%r17, %[" __rseq_str(expectnot) "]\n\t" \
0169 "beq- cr7, " __rseq_str(label) "\n\t"
0170
0171 #define RSEQ_ASM_OP_STORE(value, var) \
0172 RSEQ_STORE_LONG(var) "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n\t"
0173
0174
0175 #define RSEQ_ASM_OP_R_LOAD(var) \
0176 RSEQ_LOAD_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"
0177
0178
0179 #define RSEQ_ASM_OP_R_STORE(var) \
0180 RSEQ_STORE_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t"
0181
0182
0183 #define RSEQ_ASM_OP_R_ADD(count) \
0184 "add %%r17, %[" __rseq_str(count) "], %%r17\n\t"
0185
0186
0187 #define RSEQ_ASM_OP_R_LOADX(voffp) \
0188 RSEQ_LOADX_LONG "%%r17, %[" __rseq_str(voffp) "], %%r17\n\t"
0189
0190
0191 #define RSEQ_ASM_OP_R_MEMCPY() \
0192 RSEQ_CMP_LONG_INT "%%r19, 0\n\t" \
0193 "beq 333f\n\t" \
0194 "addi %%r20, %%r20, -1\n\t" \
0195 "addi %%r21, %%r21, -1\n\t" \
0196 "222:\n\t" \
0197 "lbzu %%r18, 1(%%r20)\n\t" \
0198 "stbu %%r18, 1(%%r21)\n\t" \
0199 "addi %%r19, %%r19, -1\n\t" \
0200 RSEQ_CMP_LONG_INT "%%r19, 0\n\t" \
0201 "bne 222b\n\t" \
0202 "333:\n\t" \
0203
0204 #define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label) \
0205 RSEQ_STORE_LONG(var) "%%r17, %[" __rseq_str(var) "]\n\t" \
0206 __rseq_str(post_commit_label) ":\n\t"
0207
0208 #define RSEQ_ASM_OP_FINAL_STORE(value, var, post_commit_label) \
0209 RSEQ_STORE_LONG(var) "%[" __rseq_str(value) "], %[" __rseq_str(var) "]\n\t" \
0210 __rseq_str(post_commit_label) ":\n\t"
0211
0212 static inline __attribute__((always_inline))
0213 int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
0214 {
0215 RSEQ_INJECT_C(9)
0216
0217 __asm__ __volatile__ goto (
0218 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f)
0219 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
0220 #ifdef RSEQ_COMPARE_TWICE
0221 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
0222 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
0223 #endif
0224
0225 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
0226
0227 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
0228 RSEQ_INJECT_ASM(3)
0229
0230 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
0231 RSEQ_INJECT_ASM(4)
0232 #ifdef RSEQ_COMPARE_TWICE
0233
0234 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
0235
0236 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
0237 #endif
0238
0239 RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
0240 RSEQ_INJECT_ASM(5)
0241 RSEQ_ASM_DEFINE_ABORT(4, abort)
0242 :
0243 : [cpu_id] "r" (cpu),
0244 [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
0245 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
0246 [v] "m" (*v),
0247 [expect] "r" (expect),
0248 [newv] "r" (newv)
0249 RSEQ_INJECT_INPUT
0250 : "memory", "cc", "r17"
0251 RSEQ_INJECT_CLOBBER
0252 : abort, cmpfail
0253 #ifdef RSEQ_COMPARE_TWICE
0254 , error1, error2
0255 #endif
0256 );
0257 rseq_after_asm_goto();
0258 return 0;
0259 abort:
0260 rseq_after_asm_goto();
0261 RSEQ_INJECT_FAILED
0262 return -1;
0263 cmpfail:
0264 rseq_after_asm_goto();
0265 return 1;
0266 #ifdef RSEQ_COMPARE_TWICE
0267 error1:
0268 rseq_after_asm_goto();
0269 rseq_bug("cpu_id comparison failed");
0270 error2:
0271 rseq_after_asm_goto();
0272 rseq_bug("expected value comparison failed");
0273 #endif
0274 }
0275
0276 static inline __attribute__((always_inline))
0277 int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
0278 long voffp, intptr_t *load, int cpu)
0279 {
0280 RSEQ_INJECT_C(9)
0281
0282 __asm__ __volatile__ goto (
0283 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f)
0284 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
0285 #ifdef RSEQ_COMPARE_TWICE
0286 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
0287 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
0288 #endif
0289
0290 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
0291
0292 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
0293 RSEQ_INJECT_ASM(3)
0294
0295 RSEQ_ASM_OP_CMPNE(v, expectnot, %l[cmpfail])
0296 RSEQ_INJECT_ASM(4)
0297 #ifdef RSEQ_COMPARE_TWICE
0298
0299 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
0300
0301 RSEQ_ASM_OP_CMPNE(v, expectnot, %l[error2])
0302 #endif
0303
0304 RSEQ_ASM_OP_R_LOAD(v)
0305
0306 RSEQ_ASM_OP_R_STORE(load)
0307
0308 RSEQ_ASM_OP_R_LOADX(voffp)
0309
0310 RSEQ_ASM_OP_R_FINAL_STORE(v, 2)
0311 RSEQ_INJECT_ASM(5)
0312 RSEQ_ASM_DEFINE_ABORT(4, abort)
0313 :
0314 : [cpu_id] "r" (cpu),
0315 [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
0316 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
0317
0318 [v] "m" (*v),
0319 [expectnot] "r" (expectnot),
0320 [voffp] "b" (voffp),
0321 [load] "m" (*load)
0322 RSEQ_INJECT_INPUT
0323 : "memory", "cc", "r17"
0324 RSEQ_INJECT_CLOBBER
0325 : abort, cmpfail
0326 #ifdef RSEQ_COMPARE_TWICE
0327 , error1, error2
0328 #endif
0329 );
0330 rseq_after_asm_goto();
0331 return 0;
0332 abort:
0333 rseq_after_asm_goto();
0334 RSEQ_INJECT_FAILED
0335 return -1;
0336 cmpfail:
0337 rseq_after_asm_goto();
0338 return 1;
0339 #ifdef RSEQ_COMPARE_TWICE
0340 error1:
0341 rseq_after_asm_goto();
0342 rseq_bug("cpu_id comparison failed");
0343 error2:
0344 rseq_after_asm_goto();
0345 rseq_bug("expected value comparison failed");
0346 #endif
0347 }
0348
0349 static inline __attribute__((always_inline))
0350 int rseq_addv(intptr_t *v, intptr_t count, int cpu)
0351 {
0352 RSEQ_INJECT_C(9)
0353
0354 __asm__ __volatile__ goto (
0355 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f)
0356 #ifdef RSEQ_COMPARE_TWICE
0357 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
0358 #endif
0359
0360 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
0361
0362 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
0363 RSEQ_INJECT_ASM(3)
0364 #ifdef RSEQ_COMPARE_TWICE
0365
0366 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
0367 #endif
0368
0369 RSEQ_ASM_OP_R_LOAD(v)
0370
0371 RSEQ_ASM_OP_R_ADD(count)
0372
0373 RSEQ_ASM_OP_R_FINAL_STORE(v, 2)
0374 RSEQ_INJECT_ASM(4)
0375 RSEQ_ASM_DEFINE_ABORT(4, abort)
0376 :
0377 : [cpu_id] "r" (cpu),
0378 [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
0379 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
0380
0381 [v] "m" (*v),
0382 [count] "r" (count)
0383 RSEQ_INJECT_INPUT
0384 : "memory", "cc", "r17"
0385 RSEQ_INJECT_CLOBBER
0386 : abort
0387 #ifdef RSEQ_COMPARE_TWICE
0388 , error1
0389 #endif
0390 );
0391 rseq_after_asm_goto();
0392 return 0;
0393 abort:
0394 rseq_after_asm_goto();
0395 RSEQ_INJECT_FAILED
0396 return -1;
0397 #ifdef RSEQ_COMPARE_TWICE
0398 error1:
0399 rseq_after_asm_goto();
0400 rseq_bug("cpu_id comparison failed");
0401 #endif
0402 }
0403
0404 static inline __attribute__((always_inline))
0405 int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
0406 intptr_t *v2, intptr_t newv2,
0407 intptr_t newv, int cpu)
0408 {
0409 RSEQ_INJECT_C(9)
0410
0411 __asm__ __volatile__ goto (
0412 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f)
0413 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
0414 #ifdef RSEQ_COMPARE_TWICE
0415 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
0416 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
0417 #endif
0418
0419 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
0420
0421 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
0422 RSEQ_INJECT_ASM(3)
0423
0424 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
0425 RSEQ_INJECT_ASM(4)
0426 #ifdef RSEQ_COMPARE_TWICE
0427
0428 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
0429
0430 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
0431 #endif
0432
0433 RSEQ_ASM_OP_STORE(newv2, v2)
0434 RSEQ_INJECT_ASM(5)
0435
0436 RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
0437 RSEQ_INJECT_ASM(6)
0438 RSEQ_ASM_DEFINE_ABORT(4, abort)
0439 :
0440 : [cpu_id] "r" (cpu),
0441 [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
0442 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
0443
0444 [v2] "m" (*v2),
0445 [newv2] "r" (newv2),
0446
0447 [v] "m" (*v),
0448 [expect] "r" (expect),
0449 [newv] "r" (newv)
0450 RSEQ_INJECT_INPUT
0451 : "memory", "cc", "r17"
0452 RSEQ_INJECT_CLOBBER
0453 : abort, cmpfail
0454 #ifdef RSEQ_COMPARE_TWICE
0455 , error1, error2
0456 #endif
0457 );
0458 rseq_after_asm_goto();
0459 return 0;
0460 abort:
0461 rseq_after_asm_goto();
0462 RSEQ_INJECT_FAILED
0463 return -1;
0464 cmpfail:
0465 rseq_after_asm_goto();
0466 return 1;
0467 #ifdef RSEQ_COMPARE_TWICE
0468 error1:
0469 rseq_after_asm_goto();
0470 rseq_bug("cpu_id comparison failed");
0471 error2:
0472 rseq_after_asm_goto();
0473 rseq_bug("expected value comparison failed");
0474 #endif
0475 }
0476
0477 static inline __attribute__((always_inline))
0478 int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
0479 intptr_t *v2, intptr_t newv2,
0480 intptr_t newv, int cpu)
0481 {
0482 RSEQ_INJECT_C(9)
0483
0484 __asm__ __volatile__ goto (
0485 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f)
0486 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
0487 #ifdef RSEQ_COMPARE_TWICE
0488 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
0489 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
0490 #endif
0491
0492 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
0493
0494 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
0495 RSEQ_INJECT_ASM(3)
0496
0497 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
0498 RSEQ_INJECT_ASM(4)
0499 #ifdef RSEQ_COMPARE_TWICE
0500
0501 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
0502
0503 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
0504 #endif
0505
0506 RSEQ_ASM_OP_STORE(newv2, v2)
0507 RSEQ_INJECT_ASM(5)
0508
0509 "lwsync\n\t"
0510
0511 RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
0512 RSEQ_INJECT_ASM(6)
0513 RSEQ_ASM_DEFINE_ABORT(4, abort)
0514 :
0515 : [cpu_id] "r" (cpu),
0516 [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
0517 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
0518
0519 [v2] "m" (*v2),
0520 [newv2] "r" (newv2),
0521
0522 [v] "m" (*v),
0523 [expect] "r" (expect),
0524 [newv] "r" (newv)
0525 RSEQ_INJECT_INPUT
0526 : "memory", "cc", "r17"
0527 RSEQ_INJECT_CLOBBER
0528 : abort, cmpfail
0529 #ifdef RSEQ_COMPARE_TWICE
0530 , error1, error2
0531 #endif
0532 );
0533 rseq_after_asm_goto();
0534 return 0;
0535 abort:
0536 rseq_after_asm_goto();
0537 RSEQ_INJECT_FAILED
0538 return -1;
0539 cmpfail:
0540 rseq_after_asm_goto();
0541 return 1;
0542 #ifdef RSEQ_COMPARE_TWICE
0543 error1:
0544 rseq_after_asm_goto();
0545 rseq_bug("cpu_id comparison failed");
0546 error2:
0547 rseq_after_asm_goto();
0548 rseq_bug("expected value comparison failed");
0549 #endif
0550 }
0551
0552 static inline __attribute__((always_inline))
0553 int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
0554 intptr_t *v2, intptr_t expect2,
0555 intptr_t newv, int cpu)
0556 {
0557 RSEQ_INJECT_C(9)
0558
0559 __asm__ __volatile__ goto (
0560 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f)
0561 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
0562 #ifdef RSEQ_COMPARE_TWICE
0563 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
0564 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
0565 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
0566 #endif
0567
0568 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
0569
0570 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
0571 RSEQ_INJECT_ASM(3)
0572
0573 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
0574 RSEQ_INJECT_ASM(4)
0575
0576 RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[cmpfail])
0577 RSEQ_INJECT_ASM(5)
0578 #ifdef RSEQ_COMPARE_TWICE
0579
0580 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
0581
0582 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
0583
0584 RSEQ_ASM_OP_CMPEQ(v2, expect2, %l[error3])
0585 #endif
0586
0587 RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
0588 RSEQ_INJECT_ASM(6)
0589 RSEQ_ASM_DEFINE_ABORT(4, abort)
0590 :
0591 : [cpu_id] "r" (cpu),
0592 [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
0593 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
0594
0595 [v2] "m" (*v2),
0596 [expect2] "r" (expect2),
0597
0598 [v] "m" (*v),
0599 [expect] "r" (expect),
0600 [newv] "r" (newv)
0601 RSEQ_INJECT_INPUT
0602 : "memory", "cc", "r17"
0603 RSEQ_INJECT_CLOBBER
0604 : abort, cmpfail
0605 #ifdef RSEQ_COMPARE_TWICE
0606 , error1, error2, error3
0607 #endif
0608 );
0609 rseq_after_asm_goto();
0610 return 0;
0611 abort:
0612 rseq_after_asm_goto();
0613 RSEQ_INJECT_FAILED
0614 return -1;
0615 cmpfail:
0616 rseq_after_asm_goto();
0617 return 1;
0618 #ifdef RSEQ_COMPARE_TWICE
0619 error1:
0620 rseq_after_asm_goto();
0621 rseq_bug("cpu_id comparison failed");
0622 error2:
0623 rseq_after_asm_goto();
0624 rseq_bug("1st expected value comparison failed");
0625 error3:
0626 rseq_after_asm_goto();
0627 rseq_bug("2nd expected value comparison failed");
0628 #endif
0629 }
0630
0631 static inline __attribute__((always_inline))
0632 int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
0633 void *dst, void *src, size_t len,
0634 intptr_t newv, int cpu)
0635 {
0636 RSEQ_INJECT_C(9)
0637
0638 __asm__ __volatile__ goto (
0639 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f)
0640 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
0641 #ifdef RSEQ_COMPARE_TWICE
0642 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
0643 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
0644 #endif
0645
0646 "mr %%r19, %[len]\n\t"
0647 "mr %%r20, %[src]\n\t"
0648 "mr %%r21, %[dst]\n\t"
0649
0650 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
0651
0652 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
0653 RSEQ_INJECT_ASM(3)
0654
0655 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
0656 RSEQ_INJECT_ASM(4)
0657 #ifdef RSEQ_COMPARE_TWICE
0658
0659 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
0660
0661 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
0662 #endif
0663
0664 RSEQ_ASM_OP_R_MEMCPY()
0665 RSEQ_INJECT_ASM(5)
0666
0667 RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
0668 RSEQ_INJECT_ASM(6)
0669
0670 RSEQ_ASM_DEFINE_ABORT(4, abort)
0671 :
0672 : [cpu_id] "r" (cpu),
0673 [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
0674 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
0675
0676 [v] "m" (*v),
0677 [expect] "r" (expect),
0678 [newv] "r" (newv),
0679
0680 [dst] "r" (dst),
0681 [src] "r" (src),
0682 [len] "r" (len)
0683 RSEQ_INJECT_INPUT
0684 : "memory", "cc", "r17", "r18", "r19", "r20", "r21"
0685 RSEQ_INJECT_CLOBBER
0686 : abort, cmpfail
0687 #ifdef RSEQ_COMPARE_TWICE
0688 , error1, error2
0689 #endif
0690 );
0691 rseq_after_asm_goto();
0692 return 0;
0693 abort:
0694 rseq_after_asm_goto();
0695 RSEQ_INJECT_FAILED
0696 return -1;
0697 cmpfail:
0698 rseq_after_asm_goto();
0699 return 1;
0700 #ifdef RSEQ_COMPARE_TWICE
0701 error1:
0702 rseq_after_asm_goto();
0703 rseq_bug("cpu_id comparison failed");
0704 error2:
0705 rseq_after_asm_goto();
0706 rseq_bug("expected value comparison failed");
0707 #endif
0708 }
0709
0710 static inline __attribute__((always_inline))
0711 int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
0712 void *dst, void *src, size_t len,
0713 intptr_t newv, int cpu)
0714 {
0715 RSEQ_INJECT_C(9)
0716
0717 __asm__ __volatile__ goto (
0718 RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f)
0719 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
0720 #ifdef RSEQ_COMPARE_TWICE
0721 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
0722 RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
0723 #endif
0724
0725 "mr %%r19, %[len]\n\t"
0726 "mr %%r20, %[src]\n\t"
0727 "mr %%r21, %[dst]\n\t"
0728
0729 RSEQ_ASM_STORE_RSEQ_CS(1, 3b, rseq_cs)
0730
0731 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
0732 RSEQ_INJECT_ASM(3)
0733
0734 RSEQ_ASM_OP_CMPEQ(v, expect, %l[cmpfail])
0735 RSEQ_INJECT_ASM(4)
0736 #ifdef RSEQ_COMPARE_TWICE
0737
0738 RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
0739
0740 RSEQ_ASM_OP_CMPEQ(v, expect, %l[error2])
0741 #endif
0742
0743 RSEQ_ASM_OP_R_MEMCPY()
0744 RSEQ_INJECT_ASM(5)
0745
0746 "lwsync\n\t"
0747
0748 RSEQ_ASM_OP_FINAL_STORE(newv, v, 2)
0749 RSEQ_INJECT_ASM(6)
0750
0751 RSEQ_ASM_DEFINE_ABORT(4, abort)
0752 :
0753 : [cpu_id] "r" (cpu),
0754 [current_cpu_id] "m" (rseq_get_abi()->cpu_id),
0755 [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
0756
0757 [v] "m" (*v),
0758 [expect] "r" (expect),
0759 [newv] "r" (newv),
0760
0761 [dst] "r" (dst),
0762 [src] "r" (src),
0763 [len] "r" (len)
0764 RSEQ_INJECT_INPUT
0765 : "memory", "cc", "r17", "r18", "r19", "r20", "r21"
0766 RSEQ_INJECT_CLOBBER
0767 : abort, cmpfail
0768 #ifdef RSEQ_COMPARE_TWICE
0769 , error1, error2
0770 #endif
0771 );
0772 rseq_after_asm_goto();
0773 return 0;
0774 abort:
0775 rseq_after_asm_goto();
0776 RSEQ_INJECT_FAILED
0777 return -1;
0778 cmpfail:
0779 rseq_after_asm_goto();
0780 return 1;
0781 #ifdef RSEQ_COMPARE_TWICE
0782 error1:
0783 rseq_after_asm_goto();
0784 rseq_bug("cpu_id comparison failed");
0785 error2:
0786 rseq_after_asm_goto();
0787 rseq_bug("expected value comparison failed");
0788 #endif
0789 }
0790
0791 #endif