rseq-or1k.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2. /*
  3. * Select the instruction "l.nop 0x35" as the RSEQ_SIG.
  4. */
  5. #define RSEQ_SIG 0x15000035
  6. #define rseq_smp_mb() __asm__ __volatile__ ("l.msync" ::: "memory")
  7. #define rseq_smp_rmb() rseq_smp_mb()
  8. #define rseq_smp_wmb() rseq_smp_mb()
  9. #define RSEQ_ASM_TMP_REG_1 "r31"
  10. #define RSEQ_ASM_TMP_REG_2 "r29"
  11. #define RSEQ_ASM_TMP_REG_3 "r27"
  12. #define RSEQ_ASM_TMP_REG_4 "r25"
  13. #define rseq_smp_load_acquire(p) \
  14. __extension__ ({ \
  15. rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
  16. rseq_smp_mb(); \
  17. ____p1; \
  18. })
  19. #define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb()
  20. #define rseq_smp_store_release(p, v) \
  21. do { \
  22. rseq_smp_mb(); \
  23. RSEQ_WRITE_ONCE(*(p), v); \
  24. } while (0)
  25. #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \
  26. post_commit_offset, abort_ip) \
  27. ".pushsection __rseq_cs, \"aw\"\n" \
  28. ".balign 32\n" \
  29. __rseq_str(label) ":\n" \
  30. ".long " __rseq_str(version) ", " __rseq_str(flags) "\n" \
  31. ".long 0x0, " __rseq_str(start_ip) ", " \
  32. "0x0, " __rseq_str(post_commit_offset) ", " \
  33. "0x0, " __rseq_str(abort_ip) "\n" \
  34. ".popsection\n\t" \
  35. ".pushsection __rseq_cs_ptr_array, \"aw\"\n" \
  36. ".long 0x0, " __rseq_str(label) "b\n" \
  37. ".popsection\n"
  38. #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
  39. __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \
  40. ((post_commit_ip) - (start_ip)), abort_ip)
  41. /*
  42. * Exit points of a rseq critical section consist of all instructions outside
  43. * of the critical section where a critical section can either branch to or
  44. * reach through the normal course of its execution. The abort IP and the
  45. * post-commit IP are already part of the __rseq_cs section and should not be
  46. * explicitly defined as additional exit points. Knowing all exit points is
  47. * useful to assist debuggers stepping over the critical section.
  48. */
  49. #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \
  50. ".pushsection __rseq_exit_point_array, \"aw\"\n" \
  51. ".long 0x0, " __rseq_str(start_ip) ", 0x0, " __rseq_str(exit_ip) "\n" \
  52. ".popsection\n"
  53. #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
  54. RSEQ_INJECT_ASM(1) \
  55. "l.movhi " RSEQ_ASM_TMP_REG_1 ", hi(" __rseq_str(cs_label) ")\n"\
  56. "l.ori " RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1 \
  57. ", lo(" __rseq_str(cs_label) ")\n"\
  58. "l.sw %[" __rseq_str(rseq_cs) "], " RSEQ_ASM_TMP_REG_1 "\n" \
  59. __rseq_str(label) ":\n"
  60. #define RSEQ_ASM_DEFINE_ABORT(label, abort_label) \
  61. "l.j 222f\n" \
  62. " l.nop\n" \
  63. ".balign 4\n" \
  64. ".long " __rseq_str(RSEQ_SIG) "\n" \
  65. __rseq_str(label) ":\n" \
  66. "l.j %l[" __rseq_str(abort_label) "]\n" \
  67. " l.nop\n" \
  68. "222:\n"
  69. #define RSEQ_ASM_OP_STORE(var, value) \
  70. "l.sw %[" __rseq_str(var) "], %[" __rseq_str(value) "]\n"
  71. #define RSEQ_ASM_OP_CMPEQ(var, expect, label) \
  72. "l.lwz " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n" \
  73. "l.sfne " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "]\n" \
  74. "l.bf " __rseq_str(label) "\n" \
  75. " l.nop\n"
  76. #define RSEQ_ASM_OP_CMPNE(var, expect, label) \
  77. "l.lwz " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n" \
  78. "l.sfeq " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(expect) "]\n" \
  79. "l.bf " __rseq_str(label) "\n" \
  80. " l.nop\n"
  81. #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \
  82. RSEQ_INJECT_ASM(2) \
  83. RSEQ_ASM_OP_CMPEQ(current_cpu_id, cpu_id, label)
  84. #define RSEQ_ASM_OP_R_LOAD(var) \
  85. "l.lwz " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(var) "]\n"
  86. #define RSEQ_ASM_OP_R_STORE(var) \
  87. "l.sw %[" __rseq_str(var) "], " RSEQ_ASM_TMP_REG_1 "\n"
  88. #define RSEQ_ASM_OP_R_LOAD_OFF(offset) \
  89. "l.lwz " RSEQ_ASM_TMP_REG_1 ", " \
  90. "%[" __rseq_str(offset) "](" RSEQ_ASM_TMP_REG_1 ")\n"
  91. #define RSEQ_ASM_OP_R_ADD(count) \
  92. "l.add " RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1 \
  93. ", %[" __rseq_str(count) "]\n"
  94. #define RSEQ_ASM_OP_FINAL_STORE(var, value, post_commit_label) \
  95. RSEQ_ASM_OP_STORE(var, value) \
  96. __rseq_str(post_commit_label) ":\n"
  97. #define RSEQ_ASM_OP_FINAL_STORE_RELEASE(var, value, post_commit_label) \
  98. "l.msync\n" \
  99. RSEQ_ASM_OP_STORE(var, value) \
  100. __rseq_str(post_commit_label) ":\n"
  101. #define RSEQ_ASM_OP_R_FINAL_STORE(var, post_commit_label) \
  102. "l.sw %[" __rseq_str(var) "], " RSEQ_ASM_TMP_REG_1 "\n" \
  103. __rseq_str(post_commit_label) ":\n"
  104. #define RSEQ_ASM_OP_R_BAD_MEMCPY(dst, src, len) \
  105. "l.sfeq %[" __rseq_str(len) "], r0\n" \
  106. "l.bf 333f\n" \
  107. " l.nop\n" \
  108. "l.ori " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(len) "], 0\n" \
  109. "l.ori " RSEQ_ASM_TMP_REG_2 ", %[" __rseq_str(src) "], 0\n" \
  110. "l.ori " RSEQ_ASM_TMP_REG_3 ", %[" __rseq_str(dst) "], 0\n" \
  111. "222:\n" \
  112. "l.lbz " RSEQ_ASM_TMP_REG_4 ", 0(" RSEQ_ASM_TMP_REG_2 ")\n" \
  113. "l.sb 0(" RSEQ_ASM_TMP_REG_3 "), " RSEQ_ASM_TMP_REG_4 "\n" \
  114. "l.addi " RSEQ_ASM_TMP_REG_1 ", " RSEQ_ASM_TMP_REG_1 ", -1\n" \
  115. "l.addi " RSEQ_ASM_TMP_REG_2 ", " RSEQ_ASM_TMP_REG_2 ", 1\n" \
  116. "l.addi " RSEQ_ASM_TMP_REG_3 ", " RSEQ_ASM_TMP_REG_3 ", 1\n" \
  117. "l.sfne " RSEQ_ASM_TMP_REG_1 ", r0\n" \
  118. "l.bf 222b\n" \
  119. " l.nop\n" \
  120. "333:\n"
  121. #define RSEQ_ASM_OP_R_DEREF_ADDV(ptr, off, inc, post_commit_label) \
  122. "l.ori " RSEQ_ASM_TMP_REG_1 ", %[" __rseq_str(ptr) "], 0\n" \
  123. RSEQ_ASM_OP_R_ADD(off) \
  124. "l.lwz " RSEQ_ASM_TMP_REG_1 ", 0(" RSEQ_ASM_TMP_REG_1 ")\n" \
  125. RSEQ_ASM_OP_R_ADD(inc) \
  126. __rseq_str(post_commit_label) ":\n"
  127. /* Per-cpu-id indexing. */
  128. #define RSEQ_TEMPLATE_CPU_ID
  129. #define RSEQ_TEMPLATE_MO_RELAXED
  130. #include "rseq-or1k-bits.h"
  131. #undef RSEQ_TEMPLATE_MO_RELAXED
  132. #define RSEQ_TEMPLATE_MO_RELEASE
  133. #include "rseq-or1k-bits.h"
  134. #undef RSEQ_TEMPLATE_MO_RELEASE
  135. #undef RSEQ_TEMPLATE_CPU_ID
  136. /* Per-mm-cid indexing. */
  137. #define RSEQ_TEMPLATE_MM_CID
  138. #define RSEQ_TEMPLATE_MO_RELAXED
  139. #include "rseq-or1k-bits.h"
  140. #undef RSEQ_TEMPLATE_MO_RELAXED
  141. #define RSEQ_TEMPLATE_MO_RELEASE
  142. #include "rseq-or1k-bits.h"
  143. #undef RSEQ_TEMPLATE_MO_RELEASE
  144. #undef RSEQ_TEMPLATE_MM_CID
  145. /* APIs which are not based on cpu ids. */
  146. #define RSEQ_TEMPLATE_CPU_ID_NONE
  147. #define RSEQ_TEMPLATE_MO_RELAXED
  148. #include "rseq-or1k-bits.h"
  149. #undef RSEQ_TEMPLATE_MO_RELAXED
  150. #undef RSEQ_TEMPLATE_CPU_ID_NONE