alternative.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_X86_ALTERNATIVE_H
  3. #define _ASM_X86_ALTERNATIVE_H
  4. #include <linux/types.h>
  5. #include <linux/stringify.h>
  6. #include <asm/asm.h>
  7. #define ALTINSTR_FLAG_INV (1 << 15)
  8. #define ALT_NOT(feat) ((feat) | ALTINSTR_FLAG_INV)
  9. #ifndef __ASSEMBLY__
  10. #include <linux/stddef.h>
  11. /*
  12. * Alternative inline assembly for SMP.
  13. *
  14. * The LOCK_PREFIX macro defined here replaces the LOCK and
  15. * LOCK_PREFIX macros used everywhere in the source tree.
  16. *
  17. * SMP alternatives use the same data structures as the other
  18. * alternatives and the X86_FEATURE_UP flag to indicate the case of a
  19. * UP system running a SMP kernel. The existing apply_alternatives()
  20. * works fine for patching a SMP kernel for UP.
  21. *
  22. * The SMP alternative tables can be kept after boot and contain both
  23. * UP and SMP versions of the instructions to allow switching back to
  24. * SMP at runtime, when hotplugging in a new CPU, which is especially
  25. * useful in virtualized environments.
  26. *
  27. * The very common lock prefix is handled as special case in a
  28. * separate table which is a pure address list without replacement ptr
  29. * and size information. That keeps the table sizes small.
  30. */
  31. #ifdef CONFIG_SMP
  32. #define LOCK_PREFIX_HERE \
  33. ".pushsection .smp_locks,\"a\"\n" \
  34. ".balign 4\n" \
  35. ".long 671f - .\n" /* offset */ \
  36. ".popsection\n" \
  37. "671:"
  38. #define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock; "
  39. #else /* ! CONFIG_SMP */
  40. #define LOCK_PREFIX_HERE ""
  41. #define LOCK_PREFIX ""
  42. #endif
  43. /*
  44. * objtool annotation to ignore the alternatives and only consider the original
  45. * instruction(s).
  46. */
  47. #define ANNOTATE_IGNORE_ALTERNATIVE \
  48. "999:\n\t" \
  49. ".pushsection .discard.ignore_alts\n\t" \
  50. ".long 999b - .\n\t" \
  51. ".popsection\n\t"
  52. struct alt_instr {
  53. s32 instr_offset; /* original instruction */
  54. s32 repl_offset; /* offset to replacement instruction */
  55. u16 cpuid; /* cpuid bit set for replacement */
  56. u8 instrlen; /* length of original instruction */
  57. u8 replacementlen; /* length of new instruction */
  58. } __packed;
  59. /*
  60. * Debug flag that can be tested to see whether alternative
  61. * instructions were patched in already:
  62. */
  63. extern int alternatives_patched;
  64. extern void alternative_instructions(void);
  65. extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
  66. extern void apply_retpolines(s32 *start, s32 *end);
  67. extern void apply_returns(s32 *start, s32 *end);
  68. extern void apply_ibt_endbr(s32 *start, s32 *end);
  69. struct module;
  70. #ifdef CONFIG_SMP
  71. extern void alternatives_smp_module_add(struct module *mod, char *name,
  72. void *locks, void *locks_end,
  73. void *text, void *text_end);
  74. extern void alternatives_smp_module_del(struct module *mod);
  75. extern void alternatives_enable_smp(void);
  76. extern int alternatives_text_reserved(void *start, void *end);
  77. extern bool skip_smp_alternatives;
  78. #else
  79. static inline void alternatives_smp_module_add(struct module *mod, char *name,
  80. void *locks, void *locks_end,
  81. void *text, void *text_end) {}
  82. static inline void alternatives_smp_module_del(struct module *mod) {}
  83. static inline void alternatives_enable_smp(void) {}
  84. static inline int alternatives_text_reserved(void *start, void *end)
  85. {
  86. return 0;
  87. }
  88. #endif /* CONFIG_SMP */
  89. #define b_replacement(num) "664"#num
  90. #define e_replacement(num) "665"#num
  91. #define alt_end_marker "663"
  92. #define alt_slen "662b-661b"
  93. #define alt_total_slen alt_end_marker"b-661b"
  94. #define alt_rlen(num) e_replacement(num)"f-"b_replacement(num)"f"
  95. #define OLDINSTR(oldinstr, num) \
  96. "# ALT: oldnstr\n" \
  97. "661:\n\t" oldinstr "\n662:\n" \
  98. "# ALT: padding\n" \
  99. ".skip -(((" alt_rlen(num) ")-(" alt_slen ")) > 0) * " \
  100. "((" alt_rlen(num) ")-(" alt_slen ")),0x90\n" \
  101. alt_end_marker ":\n"
  102. /*
  103. * gas compatible max based on the idea from:
  104. * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
  105. *
  106. * The additional "-" is needed because gas uses a "true" value of -1.
  107. */
  108. #define alt_max_short(a, b) "((" a ") ^ (((" a ") ^ (" b ")) & -(-((" a ") < (" b ")))))"
  109. /*
  110. * Pad the second replacement alternative with additional NOPs if it is
  111. * additionally longer than the first replacement alternative.
  112. */
  113. #define OLDINSTR_2(oldinstr, num1, num2) \
  114. "# ALT: oldinstr2\n" \
  115. "661:\n\t" oldinstr "\n662:\n" \
  116. "# ALT: padding2\n" \
  117. ".skip -((" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")) > 0) * " \
  118. "(" alt_max_short(alt_rlen(num1), alt_rlen(num2)) " - (" alt_slen ")), 0x90\n" \
  119. alt_end_marker ":\n"
  120. #define OLDINSTR_3(oldinsn, n1, n2, n3) \
  121. "# ALT: oldinstr3\n" \
  122. "661:\n\t" oldinsn "\n662:\n" \
  123. "# ALT: padding3\n" \
  124. ".skip -((" alt_max_short(alt_max_short(alt_rlen(n1), alt_rlen(n2)), alt_rlen(n3)) \
  125. " - (" alt_slen ")) > 0) * " \
  126. "(" alt_max_short(alt_max_short(alt_rlen(n1), alt_rlen(n2)), alt_rlen(n3)) \
  127. " - (" alt_slen ")), 0x90\n" \
  128. alt_end_marker ":\n"
  129. #define ALTINSTR_ENTRY(feature, num) \
  130. " .long 661b - .\n" /* label */ \
  131. " .long " b_replacement(num)"f - .\n" /* new instruction */ \
  132. " .word " __stringify(feature) "\n" /* feature bit */ \
  133. " .byte " alt_total_slen "\n" /* source len */ \
  134. " .byte " alt_rlen(num) "\n" /* replacement len */
  135. #define ALTINSTR_REPLACEMENT(newinstr, num) /* replacement */ \
  136. "# ALT: replacement " #num "\n" \
  137. b_replacement(num)":\n\t" newinstr "\n" e_replacement(num) ":\n"
  138. /* alternative assembly primitive: */
  139. #define ALTERNATIVE(oldinstr, newinstr, feature) \
  140. OLDINSTR(oldinstr, 1) \
  141. ".pushsection .altinstructions,\"a\"\n" \
  142. ALTINSTR_ENTRY(feature, 1) \
  143. ".popsection\n" \
  144. ".pushsection .altinstr_replacement, \"ax\"\n" \
  145. ALTINSTR_REPLACEMENT(newinstr, 1) \
  146. ".popsection\n"
  147. #define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\
  148. OLDINSTR_2(oldinstr, 1, 2) \
  149. ".pushsection .altinstructions,\"a\"\n" \
  150. ALTINSTR_ENTRY(feature1, 1) \
  151. ALTINSTR_ENTRY(feature2, 2) \
  152. ".popsection\n" \
  153. ".pushsection .altinstr_replacement, \"ax\"\n" \
  154. ALTINSTR_REPLACEMENT(newinstr1, 1) \
  155. ALTINSTR_REPLACEMENT(newinstr2, 2) \
  156. ".popsection\n"
  157. /* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
  158. #define ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) \
  159. ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \
  160. newinstr_yes, feature)
  161. #define ALTERNATIVE_3(oldinsn, newinsn1, feat1, newinsn2, feat2, newinsn3, feat3) \
  162. OLDINSTR_3(oldinsn, 1, 2, 3) \
  163. ".pushsection .altinstructions,\"a\"\n" \
  164. ALTINSTR_ENTRY(feat1, 1) \
  165. ALTINSTR_ENTRY(feat2, 2) \
  166. ALTINSTR_ENTRY(feat3, 3) \
  167. ".popsection\n" \
  168. ".pushsection .altinstr_replacement, \"ax\"\n" \
  169. ALTINSTR_REPLACEMENT(newinsn1, 1) \
  170. ALTINSTR_REPLACEMENT(newinsn2, 2) \
  171. ALTINSTR_REPLACEMENT(newinsn3, 3) \
  172. ".popsection\n"
  173. /*
  174. * Alternative instructions for different CPU types or capabilities.
  175. *
  176. * This allows to use optimized instructions even on generic binary
  177. * kernels.
  178. *
  179. * length of oldinstr must be longer or equal the length of newinstr
  180. * It can be padded with nops as needed.
  181. *
  182. * For non barrier like inlines please define new variants
  183. * without volatile and memory clobber.
  184. */
  185. #define alternative(oldinstr, newinstr, feature) \
  186. asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, feature) : : : "memory")
  187. #define alternative_2(oldinstr, newinstr1, feature1, newinstr2, feature2) \
  188. asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2) ::: "memory")
  189. #define alternative_ternary(oldinstr, feature, newinstr_yes, newinstr_no) \
  190. asm_inline volatile(ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) ::: "memory")
  191. /*
  192. * Alternative inline assembly with input.
  193. *
  194. * Peculiarities:
  195. * No memory clobber here.
  196. * Argument numbers start with 1.
  197. * Leaving an unused argument 0 to keep API compatibility.
  198. */
  199. #define alternative_input(oldinstr, newinstr, feature, input...) \
  200. asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
  201. : : "i" (0), ## input)
  202. /*
  203. * This is similar to alternative_input. But it has two features and
  204. * respective instructions.
  205. *
  206. * If CPU has feature2, newinstr2 is used.
  207. * Otherwise, if CPU has feature1, newinstr1 is used.
  208. * Otherwise, oldinstr is used.
  209. */
  210. #define alternative_input_2(oldinstr, newinstr1, feature1, newinstr2, \
  211. feature2, input...) \
  212. asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, feature1, \
  213. newinstr2, feature2) \
  214. : : "i" (0), ## input)
  215. /* Like alternative_input, but with a single output argument */
  216. #define alternative_io(oldinstr, newinstr, feature, output, input...) \
  217. asm_inline volatile (ALTERNATIVE(oldinstr, newinstr, feature) \
  218. : output : "i" (0), ## input)
  219. /* Like alternative_io, but for replacing a direct call with another one. */
  220. #define alternative_call(oldfunc, newfunc, feature, output, input...) \
  221. asm_inline volatile (ALTERNATIVE("call %P[old]", "call %P[new]", feature) \
  222. : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
  223. /*
  224. * Like alternative_call, but there are two features and respective functions.
  225. * If CPU has feature2, function2 is used.
  226. * Otherwise, if CPU has feature1, function1 is used.
  227. * Otherwise, old function is used.
  228. */
  229. #define alternative_call_2(oldfunc, newfunc1, feature1, newfunc2, feature2, \
  230. output, input...) \
  231. asm_inline volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", feature1,\
  232. "call %P[new2]", feature2) \
  233. : output, ASM_CALL_CONSTRAINT \
  234. : [old] "i" (oldfunc), [new1] "i" (newfunc1), \
  235. [new2] "i" (newfunc2), ## input)
  236. /*
  237. * use this macro(s) if you need more than one output parameter
  238. * in alternative_io
  239. */
  240. #define ASM_OUTPUT2(a...) a
  241. /*
  242. * use this macro if you need clobbers but no inputs in
  243. * alternative_{input,io,call}()
  244. */
  245. #define ASM_NO_INPUT_CLOBBER(clbr...) "i" (0) : clbr
  246. #else /* __ASSEMBLY__ */
  247. #ifdef CONFIG_SMP
  248. .macro LOCK_PREFIX
  249. 672: lock
  250. .pushsection .smp_locks,"a"
  251. .balign 4
  252. .long 672b - .
  253. .popsection
  254. .endm
  255. #else
  256. .macro LOCK_PREFIX
  257. .endm
  258. #endif
  259. /*
  260. * objtool annotation to ignore the alternatives and only consider the original
  261. * instruction(s).
  262. */
  263. .macro ANNOTATE_IGNORE_ALTERNATIVE
  264. .Lannotate_\@:
  265. .pushsection .discard.ignore_alts
  266. .long .Lannotate_\@ - .
  267. .popsection
  268. .endm
  269. /*
  270. * Issue one struct alt_instr descriptor entry (need to put it into
  271. * the section .altinstructions, see below). This entry contains
  272. * enough information for the alternatives patching code to patch an
  273. * instruction. See apply_alternatives().
  274. */
  275. .macro altinstruction_entry orig alt feature orig_len alt_len
  276. .long \orig - .
  277. .long \alt - .
  278. .word \feature
  279. .byte \orig_len
  280. .byte \alt_len
  281. .endm
  282. /*
  283. * Define an alternative between two instructions. If @feature is
  284. * present, early code in apply_alternatives() replaces @oldinstr with
  285. * @newinstr. ".skip" directive takes care of proper instruction padding
  286. * in case @newinstr is longer than @oldinstr.
  287. */
  288. .macro ALTERNATIVE oldinstr, newinstr, feature
  289. 140:
  290. \oldinstr
  291. 141:
  292. .skip -(((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)),0x90
  293. 142:
  294. .pushsection .altinstructions,"a"
  295. altinstruction_entry 140b,143f,\feature,142b-140b,144f-143f
  296. .popsection
  297. .pushsection .altinstr_replacement,"ax"
  298. 143:
  299. \newinstr
  300. 144:
  301. .popsection
  302. .endm
  303. #define old_len 141b-140b
  304. #define new_len1 144f-143f
  305. #define new_len2 145f-144f
  306. /*
  307. * gas compatible max based on the idea from:
  308. * http://graphics.stanford.edu/~seander/bithacks.html#IntegerMinOrMax
  309. *
  310. * The additional "-" is needed because gas uses a "true" value of -1.
  311. */
  312. #define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
  313. /*
  314. * Same as ALTERNATIVE macro above but for two alternatives. If CPU
  315. * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
  316. * @feature2, it replaces @oldinstr with @feature2.
  317. */
  318. .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
  319. 140:
  320. \oldinstr
  321. 141:
  322. .skip -((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \
  323. (alt_max_short(new_len1, new_len2) - (old_len)),0x90
  324. 142:
  325. .pushsection .altinstructions,"a"
  326. altinstruction_entry 140b,143f,\feature1,142b-140b,144f-143f
  327. altinstruction_entry 140b,144f,\feature2,142b-140b,145f-144f
  328. .popsection
  329. .pushsection .altinstr_replacement,"ax"
  330. 143:
  331. \newinstr1
  332. 144:
  333. \newinstr2
  334. 145:
  335. .popsection
  336. .endm
  337. /* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
  338. #define ALTERNATIVE_TERNARY(oldinstr, feature, newinstr_yes, newinstr_no) \
  339. ALTERNATIVE_2 oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \
  340. newinstr_yes, feature
  341. #endif /* __ASSEMBLY__ */
  342. #endif /* _ASM_X86_ALTERNATIVE_H */