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:

- Don't taint the kernel if CPUs have different sets of page sizes
supported (other than the one in use).

- Issue I-cache maintenance for module ftrace trampoline.

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
arm64: ftrace: Ensure module ftrace trampoline is coherent with I-side
arm64: cpufeature: Don't treat granule sizes as strict

+24 -12
+11 -3
arch/arm64/kernel/cpufeature.c
··· 184 184 }; 185 185 186 186 static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = { 187 - S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI), 188 - S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI), 189 - ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI), 187 + /* 188 + * We already refuse to boot CPUs that don't support our configured 189 + * page size, so we can only detect mismatches for a page size other 190 + * than the one we're currently using. Unfortunately, SoCs like this 191 + * exist in the wild so, even though we don't like it, we'll have to go 192 + * along with it and treat them as non-strict. 193 + */ 194 + S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI), 195 + S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI), 196 + ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI), 197 + 190 198 ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0), 191 199 /* Linux shouldn't care about secure memory */ 192 200 ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
+13 -9
arch/arm64/kernel/ftrace.c
··· 73 73 74 74 if (offset < -SZ_128M || offset >= SZ_128M) { 75 75 #ifdef CONFIG_ARM64_MODULE_PLTS 76 - struct plt_entry trampoline; 76 + struct plt_entry trampoline, *dst; 77 77 struct module *mod; 78 78 79 79 /* ··· 106 106 * to check if the actual opcodes are in fact identical, 107 107 * regardless of the offset in memory so use memcmp() instead. 108 108 */ 109 - trampoline = get_plt_entry(addr, mod->arch.ftrace_trampoline); 110 - if (memcmp(mod->arch.ftrace_trampoline, &trampoline, 111 - sizeof(trampoline))) { 112 - if (plt_entry_is_initialized(mod->arch.ftrace_trampoline)) { 109 + dst = mod->arch.ftrace_trampoline; 110 + trampoline = get_plt_entry(addr, dst); 111 + if (memcmp(dst, &trampoline, sizeof(trampoline))) { 112 + if (plt_entry_is_initialized(dst)) { 113 113 pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n"); 114 114 return -EINVAL; 115 115 } 116 116 117 117 /* point the trampoline to our ftrace entry point */ 118 118 module_disable_ro(mod); 119 - *mod->arch.ftrace_trampoline = trampoline; 119 + *dst = trampoline; 120 120 module_enable_ro(mod, true); 121 121 122 - /* update trampoline before patching in the branch */ 123 - smp_wmb(); 122 + /* 123 + * Ensure updated trampoline is visible to instruction 124 + * fetch before we patch in the branch. 125 + */ 126 + __flush_icache_range((unsigned long)&dst[0], 127 + (unsigned long)&dst[1]); 124 128 } 125 - addr = (unsigned long)(void *)mod->arch.ftrace_trampoline; 129 + addr = (unsigned long)dst; 126 130 #else /* CONFIG_ARM64_MODULE_PLTS */ 127 131 return -EINVAL; 128 132 #endif /* CONFIG_ARM64_MODULE_PLTS */