alternative.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * alternative runtime patching
  4. * inspired by the x86 version
  5. *
  6. * Copyright (C) 2014 ARM Ltd.
  7. */
  8. #define pr_fmt(fmt) "alternatives: " fmt
  9. #include <linux/init.h>
  10. #include <linux/cpu.h>
  11. #include <linux/elf.h>
  12. #include <asm/cacheflush.h>
  13. #include <asm/alternative.h>
  14. #include <asm/cpufeature.h>
  15. #include <asm/insn.h>
  16. #include <asm/module.h>
  17. #include <asm/sections.h>
  18. #include <asm/vdso.h>
  19. #include <linux/stop_machine.h>
  20. #define __ALT_PTR(a, f) ((void *)&(a)->f + (a)->f)
  21. #define ALT_ORIG_PTR(a) __ALT_PTR(a, orig_offset)
  22. #define ALT_REPL_PTR(a) __ALT_PTR(a, alt_offset)
  23. #define ALT_CAP(a) ((a)->cpufeature & ~ARM64_CB_BIT)
  24. #define ALT_HAS_CB(a) ((a)->cpufeature & ARM64_CB_BIT)
  25. /* Volatile, as we may be patching the guts of READ_ONCE() */
  26. static volatile int all_alternatives_applied;
  27. static DECLARE_BITMAP(applied_alternatives, ARM64_NCAPS);
  28. struct alt_region {
  29. struct alt_instr *begin;
  30. struct alt_instr *end;
  31. };
  32. bool alternative_is_applied(u16 cpufeature)
  33. {
  34. if (WARN_ON(cpufeature >= ARM64_NCAPS))
  35. return false;
  36. return test_bit(cpufeature, applied_alternatives);
  37. }
  38. /*
  39. * Check if the target PC is within an alternative block.
  40. */
  41. static __always_inline bool branch_insn_requires_update(struct alt_instr *alt, unsigned long pc)
  42. {
  43. unsigned long replptr = (unsigned long)ALT_REPL_PTR(alt);
  44. return !(pc >= replptr && pc <= (replptr + alt->alt_len));
  45. }
  46. #define align_down(x, a) ((unsigned long)(x) & ~(((unsigned long)(a)) - 1))
  47. static __always_inline u32 get_alt_insn(struct alt_instr *alt, __le32 *insnptr, __le32 *altinsnptr)
  48. {
  49. u32 insn;
  50. insn = le32_to_cpu(*altinsnptr);
  51. if (aarch64_insn_is_branch_imm(insn)) {
  52. s32 offset = aarch64_get_branch_offset(insn);
  53. unsigned long target;
  54. target = (unsigned long)altinsnptr + offset;
  55. /*
  56. * If we're branching inside the alternate sequence,
  57. * do not rewrite the instruction, as it is already
  58. * correct. Otherwise, generate the new instruction.
  59. */
  60. if (branch_insn_requires_update(alt, target)) {
  61. offset = target - (unsigned long)insnptr;
  62. insn = aarch64_set_branch_offset(insn, offset);
  63. }
  64. } else if (aarch64_insn_is_adrp(insn)) {
  65. s32 orig_offset, new_offset;
  66. unsigned long target;
  67. /*
  68. * If we're replacing an adrp instruction, which uses PC-relative
  69. * immediate addressing, adjust the offset to reflect the new
  70. * PC. adrp operates on 4K aligned addresses.
  71. */
  72. orig_offset = aarch64_insn_adrp_get_offset(insn);
  73. target = align_down(altinsnptr, SZ_4K) + orig_offset;
  74. new_offset = target - align_down(insnptr, SZ_4K);
  75. insn = aarch64_insn_adrp_set_offset(insn, new_offset);
  76. } else if (aarch64_insn_uses_literal(insn)) {
  77. /*
  78. * Disallow patching unhandled instructions using PC relative
  79. * literal addresses
  80. */
  81. BUG();
  82. }
  83. return insn;
  84. }
  85. static noinstr void patch_alternative(struct alt_instr *alt,
  86. __le32 *origptr, __le32 *updptr, int nr_inst)
  87. {
  88. __le32 *replptr;
  89. int i;
  90. replptr = ALT_REPL_PTR(alt);
  91. for (i = 0; i < nr_inst; i++) {
  92. u32 insn;
  93. insn = get_alt_insn(alt, origptr + i, replptr + i);
  94. updptr[i] = cpu_to_le32(insn);
  95. }
  96. }
  97. /*
  98. * We provide our own, private D-cache cleaning function so that we don't
  99. * accidentally call into the cache.S code, which is patched by us at
  100. * runtime.
  101. */
  102. static void clean_dcache_range_nopatch(u64 start, u64 end)
  103. {
  104. u64 cur, d_size, ctr_el0;
  105. ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0);
  106. d_size = 4 << cpuid_feature_extract_unsigned_field(ctr_el0,
  107. CTR_EL0_DminLine_SHIFT);
  108. cur = start & ~(d_size - 1);
  109. do {
  110. /*
  111. * We must clean+invalidate to the PoC in order to avoid
  112. * Cortex-A53 errata 826319, 827319, 824069 and 819472
  113. * (this corresponds to ARM64_WORKAROUND_CLEAN_CACHE)
  114. */
  115. asm volatile("dc civac, %0" : : "r" (cur) : "memory");
  116. } while (cur += d_size, cur < end);
  117. }
  118. static void __apply_alternatives(const struct alt_region *region,
  119. bool is_module,
  120. unsigned long *feature_mask)
  121. {
  122. struct alt_instr *alt;
  123. __le32 *origptr, *updptr;
  124. alternative_cb_t alt_cb;
  125. for (alt = region->begin; alt < region->end; alt++) {
  126. int nr_inst;
  127. int cap = ALT_CAP(alt);
  128. if (!test_bit(cap, feature_mask))
  129. continue;
  130. if (!cpus_have_cap(cap))
  131. continue;
  132. if (ALT_HAS_CB(alt))
  133. BUG_ON(alt->alt_len != 0);
  134. else
  135. BUG_ON(alt->alt_len != alt->orig_len);
  136. origptr = ALT_ORIG_PTR(alt);
  137. updptr = is_module ? origptr : lm_alias(origptr);
  138. nr_inst = alt->orig_len / AARCH64_INSN_SIZE;
  139. if (ALT_HAS_CB(alt))
  140. alt_cb = ALT_REPL_PTR(alt);
  141. else
  142. alt_cb = patch_alternative;
  143. alt_cb(alt, origptr, updptr, nr_inst);
  144. if (!is_module) {
  145. clean_dcache_range_nopatch((u64)origptr,
  146. (u64)(origptr + nr_inst));
  147. }
  148. }
  149. /*
  150. * The core module code takes care of cache maintenance in
  151. * flush_module_icache().
  152. */
  153. if (!is_module) {
  154. dsb(ish);
  155. icache_inval_all_pou();
  156. isb();
  157. /* Ignore ARM64_CB bit from feature mask */
  158. bitmap_or(applied_alternatives, applied_alternatives,
  159. feature_mask, ARM64_NCAPS);
  160. bitmap_and(applied_alternatives, applied_alternatives,
  161. cpu_hwcaps, ARM64_NCAPS);
  162. }
  163. }
  164. void apply_alternatives_vdso(void)
  165. {
  166. struct alt_region region;
  167. const struct elf64_hdr *hdr;
  168. const struct elf64_shdr *shdr;
  169. const struct elf64_shdr *alt;
  170. DECLARE_BITMAP(all_capabilities, ARM64_NCAPS);
  171. bitmap_fill(all_capabilities, ARM64_NCAPS);
  172. hdr = (struct elf64_hdr *)vdso_start;
  173. shdr = (void *)hdr + hdr->e_shoff;
  174. alt = find_section(hdr, shdr, ".altinstructions");
  175. if (!alt)
  176. return;
  177. region = (struct alt_region){
  178. .begin = (void *)hdr + alt->sh_offset,
  179. .end = (void *)hdr + alt->sh_offset + alt->sh_size,
  180. };
  181. __apply_alternatives(&region, false, &all_capabilities[0]);
  182. }
  183. static const struct alt_region kernel_alternatives = {
  184. .begin = (struct alt_instr *)__alt_instructions,
  185. .end = (struct alt_instr *)__alt_instructions_end,
  186. };
  187. /*
  188. * We might be patching the stop_machine state machine, so implement a
  189. * really simple polling protocol here.
  190. */
  191. static int __apply_alternatives_multi_stop(void *unused)
  192. {
  193. /* We always have a CPU 0 at this point (__init) */
  194. if (smp_processor_id()) {
  195. while (!all_alternatives_applied)
  196. cpu_relax();
  197. isb();
  198. } else {
  199. DECLARE_BITMAP(remaining_capabilities, ARM64_NCAPS);
  200. bitmap_complement(remaining_capabilities, boot_capabilities,
  201. ARM64_NCAPS);
  202. BUG_ON(all_alternatives_applied);
  203. __apply_alternatives(&kernel_alternatives, false,
  204. remaining_capabilities);
  205. /* Barriers provided by the cache flushing */
  206. all_alternatives_applied = 1;
  207. }
  208. return 0;
  209. }
  210. void __init apply_alternatives_all(void)
  211. {
  212. pr_info("applying system-wide alternatives\n");
  213. apply_alternatives_vdso();
  214. /* better not try code patching on a live SMP system */
  215. stop_machine(__apply_alternatives_multi_stop, NULL, cpu_online_mask);
  216. }
  217. /*
  218. * This is called very early in the boot process (directly after we run
  219. * a feature detect on the boot CPU). No need to worry about other CPUs
  220. * here.
  221. */
  222. void __init apply_boot_alternatives(void)
  223. {
  224. /* If called on non-boot cpu things could go wrong */
  225. WARN_ON(smp_processor_id() != 0);
  226. pr_info("applying boot alternatives\n");
  227. __apply_alternatives(&kernel_alternatives, false,
  228. &boot_capabilities[0]);
  229. }
  230. #ifdef CONFIG_MODULES
  231. void apply_alternatives_module(void *start, size_t length)
  232. {
  233. struct alt_region region = {
  234. .begin = start,
  235. .end = start + length,
  236. };
  237. DECLARE_BITMAP(all_capabilities, ARM64_NCAPS);
  238. bitmap_fill(all_capabilities, ARM64_NCAPS);
  239. __apply_alternatives(&region, true, &all_capabilities[0]);
  240. }
  241. #endif
  242. noinstr void alt_cb_patch_nops(struct alt_instr *alt, __le32 *origptr,
  243. __le32 *updptr, int nr_inst)
  244. {
  245. for (int i = 0; i < nr_inst; i++)
  246. updptr[i] = cpu_to_le32(aarch64_insn_gen_nop());
  247. }
  248. EXPORT_SYMBOL(alt_cb_patch_nops);