feature-fixups.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. #ifndef __ASM_POWERPC_FEATURE_FIXUPS_H
  3. #define __ASM_POWERPC_FEATURE_FIXUPS_H
  4. #include <asm/asm-const.h>
  5. /*
  6. */
  7. /*
  8. * Feature section common macros
  9. *
  10. * Note that the entries now contain offsets between the table entry
  11. * and the code rather than absolute code pointers in order to be
  12. * useable with the vdso shared library. There is also an assumption
  13. * that values will be negative, that is, the fixup table has to be
  14. * located after the code it fixes up.
  15. */
  16. #if defined(CONFIG_PPC64) && !defined(__powerpc64__)
  17. /* 64 bits kernel, 32 bits code (ie. vdso32) */
  18. #define FTR_ENTRY_LONG .8byte
  19. #define FTR_ENTRY_OFFSET .long 0xffffffff; .long
  20. #elif defined(CONFIG_PPC64)
  21. #define FTR_ENTRY_LONG .8byte
  22. #define FTR_ENTRY_OFFSET .8byte
  23. #else
  24. #define FTR_ENTRY_LONG .long
  25. #define FTR_ENTRY_OFFSET .long
  26. #endif
  27. #define START_FTR_SECTION(label) label##1:
  28. #define FTR_SECTION_ELSE_NESTED(label) \
  29. label##2: \
  30. .pushsection __ftr_alt_##label,"a"; \
  31. .align 2; \
  32. label##3:
  33. #ifndef CONFIG_CC_IS_CLANG
  34. #define CHECK_ALT_SIZE(else_size, body_size) \
  35. .ifgt (else_size) - (body_size); \
  36. .error "Feature section else case larger than body"; \
  37. .endif;
  38. #else
  39. /*
  40. * If we use the ifgt syntax above, clang's assembler complains about the
  41. * expression being non-absolute when the code appears in an inline assembly
  42. * statement.
  43. * As a workaround use an .org directive that has no effect if the else case
  44. * instructions are smaller than the body, but fails otherwise.
  45. */
  46. #define CHECK_ALT_SIZE(else_size, body_size) \
  47. .org . + ((else_size) > (body_size));
  48. #endif
  49. #define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \
  50. label##4: \
  51. .popsection; \
  52. .pushsection sect,"a"; \
  53. .align 3; \
  54. label##5: \
  55. FTR_ENTRY_LONG msk; \
  56. FTR_ENTRY_LONG val; \
  57. FTR_ENTRY_OFFSET label##1b-label##5b; \
  58. FTR_ENTRY_OFFSET label##2b-label##5b; \
  59. FTR_ENTRY_OFFSET label##3b-label##5b; \
  60. FTR_ENTRY_OFFSET label##4b-label##5b; \
  61. CHECK_ALT_SIZE((label##4b-label##3b), (label##2b-label##1b)); \
  62. .popsection;
  63. /* CPU feature dependent sections */
  64. #define BEGIN_FTR_SECTION_NESTED(label) START_FTR_SECTION(label)
  65. #define BEGIN_FTR_SECTION START_FTR_SECTION(97)
  66. #define END_FTR_SECTION_NESTED(msk, val, label) \
  67. FTR_SECTION_ELSE_NESTED(label) \
  68. MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup)
  69. #define END_FTR_SECTION(msk, val) \
  70. END_FTR_SECTION_NESTED(msk, val, 97)
  71. #define END_FTR_SECTION_NESTED_IFSET(msk, label) \
  72. END_FTR_SECTION_NESTED((msk), (msk), label)
  73. #define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk))
  74. #define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0)
  75. /* CPU feature sections with alternatives, use BEGIN_FTR_SECTION to start */
  76. #define FTR_SECTION_ELSE FTR_SECTION_ELSE_NESTED(97)
  77. #define ALT_FTR_SECTION_END_NESTED(msk, val, label) \
  78. MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup)
  79. #define ALT_FTR_SECTION_END_NESTED_IFSET(msk, label) \
  80. ALT_FTR_SECTION_END_NESTED(msk, msk, label)
  81. #define ALT_FTR_SECTION_END_NESTED_IFCLR(msk, label) \
  82. ALT_FTR_SECTION_END_NESTED(msk, 0, label)
  83. #define ALT_FTR_SECTION_END(msk, val) \
  84. ALT_FTR_SECTION_END_NESTED(msk, val, 97)
  85. #define ALT_FTR_SECTION_END_IFSET(msk) \
  86. ALT_FTR_SECTION_END_NESTED_IFSET(msk, 97)
  87. #define ALT_FTR_SECTION_END_IFCLR(msk) \
  88. ALT_FTR_SECTION_END_NESTED_IFCLR(msk, 97)
  89. /* MMU feature dependent sections */
  90. #define BEGIN_MMU_FTR_SECTION_NESTED(label) START_FTR_SECTION(label)
  91. #define BEGIN_MMU_FTR_SECTION START_FTR_SECTION(97)
  92. #define END_MMU_FTR_SECTION_NESTED(msk, val, label) \
  93. FTR_SECTION_ELSE_NESTED(label) \
  94. MAKE_FTR_SECTION_ENTRY(msk, val, label, __mmu_ftr_fixup)
  95. #define END_MMU_FTR_SECTION(msk, val) \
  96. END_MMU_FTR_SECTION_NESTED(msk, val, 97)
  97. #define END_MMU_FTR_SECTION_NESTED_IFSET(msk, label) \
  98. END_MMU_FTR_SECTION_NESTED((msk), (msk), label)
  99. #define END_MMU_FTR_SECTION_NESTED_IFCLR(msk, label) \
  100. END_MMU_FTR_SECTION_NESTED((msk), 0, label)
  101. #define END_MMU_FTR_SECTION_IFSET(msk) END_MMU_FTR_SECTION((msk), (msk))
  102. #define END_MMU_FTR_SECTION_IFCLR(msk) END_MMU_FTR_SECTION((msk), 0)
  103. /* MMU feature sections with alternatives, use BEGIN_FTR_SECTION to start */
  104. #define MMU_FTR_SECTION_ELSE_NESTED(label) FTR_SECTION_ELSE_NESTED(label)
  105. #define MMU_FTR_SECTION_ELSE MMU_FTR_SECTION_ELSE_NESTED(97)
  106. #define ALT_MMU_FTR_SECTION_END_NESTED(msk, val, label) \
  107. MAKE_FTR_SECTION_ENTRY(msk, val, label, __mmu_ftr_fixup)
  108. #define ALT_MMU_FTR_SECTION_END_NESTED_IFSET(msk, label) \
  109. ALT_MMU_FTR_SECTION_END_NESTED(msk, msk, label)
  110. #define ALT_MMU_FTR_SECTION_END_NESTED_IFCLR(msk, label) \
  111. ALT_MMU_FTR_SECTION_END_NESTED(msk, 0, label)
  112. #define ALT_MMU_FTR_SECTION_END(msk, val) \
  113. ALT_MMU_FTR_SECTION_END_NESTED(msk, val, 97)
  114. #define ALT_MMU_FTR_SECTION_END_IFSET(msk) \
  115. ALT_MMU_FTR_SECTION_END_NESTED_IFSET(msk, 97)
  116. #define ALT_MMU_FTR_SECTION_END_IFCLR(msk) \
  117. ALT_MMU_FTR_SECTION_END_NESTED_IFCLR(msk, 97)
  118. /* Firmware feature dependent sections */
  119. #define BEGIN_FW_FTR_SECTION_NESTED(label) START_FTR_SECTION(label)
  120. #define BEGIN_FW_FTR_SECTION START_FTR_SECTION(97)
  121. #define END_FW_FTR_SECTION_NESTED(msk, val, label) \
  122. FTR_SECTION_ELSE_NESTED(label) \
  123. MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup)
  124. #define END_FW_FTR_SECTION(msk, val) \
  125. END_FW_FTR_SECTION_NESTED(msk, val, 97)
  126. #define END_FW_FTR_SECTION_IFSET(msk) END_FW_FTR_SECTION((msk), (msk))
  127. #define END_FW_FTR_SECTION_IFCLR(msk) END_FW_FTR_SECTION((msk), 0)
  128. /* Firmware feature sections with alternatives */
  129. #define FW_FTR_SECTION_ELSE_NESTED(label) FTR_SECTION_ELSE_NESTED(label)
  130. #define FW_FTR_SECTION_ELSE FTR_SECTION_ELSE_NESTED(97)
  131. #define ALT_FW_FTR_SECTION_END_NESTED(msk, val, label) \
  132. MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup)
  133. #define ALT_FW_FTR_SECTION_END_NESTED_IFSET(msk, label) \
  134. ALT_FW_FTR_SECTION_END_NESTED(msk, msk, label)
  135. #define ALT_FW_FTR_SECTION_END_NESTED_IFCLR(msk, label) \
  136. ALT_FW_FTR_SECTION_END_NESTED(msk, 0, label)
  137. #define ALT_FW_FTR_SECTION_END(msk, val) \
  138. ALT_FW_FTR_SECTION_END_NESTED(msk, val, 97)
  139. #define ALT_FW_FTR_SECTION_END_IFSET(msk) \
  140. ALT_FW_FTR_SECTION_END_NESTED_IFSET(msk, 97)
  141. #define ALT_FW_FTR_SECTION_END_IFCLR(msk) \
  142. ALT_FW_FTR_SECTION_END_NESTED_IFCLR(msk, 97)
  143. #ifndef __ASSEMBLY__
  144. #define ASM_FTR_IF(section_if, section_else, msk, val) \
  145. stringify_in_c(BEGIN_FTR_SECTION) \
  146. section_if "; " \
  147. stringify_in_c(FTR_SECTION_ELSE) \
  148. section_else "; " \
  149. stringify_in_c(ALT_FTR_SECTION_END((msk), (val)))
  150. #define ASM_FTR_IFSET(section_if, section_else, msk) \
  151. ASM_FTR_IF(section_if, section_else, (msk), (msk))
  152. #define ASM_FTR_IFCLR(section_if, section_else, msk) \
  153. ASM_FTR_IF(section_if, section_else, (msk), 0)
  154. #define ASM_MMU_FTR_IF(section_if, section_else, msk, val) \
  155. stringify_in_c(BEGIN_MMU_FTR_SECTION) \
  156. section_if "; " \
  157. stringify_in_c(MMU_FTR_SECTION_ELSE) \
  158. section_else "; " \
  159. stringify_in_c(ALT_MMU_FTR_SECTION_END((msk), (val)))
  160. #define ASM_MMU_FTR_IFSET(section_if, section_else, msk) \
  161. ASM_MMU_FTR_IF(section_if, section_else, (msk), (msk))
  162. #define ASM_MMU_FTR_IFCLR(section_if, section_else, msk) \
  163. ASM_MMU_FTR_IF(section_if, section_else, (msk), 0)
  164. #endif /* __ASSEMBLY__ */
  165. /* LWSYNC feature sections */
  166. #define START_LWSYNC_SECTION(label) label##1:
  167. #define MAKE_LWSYNC_SECTION_ENTRY(label, sect) \
  168. label##2: \
  169. .pushsection sect,"a"; \
  170. .align 2; \
  171. label##3: \
  172. FTR_ENTRY_OFFSET label##1b-label##3b; \
  173. .popsection;
  174. #define STF_ENTRY_BARRIER_FIXUP_SECTION \
  175. 953: \
  176. .pushsection __stf_entry_barrier_fixup,"a"; \
  177. .align 2; \
  178. 954: \
  179. FTR_ENTRY_OFFSET 953b-954b; \
  180. .popsection;
  181. #define STF_EXIT_BARRIER_FIXUP_SECTION \
  182. 955: \
  183. .pushsection __stf_exit_barrier_fixup,"a"; \
  184. .align 2; \
  185. 956: \
  186. FTR_ENTRY_OFFSET 955b-956b; \
  187. .popsection;
  188. #define UACCESS_FLUSH_FIXUP_SECTION \
  189. 959: \
  190. .pushsection __uaccess_flush_fixup,"a"; \
  191. .align 2; \
  192. 960: \
  193. FTR_ENTRY_OFFSET 959b-960b; \
  194. .popsection;
  195. #define ENTRY_FLUSH_FIXUP_SECTION \
  196. 957: \
  197. .pushsection __entry_flush_fixup,"a"; \
  198. .align 2; \
  199. 958: \
  200. FTR_ENTRY_OFFSET 957b-958b; \
  201. .popsection;
  202. #define SCV_ENTRY_FLUSH_FIXUP_SECTION \
  203. 957: \
  204. .pushsection __scv_entry_flush_fixup,"a"; \
  205. .align 2; \
  206. 958: \
  207. FTR_ENTRY_OFFSET 957b-958b; \
  208. .popsection;
  209. #define RFI_FLUSH_FIXUP_SECTION \
  210. 951: \
  211. .pushsection __rfi_flush_fixup,"a"; \
  212. .align 2; \
  213. 952: \
  214. FTR_ENTRY_OFFSET 951b-952b; \
  215. .popsection;
  216. #define NOSPEC_BARRIER_FIXUP_SECTION \
  217. 953: \
  218. .pushsection __barrier_nospec_fixup,"a"; \
  219. .align 2; \
  220. 954: \
  221. FTR_ENTRY_OFFSET 953b-954b; \
  222. .popsection;
  223. #define START_BTB_FLUSH_SECTION \
  224. 955: \
  225. #define END_BTB_FLUSH_SECTION \
  226. 956: \
  227. .pushsection __btb_flush_fixup,"a"; \
  228. .align 2; \
  229. 957: \
  230. FTR_ENTRY_OFFSET 955b-957b; \
  231. FTR_ENTRY_OFFSET 956b-957b; \
  232. .popsection;
  233. #ifndef __ASSEMBLY__
  234. #include <linux/types.h>
  235. extern long stf_barrier_fallback;
  236. extern long entry_flush_fallback;
  237. extern long scv_entry_flush_fallback;
  238. extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup;
  239. extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup;
  240. extern long __start___uaccess_flush_fixup, __stop___uaccess_flush_fixup;
  241. extern long __start___entry_flush_fixup, __stop___entry_flush_fixup;
  242. extern long __start___scv_entry_flush_fixup, __stop___scv_entry_flush_fixup;
  243. extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup;
  244. extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup;
  245. extern long __start__btb_flush_fixup, __stop__btb_flush_fixup;
  246. void apply_feature_fixups(void);
  247. void setup_feature_keys(void);
  248. #endif
  249. #endif /* __ASM_POWERPC_FEATURE_FIXUPS_H */