rseq-arm-bits.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2. /*
  3. * rseq-arm-bits.h
  4. *
  5. * (C) Copyright 2016-2022 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  6. */
  7. #include "rseq-bits-template.h"
  8. #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \
  9. (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
  10. static inline __attribute__((always_inline))
  11. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev)(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
  12. {
  13. RSEQ_INJECT_C(9)
  14. __asm__ __volatile__ goto (
  15. RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
  16. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
  17. #ifdef RSEQ_COMPARE_TWICE
  18. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
  19. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
  20. #endif
  21. /* Start rseq by storing table entry pointer into rseq_cs. */
  22. RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
  23. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  24. RSEQ_INJECT_ASM(3)
  25. "ldr r0, %[v]\n\t"
  26. "cmp %[expect], r0\n\t"
  27. "bne %l[cmpfail]\n\t"
  28. RSEQ_INJECT_ASM(4)
  29. #ifdef RSEQ_COMPARE_TWICE
  30. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  31. "ldr r0, %[v]\n\t"
  32. "cmp %[expect], r0\n\t"
  33. "bne %l[error2]\n\t"
  34. #endif
  35. /* final store */
  36. "str %[newv], %[v]\n\t"
  37. "2:\n\t"
  38. RSEQ_INJECT_ASM(5)
  39. "b 5f\n\t"
  40. RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
  41. "5:\n\t"
  42. : /* gcc asm goto does not allow outputs */
  43. : [cpu_id] "r" (cpu),
  44. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  45. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  46. [v] "m" (*v),
  47. [expect] "r" (expect),
  48. [newv] "r" (newv)
  49. RSEQ_INJECT_INPUT
  50. : "r0", "memory", "cc"
  51. RSEQ_INJECT_CLOBBER
  52. : abort, cmpfail
  53. #ifdef RSEQ_COMPARE_TWICE
  54. , error1, error2
  55. #endif
  56. );
  57. rseq_after_asm_goto();
  58. return 0;
  59. abort:
  60. rseq_after_asm_goto();
  61. RSEQ_INJECT_FAILED
  62. return -1;
  63. cmpfail:
  64. rseq_after_asm_goto();
  65. return 1;
  66. #ifdef RSEQ_COMPARE_TWICE
  67. error1:
  68. rseq_after_asm_goto();
  69. rseq_bug("cpu_id comparison failed");
  70. error2:
  71. rseq_after_asm_goto();
  72. rseq_bug("expected value comparison failed");
  73. #endif
  74. }
  75. static inline __attribute__((always_inline))
  76. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load)(intptr_t *v, intptr_t expectnot,
  77. long voffp, intptr_t *load, int cpu)
  78. {
  79. RSEQ_INJECT_C(9)
  80. __asm__ __volatile__ goto (
  81. RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
  82. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
  83. #ifdef RSEQ_COMPARE_TWICE
  84. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
  85. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
  86. #endif
  87. /* Start rseq by storing table entry pointer into rseq_cs. */
  88. RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
  89. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  90. RSEQ_INJECT_ASM(3)
  91. "ldr r0, %[v]\n\t"
  92. "cmp %[expectnot], r0\n\t"
  93. "beq %l[cmpfail]\n\t"
  94. RSEQ_INJECT_ASM(4)
  95. #ifdef RSEQ_COMPARE_TWICE
  96. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  97. "ldr r0, %[v]\n\t"
  98. "cmp %[expectnot], r0\n\t"
  99. "beq %l[error2]\n\t"
  100. #endif
  101. "str r0, %[load]\n\t"
  102. "add r0, %[voffp]\n\t"
  103. "ldr r0, [r0]\n\t"
  104. /* final store */
  105. "str r0, %[v]\n\t"
  106. "2:\n\t"
  107. RSEQ_INJECT_ASM(5)
  108. "b 5f\n\t"
  109. RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
  110. "5:\n\t"
  111. : /* gcc asm goto does not allow outputs */
  112. : [cpu_id] "r" (cpu),
  113. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  114. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  115. /* final store input */
  116. [v] "m" (*v),
  117. [expectnot] "r" (expectnot),
  118. [voffp] "Ir" (voffp),
  119. [load] "m" (*load)
  120. RSEQ_INJECT_INPUT
  121. : "r0", "memory", "cc"
  122. RSEQ_INJECT_CLOBBER
  123. : abort, cmpfail
  124. #ifdef RSEQ_COMPARE_TWICE
  125. , error1, error2
  126. #endif
  127. );
  128. rseq_after_asm_goto();
  129. return 0;
  130. abort:
  131. rseq_after_asm_goto();
  132. RSEQ_INJECT_FAILED
  133. return -1;
  134. cmpfail:
  135. rseq_after_asm_goto();
  136. return 1;
  137. #ifdef RSEQ_COMPARE_TWICE
  138. error1:
  139. rseq_after_asm_goto();
  140. rseq_bug("cpu_id comparison failed");
  141. error2:
  142. rseq_after_asm_goto();
  143. rseq_bug("expected value comparison failed");
  144. #endif
  145. }
  146. static inline __attribute__((always_inline))
  147. int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv)(intptr_t *v, intptr_t count, int cpu)
  148. {
  149. RSEQ_INJECT_C(9)
  150. __asm__ __volatile__ goto (
  151. RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
  152. #ifdef RSEQ_COMPARE_TWICE
  153. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
  154. #endif
  155. /* Start rseq by storing table entry pointer into rseq_cs. */
  156. RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
  157. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  158. RSEQ_INJECT_ASM(3)
  159. #ifdef RSEQ_COMPARE_TWICE
  160. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  161. #endif
  162. "ldr r0, %[v]\n\t"
  163. "add r0, %[count]\n\t"
  164. /* final store */
  165. "str r0, %[v]\n\t"
  166. "2:\n\t"
  167. RSEQ_INJECT_ASM(4)
  168. "b 5f\n\t"
  169. RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
  170. "5:\n\t"
  171. : /* gcc asm goto does not allow outputs */
  172. : [cpu_id] "r" (cpu),
  173. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  174. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  175. [v] "m" (*v),
  176. [count] "Ir" (count)
  177. RSEQ_INJECT_INPUT
  178. : "r0", "memory", "cc"
  179. RSEQ_INJECT_CLOBBER
  180. : abort
  181. #ifdef RSEQ_COMPARE_TWICE
  182. , error1
  183. #endif
  184. );
  185. rseq_after_asm_goto();
  186. return 0;
  187. abort:
  188. rseq_after_asm_goto();
  189. RSEQ_INJECT_FAILED
  190. return -1;
  191. #ifdef RSEQ_COMPARE_TWICE
  192. error1:
  193. rseq_after_asm_goto();
  194. rseq_bug("cpu_id comparison failed");
  195. #endif
  196. }
  197. static inline __attribute__((always_inline))
  198. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev)(intptr_t *v, intptr_t expect,
  199. intptr_t *v2, intptr_t expect2,
  200. intptr_t newv, int cpu)
  201. {
  202. RSEQ_INJECT_C(9)
  203. __asm__ __volatile__ goto (
  204. RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
  205. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
  206. #ifdef RSEQ_COMPARE_TWICE
  207. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
  208. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
  209. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error3])
  210. #endif
  211. /* Start rseq by storing table entry pointer into rseq_cs. */
  212. RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
  213. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  214. RSEQ_INJECT_ASM(3)
  215. "ldr r0, %[v]\n\t"
  216. "cmp %[expect], r0\n\t"
  217. "bne %l[cmpfail]\n\t"
  218. RSEQ_INJECT_ASM(4)
  219. "ldr r0, %[v2]\n\t"
  220. "cmp %[expect2], r0\n\t"
  221. "bne %l[cmpfail]\n\t"
  222. RSEQ_INJECT_ASM(5)
  223. #ifdef RSEQ_COMPARE_TWICE
  224. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  225. "ldr r0, %[v]\n\t"
  226. "cmp %[expect], r0\n\t"
  227. "bne %l[error2]\n\t"
  228. "ldr r0, %[v2]\n\t"
  229. "cmp %[expect2], r0\n\t"
  230. "bne %l[error3]\n\t"
  231. #endif
  232. /* final store */
  233. "str %[newv], %[v]\n\t"
  234. "2:\n\t"
  235. RSEQ_INJECT_ASM(6)
  236. "b 5f\n\t"
  237. RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
  238. "5:\n\t"
  239. : /* gcc asm goto does not allow outputs */
  240. : [cpu_id] "r" (cpu),
  241. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  242. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  243. /* cmp2 input */
  244. [v2] "m" (*v2),
  245. [expect2] "r" (expect2),
  246. /* final store input */
  247. [v] "m" (*v),
  248. [expect] "r" (expect),
  249. [newv] "r" (newv)
  250. RSEQ_INJECT_INPUT
  251. : "r0", "memory", "cc"
  252. RSEQ_INJECT_CLOBBER
  253. : abort, cmpfail
  254. #ifdef RSEQ_COMPARE_TWICE
  255. , error1, error2, error3
  256. #endif
  257. );
  258. rseq_after_asm_goto();
  259. return 0;
  260. abort:
  261. rseq_after_asm_goto();
  262. RSEQ_INJECT_FAILED
  263. return -1;
  264. cmpfail:
  265. rseq_after_asm_goto();
  266. return 1;
  267. #ifdef RSEQ_COMPARE_TWICE
  268. error1:
  269. rseq_after_asm_goto();
  270. rseq_bug("cpu_id comparison failed");
  271. error2:
  272. rseq_after_asm_goto();
  273. rseq_bug("1st expected value comparison failed");
  274. error3:
  275. rseq_after_asm_goto();
  276. rseq_bug("2nd expected value comparison failed");
  277. #endif
  278. }
  279. #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) &&
  280. (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
  281. #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \
  282. (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
  283. static inline __attribute__((always_inline))
  284. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev)(intptr_t *v, intptr_t expect,
  285. intptr_t *v2, intptr_t newv2,
  286. intptr_t newv, int cpu)
  287. {
  288. RSEQ_INJECT_C(9)
  289. __asm__ __volatile__ goto (
  290. RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
  291. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
  292. #ifdef RSEQ_COMPARE_TWICE
  293. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
  294. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
  295. #endif
  296. /* Start rseq by storing table entry pointer into rseq_cs. */
  297. RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
  298. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  299. RSEQ_INJECT_ASM(3)
  300. "ldr r0, %[v]\n\t"
  301. "cmp %[expect], r0\n\t"
  302. "bne %l[cmpfail]\n\t"
  303. RSEQ_INJECT_ASM(4)
  304. #ifdef RSEQ_COMPARE_TWICE
  305. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, %l[error1])
  306. "ldr r0, %[v]\n\t"
  307. "cmp %[expect], r0\n\t"
  308. "bne %l[error2]\n\t"
  309. #endif
  310. /* try store */
  311. "str %[newv2], %[v2]\n\t"
  312. RSEQ_INJECT_ASM(5)
  313. #ifdef RSEQ_TEMPLATE_MO_RELEASE
  314. "dmb\n\t" /* full mb provides store-release */
  315. #endif
  316. /* final store */
  317. "str %[newv], %[v]\n\t"
  318. "2:\n\t"
  319. RSEQ_INJECT_ASM(6)
  320. "b 5f\n\t"
  321. RSEQ_ASM_DEFINE_ABORT(3, 4, "", abort, 1b, 2b, 4f)
  322. "5:\n\t"
  323. : /* gcc asm goto does not allow outputs */
  324. : [cpu_id] "r" (cpu),
  325. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  326. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  327. /* try store input */
  328. [v2] "m" (*v2),
  329. [newv2] "r" (newv2),
  330. /* final store input */
  331. [v] "m" (*v),
  332. [expect] "r" (expect),
  333. [newv] "r" (newv)
  334. RSEQ_INJECT_INPUT
  335. : "r0", "memory", "cc"
  336. RSEQ_INJECT_CLOBBER
  337. : abort, cmpfail
  338. #ifdef RSEQ_COMPARE_TWICE
  339. , error1, error2
  340. #endif
  341. );
  342. rseq_after_asm_goto();
  343. return 0;
  344. abort:
  345. rseq_after_asm_goto();
  346. RSEQ_INJECT_FAILED
  347. return -1;
  348. cmpfail:
  349. rseq_after_asm_goto();
  350. return 1;
  351. #ifdef RSEQ_COMPARE_TWICE
  352. error1:
  353. rseq_after_asm_goto();
  354. rseq_bug("cpu_id comparison failed");
  355. error2:
  356. rseq_after_asm_goto();
  357. rseq_bug("expected value comparison failed");
  358. #endif
  359. }
  360. static inline __attribute__((always_inline))
  361. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev)(intptr_t *v, intptr_t expect,
  362. void *dst, void *src, size_t len,
  363. intptr_t newv, int cpu)
  364. {
  365. uint32_t rseq_scratch[3];
  366. RSEQ_INJECT_C(9)
  367. __asm__ __volatile__ goto (
  368. RSEQ_ASM_DEFINE_TABLE(9, 1f, 2f, 4f) /* start, commit, abort */
  369. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[cmpfail])
  370. #ifdef RSEQ_COMPARE_TWICE
  371. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
  372. RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error2])
  373. #endif
  374. "str %[src], %[rseq_scratch0]\n\t"
  375. "str %[dst], %[rseq_scratch1]\n\t"
  376. "str %[len], %[rseq_scratch2]\n\t"
  377. /* Start rseq by storing table entry pointer into rseq_cs. */
  378. RSEQ_ASM_STORE_RSEQ_CS(1, 3f, rseq_cs)
  379. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  380. RSEQ_INJECT_ASM(3)
  381. "ldr r0, %[v]\n\t"
  382. "cmp %[expect], r0\n\t"
  383. "bne 5f\n\t"
  384. RSEQ_INJECT_ASM(4)
  385. #ifdef RSEQ_COMPARE_TWICE
  386. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 6f)
  387. "ldr r0, %[v]\n\t"
  388. "cmp %[expect], r0\n\t"
  389. "bne 7f\n\t"
  390. #endif
  391. /* try memcpy */
  392. "cmp %[len], #0\n\t" \
  393. "beq 333f\n\t" \
  394. "222:\n\t" \
  395. "ldrb %%r0, [%[src]]\n\t" \
  396. "strb %%r0, [%[dst]]\n\t" \
  397. "adds %[src], #1\n\t" \
  398. "adds %[dst], #1\n\t" \
  399. "subs %[len], #1\n\t" \
  400. "bne 222b\n\t" \
  401. "333:\n\t" \
  402. RSEQ_INJECT_ASM(5)
  403. #ifdef RSEQ_TEMPLATE_MO_RELEASE
  404. "dmb\n\t" /* full mb provides store-release */
  405. #endif
  406. /* final store */
  407. "str %[newv], %[v]\n\t"
  408. "2:\n\t"
  409. RSEQ_INJECT_ASM(6)
  410. /* teardown */
  411. "ldr %[len], %[rseq_scratch2]\n\t"
  412. "ldr %[dst], %[rseq_scratch1]\n\t"
  413. "ldr %[src], %[rseq_scratch0]\n\t"
  414. "b 8f\n\t"
  415. RSEQ_ASM_DEFINE_ABORT(3, 4,
  416. /* teardown */
  417. "ldr %[len], %[rseq_scratch2]\n\t"
  418. "ldr %[dst], %[rseq_scratch1]\n\t"
  419. "ldr %[src], %[rseq_scratch0]\n\t",
  420. abort, 1b, 2b, 4f)
  421. RSEQ_ASM_DEFINE_CMPFAIL(5,
  422. /* teardown */
  423. "ldr %[len], %[rseq_scratch2]\n\t"
  424. "ldr %[dst], %[rseq_scratch1]\n\t"
  425. "ldr %[src], %[rseq_scratch0]\n\t",
  426. cmpfail)
  427. #ifdef RSEQ_COMPARE_TWICE
  428. RSEQ_ASM_DEFINE_CMPFAIL(6,
  429. /* teardown */
  430. "ldr %[len], %[rseq_scratch2]\n\t"
  431. "ldr %[dst], %[rseq_scratch1]\n\t"
  432. "ldr %[src], %[rseq_scratch0]\n\t",
  433. error1)
  434. RSEQ_ASM_DEFINE_CMPFAIL(7,
  435. /* teardown */
  436. "ldr %[len], %[rseq_scratch2]\n\t"
  437. "ldr %[dst], %[rseq_scratch1]\n\t"
  438. "ldr %[src], %[rseq_scratch0]\n\t",
  439. error2)
  440. #endif
  441. "8:\n\t"
  442. : /* gcc asm goto does not allow outputs */
  443. : [cpu_id] "r" (cpu),
  444. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  445. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  446. /* final store input */
  447. [v] "m" (*v),
  448. [expect] "r" (expect),
  449. [newv] "r" (newv),
  450. /* try memcpy input */
  451. [dst] "r" (dst),
  452. [src] "r" (src),
  453. [len] "r" (len),
  454. [rseq_scratch0] "m" (rseq_scratch[0]),
  455. [rseq_scratch1] "m" (rseq_scratch[1]),
  456. [rseq_scratch2] "m" (rseq_scratch[2])
  457. RSEQ_INJECT_INPUT
  458. : "r0", "memory", "cc"
  459. RSEQ_INJECT_CLOBBER
  460. : abort, cmpfail
  461. #ifdef RSEQ_COMPARE_TWICE
  462. , error1, error2
  463. #endif
  464. );
  465. rseq_after_asm_goto();
  466. return 0;
  467. abort:
  468. rseq_after_asm_goto();
  469. RSEQ_INJECT_FAILED
  470. return -1;
  471. cmpfail:
  472. rseq_after_asm_goto();
  473. return 1;
  474. #ifdef RSEQ_COMPARE_TWICE
  475. error1:
  476. rseq_after_asm_goto();
  477. rseq_bug("cpu_id comparison failed");
  478. error2:
  479. rseq_after_asm_goto();
  480. rseq_bug("expected value comparison failed");
  481. #endif
  482. }
  483. #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) &&
  484. (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
  485. #include "rseq-bits-reset.h"