Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 fixes from Catalin Marinas:

- The alternatives patching code uses flush_icache_range() which itself
uses alternatives. Change the code to use an unpatched variant of
cache maintenance

- Remove unnecessary ISBs from set_{pte,pmd,pud}

- perf: xgene_pmu: Fix IOB SLOW PMU parser error

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: Remove unnecessary ISBs from set_{pte,pmd,pud}
arm64: Avoid flush_icache_range() in alternatives patching code
drivers/perf: xgene_pmu: Fix IOB SLOW PMU parser error

+54 -17
+6 -1
arch/arm64/include/asm/alternative.h
··· 28 28 __le32 *origptr, __le32 *updptr, int nr_inst); 29 29 30 30 void __init apply_alternatives_all(void); 31 - void apply_alternatives(void *start, size_t length); 31 + 32 + #ifdef CONFIG_MODULES 33 + void apply_alternatives_module(void *start, size_t length); 34 + #else 35 + static inline void apply_alternatives_module(void *start, size_t length) { } 36 + #endif 32 37 33 38 #define ALTINSTR_ENTRY(feature,cb) \ 34 39 " .word 661b - .\n" /* label */ \
+1 -5
arch/arm64/include/asm/pgtable.h
··· 224 224 * Only if the new pte is valid and kernel, otherwise TLB maintenance 225 225 * or update_mmu_cache() have the necessary barriers. 226 226 */ 227 - if (pte_valid_not_user(pte)) { 227 + if (pte_valid_not_user(pte)) 228 228 dsb(ishst); 229 - isb(); 230 - } 231 229 } 232 230 233 231 extern void __sync_icache_dcache(pte_t pteval); ··· 432 434 { 433 435 WRITE_ONCE(*pmdp, pmd); 434 436 dsb(ishst); 435 - isb(); 436 437 } 437 438 438 439 static inline void pmd_clear(pmd_t *pmdp) ··· 482 485 { 483 486 WRITE_ONCE(*pudp, pud); 484 487 dsb(ishst); 485 - isb(); 486 488 } 487 489 488 490 static inline void pud_clear(pud_t *pudp)
+44 -7
arch/arm64/kernel/alternative.c
··· 122 122 } 123 123 } 124 124 125 - static void __apply_alternatives(void *alt_region, bool use_linear_alias) 125 + /* 126 + * We provide our own, private D-cache cleaning function so that we don't 127 + * accidentally call into the cache.S code, which is patched by us at 128 + * runtime. 129 + */ 130 + static void clean_dcache_range_nopatch(u64 start, u64 end) 131 + { 132 + u64 cur, d_size, ctr_el0; 133 + 134 + ctr_el0 = read_sanitised_ftr_reg(SYS_CTR_EL0); 135 + d_size = 4 << cpuid_feature_extract_unsigned_field(ctr_el0, 136 + CTR_DMINLINE_SHIFT); 137 + cur = start & ~(d_size - 1); 138 + do { 139 + /* 140 + * We must clean+invalidate to the PoC in order to avoid 141 + * Cortex-A53 errata 826319, 827319, 824069 and 819472 142 + * (this corresponds to ARM64_WORKAROUND_CLEAN_CACHE) 143 + */ 144 + asm volatile("dc civac, %0" : : "r" (cur) : "memory"); 145 + } while (cur += d_size, cur < end); 146 + } 147 + 148 + static void __apply_alternatives(void *alt_region, bool is_module) 126 149 { 127 150 struct alt_instr *alt; 128 151 struct alt_region *region = alt_region; ··· 168 145 pr_info_once("patching kernel code\n"); 169 146 170 147 origptr = ALT_ORIG_PTR(alt); 171 - updptr = use_linear_alias ? lm_alias(origptr) : origptr; 148 + updptr = is_module ? origptr : lm_alias(origptr); 172 149 nr_inst = alt->orig_len / AARCH64_INSN_SIZE; 173 150 174 151 if (alt->cpufeature < ARM64_CB_PATCH) ··· 178 155 179 156 alt_cb(alt, origptr, updptr, nr_inst); 180 157 181 - flush_icache_range((uintptr_t)origptr, 182 - (uintptr_t)(origptr + nr_inst)); 158 + if (!is_module) { 159 + clean_dcache_range_nopatch((u64)origptr, 160 + (u64)(origptr + nr_inst)); 161 + } 162 + } 163 + 164 + /* 165 + * The core module code takes care of cache maintenance in 166 + * flush_module_icache(). 167 + */ 168 + if (!is_module) { 169 + dsb(ish); 170 + __flush_icache_all(); 171 + isb(); 183 172 } 184 173 } 185 174 ··· 213 178 isb(); 214 179 } else { 215 180 BUG_ON(alternatives_applied); 216 - __apply_alternatives(&region, true); 181 + __apply_alternatives(&region, false); 217 182 /* Barriers provided by the cache flushing */ 218 183 WRITE_ONCE(alternatives_applied, 1); 219 184 } ··· 227 192 stop_machine(__apply_alternatives_multi_stop, NULL, cpu_online_mask); 228 193 } 229 194 230 - void apply_alternatives(void *start, size_t length) 195 + #ifdef CONFIG_MODULES 196 + void apply_alternatives_module(void *start, size_t length) 231 197 { 232 198 struct alt_region region = { 233 199 .begin = start, 234 200 .end = start + length, 235 201 }; 236 202 237 - __apply_alternatives(&region, false); 203 + __apply_alternatives(&region, true); 238 204 } 205 + #endif
+2 -3
arch/arm64/kernel/module.c
··· 448 448 const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 449 449 450 450 for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) { 451 - if (strcmp(".altinstructions", secstrs + s->sh_name) == 0) { 452 - apply_alternatives((void *)s->sh_addr, s->sh_size); 453 - } 451 + if (strcmp(".altinstructions", secstrs + s->sh_name) == 0) 452 + apply_alternatives_module((void *)s->sh_addr, s->sh_size); 454 453 #ifdef CONFIG_ARM64_MODULE_PLTS 455 454 if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE) && 456 455 !strcmp(".text.ftrace_trampoline", secstrs + s->sh_name))
+1 -1
drivers/perf/xgene_pmu.c
··· 1463 1463 case PMU_TYPE_IOB: 1464 1464 return devm_kasprintf(dev, GFP_KERNEL, "iob%d", id); 1465 1465 case PMU_TYPE_IOB_SLOW: 1466 - return devm_kasprintf(dev, GFP_KERNEL, "iob-slow%d", id); 1466 + return devm_kasprintf(dev, GFP_KERNEL, "iob_slow%d", id); 1467 1467 case PMU_TYPE_MCB: 1468 1468 return devm_kasprintf(dev, GFP_KERNEL, "mcb%d", id); 1469 1469 case PMU_TYPE_MC: