rseq-mips.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /* SPDX-License-Identifier: LGPL-2.1 OR MIT */
  2. /*
  3. * Author: Paul Burton <paul.burton@mips.com>
  4. * (C) Copyright 2018 MIPS Tech LLC
  5. * (C) Copyright 2016-2022 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
  6. */
  7. /*
  8. * RSEQ_SIG uses the break instruction. The instruction pattern is:
  9. *
  10. * On MIPS:
  11. * 0350000d break 0x350
  12. *
  13. * On nanoMIPS:
  14. * 00100350 break 0x350
  15. *
  16. * On microMIPS:
  17. * 0000d407 break 0x350
  18. *
  19. * For nanoMIPS32 and microMIPS, the instruction stream is encoded as 16-bit
  20. * halfwords, so the signature halfwords need to be swapped accordingly for
  21. * little-endian.
  22. */
  23. #if defined(__nanomips__)
  24. # ifdef __MIPSEL__
  25. # define RSEQ_SIG 0x03500010
  26. # else
  27. # define RSEQ_SIG 0x00100350
  28. # endif
  29. #elif defined(__mips_micromips)
  30. # ifdef __MIPSEL__
  31. # define RSEQ_SIG 0xd4070000
  32. # else
  33. # define RSEQ_SIG 0x0000d407
  34. # endif
  35. #elif defined(__mips__)
  36. # define RSEQ_SIG 0x0350000d
  37. #else
  38. /* Unknown MIPS architecture. */
  39. #endif
  40. #define rseq_smp_mb() __asm__ __volatile__ ("sync" ::: "memory")
  41. #define rseq_smp_rmb() rseq_smp_mb()
  42. #define rseq_smp_wmb() rseq_smp_mb()
  43. #define rseq_smp_load_acquire(p) \
  44. __extension__ ({ \
  45. rseq_unqual_scalar_typeof(*(p)) ____p1 = RSEQ_READ_ONCE(*(p)); \
  46. rseq_smp_mb(); \
  47. ____p1; \
  48. })
  49. #define rseq_smp_acquire__after_ctrl_dep() rseq_smp_rmb()
  50. #define rseq_smp_store_release(p, v) \
  51. do { \
  52. rseq_smp_mb(); \
  53. RSEQ_WRITE_ONCE(*(p), v); \
  54. } while (0)
  55. #if _MIPS_SZLONG == 64
  56. # define LONG ".dword"
  57. # define LONG_LA "dla"
  58. # define LONG_L "ld"
  59. # define LONG_S "sd"
  60. # define LONG_ADDI "daddiu"
  61. # define U32_U64_PAD(x) x
  62. #elif _MIPS_SZLONG == 32
  63. # define LONG ".word"
  64. # define LONG_LA "la"
  65. # define LONG_L "lw"
  66. # define LONG_S "sw"
  67. # define LONG_ADDI "addiu"
  68. # ifdef __BIG_ENDIAN
  69. # define U32_U64_PAD(x) "0x0, " x
  70. # else
  71. # define U32_U64_PAD(x) x ", 0x0"
  72. # endif
  73. #else
  74. # error unsupported _MIPS_SZLONG
  75. #endif
  76. #define __RSEQ_ASM_DEFINE_TABLE(label, version, flags, start_ip, \
  77. post_commit_offset, abort_ip) \
  78. ".pushsection __rseq_cs, \"aw\"\n\t" \
  79. ".balign 32\n\t" \
  80. __rseq_str(label) ":\n\t" \
  81. ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
  82. LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
  83. LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \
  84. LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \
  85. ".popsection\n\t" \
  86. ".pushsection __rseq_cs_ptr_array, \"aw\"\n\t" \
  87. LONG " " U32_U64_PAD(__rseq_str(label) "b") "\n\t" \
  88. ".popsection\n\t"
  89. #define RSEQ_ASM_DEFINE_TABLE(label, start_ip, post_commit_ip, abort_ip) \
  90. __RSEQ_ASM_DEFINE_TABLE(label, 0x0, 0x0, start_ip, \
  91. (post_commit_ip - start_ip), abort_ip)
  92. /*
  93. * Exit points of a rseq critical section consist of all instructions outside
  94. * of the critical section where a critical section can either branch to or
  95. * reach through the normal course of its execution. The abort IP and the
  96. * post-commit IP are already part of the __rseq_cs section and should not be
  97. * explicitly defined as additional exit points. Knowing all exit points is
  98. * useful to assist debuggers stepping over the critical section.
  99. */
  100. #define RSEQ_ASM_DEFINE_EXIT_POINT(start_ip, exit_ip) \
  101. ".pushsection __rseq_exit_point_array, \"aw\"\n\t" \
  102. LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
  103. LONG " " U32_U64_PAD(__rseq_str(exit_ip)) "\n\t" \
  104. ".popsection\n\t"
  105. #define RSEQ_ASM_STORE_RSEQ_CS(label, cs_label, rseq_cs) \
  106. RSEQ_INJECT_ASM(1) \
  107. LONG_LA " $4, " __rseq_str(cs_label) "\n\t" \
  108. LONG_S " $4, %[" __rseq_str(rseq_cs) "]\n\t" \
  109. __rseq_str(label) ":\n\t"
  110. #define RSEQ_ASM_CMP_CPU_ID(cpu_id, current_cpu_id, label) \
  111. RSEQ_INJECT_ASM(2) \
  112. "lw $4, %[" __rseq_str(current_cpu_id) "]\n\t" \
  113. "bne $4, %[" __rseq_str(cpu_id) "], " __rseq_str(label) "\n\t"
  114. #define __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
  115. abort_label, version, flags, \
  116. start_ip, post_commit_offset, abort_ip) \
  117. ".balign 32\n\t" \
  118. __rseq_str(table_label) ":\n\t" \
  119. ".word " __rseq_str(version) ", " __rseq_str(flags) "\n\t" \
  120. LONG " " U32_U64_PAD(__rseq_str(start_ip)) "\n\t" \
  121. LONG " " U32_U64_PAD(__rseq_str(post_commit_offset)) "\n\t" \
  122. LONG " " U32_U64_PAD(__rseq_str(abort_ip)) "\n\t" \
  123. ".word " __rseq_str(RSEQ_SIG) "\n\t" \
  124. __rseq_str(label) ":\n\t" \
  125. teardown \
  126. "b %l[" __rseq_str(abort_label) "]\n\t"
  127. #define RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, abort_label, \
  128. start_ip, post_commit_ip, abort_ip) \
  129. __RSEQ_ASM_DEFINE_ABORT(table_label, label, teardown, \
  130. abort_label, 0x0, 0x0, start_ip, \
  131. (post_commit_ip - start_ip), abort_ip)
  132. #define RSEQ_ASM_DEFINE_CMPFAIL(label, teardown, cmpfail_label) \
  133. __rseq_str(label) ":\n\t" \
  134. teardown \
  135. "b %l[" __rseq_str(cmpfail_label) "]\n\t"
  136. /* Per-cpu-id indexing. */
  137. #define RSEQ_TEMPLATE_CPU_ID
  138. #define RSEQ_TEMPLATE_MO_RELAXED
  139. #include "rseq-mips-bits.h"
  140. #undef RSEQ_TEMPLATE_MO_RELAXED
  141. #define RSEQ_TEMPLATE_MO_RELEASE
  142. #include "rseq-mips-bits.h"
  143. #undef RSEQ_TEMPLATE_MO_RELEASE
  144. #undef RSEQ_TEMPLATE_CPU_ID
  145. /* Per-mm-cid indexing. */
  146. #define RSEQ_TEMPLATE_MM_CID
  147. #define RSEQ_TEMPLATE_MO_RELAXED
  148. #include "rseq-mips-bits.h"
  149. #undef RSEQ_TEMPLATE_MO_RELAXED
  150. #define RSEQ_TEMPLATE_MO_RELEASE
  151. #include "rseq-mips-bits.h"
  152. #undef RSEQ_TEMPLATE_MO_RELEASE
  153. #undef RSEQ_TEMPLATE_MM_CID
  154. /* APIs which are not based on cpu ids. */
  155. #define RSEQ_TEMPLATE_CPU_ID_NONE
  156. #define RSEQ_TEMPLATE_MO_RELAXED
  157. #include "rseq-mips-bits.h"
  158. #undef RSEQ_TEMPLATE_MO_RELAXED
  159. #undef RSEQ_TEMPLATE_CPU_ID_NONE