rseq-riscv-bits.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2. #include "rseq-bits-template.h"
  3. #if defined(RSEQ_TEMPLATE_MO_RELAXED) && \
  4. (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
  5. static inline __always_inline
  6. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_storev)(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
  7. {
  8. RSEQ_INJECT_C(9)
  9. __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
  10. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
  11. #ifdef RSEQ_COMPARE_TWICE
  12. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
  13. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
  14. #endif
  15. RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
  16. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  17. RSEQ_INJECT_ASM(3)
  18. RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
  19. RSEQ_INJECT_ASM(4)
  20. #ifdef RSEQ_COMPARE_TWICE
  21. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
  22. RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
  23. #endif
  24. RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
  25. RSEQ_INJECT_ASM(5)
  26. RSEQ_ASM_DEFINE_ABORT(4, abort)
  27. : /* gcc asm goto does not allow outputs */
  28. : [cpu_id] "r" (cpu),
  29. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  30. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  31. [v] "m" (*v),
  32. [expect] "r" (expect),
  33. [newv] "r" (newv)
  34. RSEQ_INJECT_INPUT
  35. : "memory", RSEQ_ASM_TMP_REG_1
  36. RSEQ_INJECT_CLOBBER
  37. : abort, cmpfail
  38. #ifdef RSEQ_COMPARE_TWICE
  39. , error1, error2
  40. #endif
  41. );
  42. return 0;
  43. abort:
  44. RSEQ_INJECT_FAILED
  45. return -1;
  46. cmpfail:
  47. return 1;
  48. #ifdef RSEQ_COMPARE_TWICE
  49. error1:
  50. rseq_bug("cpu_id comparison failed");
  51. error2:
  52. rseq_bug("expected value comparison failed");
  53. #endif
  54. }
  55. static inline __always_inline
  56. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpnev_storeoffp_load)(intptr_t *v, intptr_t expectnot,
  57. off_t voffp, intptr_t *load, int cpu)
  58. {
  59. RSEQ_INJECT_C(9)
  60. __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
  61. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
  62. #ifdef RSEQ_COMPARE_TWICE
  63. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
  64. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
  65. #endif
  66. RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
  67. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  68. RSEQ_INJECT_ASM(3)
  69. RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[cmpfail]")
  70. RSEQ_INJECT_ASM(4)
  71. #ifdef RSEQ_COMPARE_TWICE
  72. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
  73. RSEQ_ASM_OP_CMPNE(v, expectnot, "%l[error2]")
  74. #endif
  75. RSEQ_ASM_OP_R_LOAD(v)
  76. RSEQ_ASM_OP_R_STORE(load)
  77. RSEQ_ASM_OP_R_LOAD_OFF(voffp)
  78. RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
  79. RSEQ_INJECT_ASM(5)
  80. RSEQ_ASM_DEFINE_ABORT(4, abort)
  81. : /* gcc asm goto does not allow outputs */
  82. : [cpu_id] "r" (cpu),
  83. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  84. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  85. [v] "m" (*v),
  86. [expectnot] "r" (expectnot),
  87. [load] "m" (*load),
  88. [voffp] "r" (voffp)
  89. RSEQ_INJECT_INPUT
  90. : "memory", RSEQ_ASM_TMP_REG_1
  91. RSEQ_INJECT_CLOBBER
  92. : abort, cmpfail
  93. #ifdef RSEQ_COMPARE_TWICE
  94. , error1, error2
  95. #endif
  96. );
  97. return 0;
  98. abort:
  99. RSEQ_INJECT_FAILED
  100. return -1;
  101. cmpfail:
  102. return 1;
  103. #ifdef RSEQ_COMPARE_TWICE
  104. error1:
  105. rseq_bug("cpu_id comparison failed");
  106. error2:
  107. rseq_bug("expected value comparison failed");
  108. #endif
  109. }
  110. static inline __always_inline
  111. int RSEQ_TEMPLATE_IDENTIFIER(rseq_addv)(intptr_t *v, intptr_t count, int cpu)
  112. {
  113. RSEQ_INJECT_C(9)
  114. __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
  115. #ifdef RSEQ_COMPARE_TWICE
  116. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
  117. #endif
  118. RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
  119. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  120. RSEQ_INJECT_ASM(3)
  121. #ifdef RSEQ_COMPARE_TWICE
  122. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
  123. #endif
  124. RSEQ_ASM_OP_R_LOAD(v)
  125. RSEQ_ASM_OP_R_ADD(count)
  126. RSEQ_ASM_OP_R_FINAL_STORE(v, 3)
  127. RSEQ_INJECT_ASM(4)
  128. RSEQ_ASM_DEFINE_ABORT(4, abort)
  129. : /* gcc asm goto does not allow outputs */
  130. : [cpu_id] "r" (cpu),
  131. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  132. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  133. [v] "m" (*v),
  134. [count] "r" (count)
  135. RSEQ_INJECT_INPUT
  136. : "memory", RSEQ_ASM_TMP_REG_1
  137. RSEQ_INJECT_CLOBBER
  138. : abort
  139. #ifdef RSEQ_COMPARE_TWICE
  140. , error1
  141. #endif
  142. );
  143. return 0;
  144. abort:
  145. RSEQ_INJECT_FAILED
  146. return -1;
  147. #ifdef RSEQ_COMPARE_TWICE
  148. error1:
  149. rseq_bug("cpu_id comparison failed");
  150. #endif
  151. }
  152. static inline __always_inline
  153. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_cmpeqv_storev)(intptr_t *v, intptr_t expect,
  154. intptr_t *v2, intptr_t expect2,
  155. intptr_t newv, int cpu)
  156. {
  157. RSEQ_INJECT_C(9)
  158. __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
  159. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
  160. #ifdef RSEQ_COMPARE_TWICE
  161. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
  162. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
  163. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error3]")
  164. #endif
  165. RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
  166. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  167. RSEQ_INJECT_ASM(3)
  168. RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
  169. RSEQ_INJECT_ASM(4)
  170. RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[cmpfail]")
  171. RSEQ_INJECT_ASM(5)
  172. #ifdef RSEQ_COMPARE_TWICE
  173. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
  174. RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
  175. RSEQ_ASM_OP_CMPEQ(v2, expect2, "%l[error3]")
  176. #endif
  177. RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
  178. RSEQ_INJECT_ASM(6)
  179. RSEQ_ASM_DEFINE_ABORT(4, abort)
  180. : /* gcc asm goto does not allow outputs */
  181. : [cpu_id] "r" (cpu),
  182. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  183. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  184. [v] "m" (*v),
  185. [expect] "r" (expect),
  186. [v2] "m" (*v2),
  187. [expect2] "r" (expect2),
  188. [newv] "r" (newv)
  189. RSEQ_INJECT_INPUT
  190. : "memory", RSEQ_ASM_TMP_REG_1
  191. RSEQ_INJECT_CLOBBER
  192. : abort, cmpfail
  193. #ifdef RSEQ_COMPARE_TWICE
  194. , error1, error2, error3
  195. #endif
  196. );
  197. return 0;
  198. abort:
  199. RSEQ_INJECT_FAILED
  200. return -1;
  201. cmpfail:
  202. return 1;
  203. #ifdef RSEQ_COMPARE_TWICE
  204. error1:
  205. rseq_bug("cpu_id comparison failed");
  206. error2:
  207. rseq_bug("expected value comparison failed");
  208. error3:
  209. rseq_bug("2nd expected value comparison failed");
  210. #endif
  211. }
  212. #define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
  213. /*
  214. * pval = *(ptr+off)
  215. * *pval += inc;
  216. */
  217. static inline __always_inline
  218. int RSEQ_TEMPLATE_IDENTIFIER(rseq_offset_deref_addv)(intptr_t *ptr, off_t off, intptr_t inc, int cpu)
  219. {
  220. RSEQ_INJECT_C(9)
  221. __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
  222. #ifdef RSEQ_COMPARE_TWICE
  223. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
  224. #endif
  225. RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
  226. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  227. RSEQ_INJECT_ASM(3)
  228. #ifdef RSEQ_COMPARE_TWICE
  229. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
  230. #endif
  231. RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, inc, 3)
  232. RSEQ_INJECT_ASM(4)
  233. RSEQ_ASM_DEFINE_ABORT(4, abort)
  234. : /* gcc asm goto does not allow outputs */
  235. : [cpu_id] "r" (cpu),
  236. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  237. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  238. [ptr] "r" (ptr),
  239. [off] "r" (off),
  240. [inc] "r" (inc)
  241. RSEQ_INJECT_INPUT
  242. : "memory", RSEQ_ASM_TMP_REG_1
  243. RSEQ_INJECT_CLOBBER
  244. : abort
  245. #ifdef RSEQ_COMPARE_TWICE
  246. , error1
  247. #endif
  248. );
  249. return 0;
  250. abort:
  251. RSEQ_INJECT_FAILED
  252. return -1;
  253. #ifdef RSEQ_COMPARE_TWICE
  254. error1:
  255. rseq_bug("cpu_id comparison failed");
  256. #endif
  257. }
  258. #endif /* #if defined(RSEQ_TEMPLATE_MO_RELAXED) &&
  259. (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
  260. #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) && \
  261. (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID))
  262. static inline __always_inline
  263. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trystorev_storev)(intptr_t *v, intptr_t expect,
  264. intptr_t *v2, intptr_t newv2,
  265. intptr_t newv, int cpu)
  266. {
  267. RSEQ_INJECT_C(9)
  268. __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
  269. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
  270. #ifdef RSEQ_COMPARE_TWICE
  271. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
  272. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
  273. #endif
  274. RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
  275. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  276. RSEQ_INJECT_ASM(3)
  277. RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
  278. RSEQ_INJECT_ASM(4)
  279. #ifdef RSEQ_COMPARE_TWICE
  280. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
  281. RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
  282. #endif
  283. RSEQ_ASM_OP_STORE(newv2, v2)
  284. RSEQ_INJECT_ASM(5)
  285. #ifdef RSEQ_TEMPLATE_MO_RELEASE
  286. RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3)
  287. #else
  288. RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
  289. #endif
  290. RSEQ_INJECT_ASM(6)
  291. RSEQ_ASM_DEFINE_ABORT(4, abort)
  292. : /* gcc asm goto does not allow outputs */
  293. : [cpu_id] "r" (cpu),
  294. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  295. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  296. [expect] "r" (expect),
  297. [v] "m" (*v),
  298. [newv] "r" (newv),
  299. [v2] "m" (*v2),
  300. [newv2] "r" (newv2)
  301. RSEQ_INJECT_INPUT
  302. : "memory", RSEQ_ASM_TMP_REG_1
  303. RSEQ_INJECT_CLOBBER
  304. : abort, cmpfail
  305. #ifdef RSEQ_COMPARE_TWICE
  306. , error1, error2
  307. #endif
  308. );
  309. return 0;
  310. abort:
  311. RSEQ_INJECT_FAILED
  312. return -1;
  313. cmpfail:
  314. return 1;
  315. #ifdef RSEQ_COMPARE_TWICE
  316. error1:
  317. rseq_bug("cpu_id comparison failed");
  318. error2:
  319. rseq_bug("expected value comparison failed");
  320. #endif
  321. }
  322. static inline __always_inline
  323. int RSEQ_TEMPLATE_IDENTIFIER(rseq_cmpeqv_trymemcpy_storev)(intptr_t *v, intptr_t expect,
  324. void *dst, void *src, size_t len,
  325. intptr_t newv, int cpu)
  326. {
  327. RSEQ_INJECT_C(9)
  328. __asm__ __volatile__ goto(RSEQ_ASM_DEFINE_TABLE(1, 2f, 3f, 4f)
  329. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[cmpfail]")
  330. #ifdef RSEQ_COMPARE_TWICE
  331. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error1]")
  332. RSEQ_ASM_DEFINE_EXIT_POINT(2f, "%l[error2]")
  333. #endif
  334. RSEQ_ASM_STORE_RSEQ_CS(2, 1b, rseq_cs)
  335. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, 4f)
  336. RSEQ_INJECT_ASM(3)
  337. RSEQ_ASM_OP_CMPEQ(v, expect, "%l[cmpfail]")
  338. RSEQ_INJECT_ASM(4)
  339. #ifdef RSEQ_COMPARE_TWICE
  340. RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, "%l[error1]")
  341. RSEQ_ASM_OP_CMPEQ(v, expect, "%l[error2]")
  342. #endif
  343. RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len)
  344. RSEQ_INJECT_ASM(5)
  345. #ifdef RSEQ_TEMPLATE_MO_RELEASE
  346. RSEQ_ASM_OP_FINAL_STORE_RELEASE(newv, v, 3)
  347. #else
  348. RSEQ_ASM_OP_FINAL_STORE(newv, v, 3)
  349. #endif
  350. RSEQ_INJECT_ASM(6)
  351. RSEQ_ASM_DEFINE_ABORT(4, abort)
  352. : /* gcc asm goto does not allow outputs */
  353. : [cpu_id] "r" (cpu),
  354. [current_cpu_id] "m" (rseq_get_abi()->RSEQ_TEMPLATE_CPU_ID_FIELD),
  355. [rseq_cs] "m" (rseq_get_abi()->rseq_cs.arch.ptr),
  356. [expect] "r" (expect),
  357. [v] "m" (*v),
  358. [newv] "r" (newv),
  359. [dst] "r" (dst),
  360. [src] "r" (src),
  361. [len] "r" (len)
  362. RSEQ_INJECT_INPUT
  363. : "memory", RSEQ_ASM_TMP_REG_1, RSEQ_ASM_TMP_REG_2,
  364. RSEQ_ASM_TMP_REG_3, RSEQ_ASM_TMP_REG_4
  365. RSEQ_INJECT_CLOBBER
  366. : abort, cmpfail
  367. #ifdef RSEQ_COMPARE_TWICE
  368. , error1, error2
  369. #endif
  370. );
  371. return 0;
  372. abort:
  373. RSEQ_INJECT_FAILED
  374. return -1;
  375. cmpfail:
  376. return 1;
  377. #ifdef RSEQ_COMPARE_TWICE
  378. error1:
  379. rseq_bug("cpu_id comparison failed");
  380. error2:
  381. rseq_bug("expected value comparison failed");
  382. #endif
  383. }
  384. #endif /* #if (defined(RSEQ_TEMPLATE_MO_RELAXED) || defined(RSEQ_TEMPLATE_MO_RELEASE)) &&
  385. (defined(RSEQ_TEMPLATE_CPU_ID) || defined(RSEQ_TEMPLATE_MM_CID)) */
  386. #include "rseq-bits-reset.h"