Commit b7e7c85d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 2d63ba3e b6143d10
Loading
Loading
Loading
Loading
+11 −3
Original line number Diff line number Diff line
@@ -184,9 +184,17 @@ static const struct arm64_ftr_bits ftr_id_aa64zfr0[] = {
};

static const struct arm64_ftr_bits ftr_id_aa64mmfr0[] = {
	S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
	S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),
	/*
	 * We already refuse to boot CPUs that don't support our configured
	 * page size, so we can only detect mismatches for a page size other
	 * than the one we're currently using. Unfortunately, SoCs like this
	 * exist in the wild so, even though we don't like it, we'll have to go
	 * along with it and treat them as non-strict.
	 */
	S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN4_SHIFT, 4, ID_AA64MMFR0_TGRAN4_NI),
	S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN64_SHIFT, 4, ID_AA64MMFR0_TGRAN64_NI),
	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_TGRAN16_SHIFT, 4, ID_AA64MMFR0_TGRAN16_NI),

	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_BIGENDEL0_SHIFT, 4, 0),
	/* Linux shouldn't care about secure memory */
	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64MMFR0_SNSMEM_SHIFT, 4, 0),
+13 −9
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)

	if (offset < -SZ_128M || offset >= SZ_128M) {
#ifdef CONFIG_ARM64_MODULE_PLTS
		struct plt_entry trampoline;
		struct plt_entry trampoline, *dst;
		struct module *mod;

		/*
@@ -106,23 +106,27 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
		 * to check if the actual opcodes are in fact identical,
		 * regardless of the offset in memory so use memcmp() instead.
		 */
		trampoline = get_plt_entry(addr, mod->arch.ftrace_trampoline);
		if (memcmp(mod->arch.ftrace_trampoline, &trampoline,
			   sizeof(trampoline))) {
			if (plt_entry_is_initialized(mod->arch.ftrace_trampoline)) {
		dst = mod->arch.ftrace_trampoline;
		trampoline = get_plt_entry(addr, dst);
		if (memcmp(dst, &trampoline, sizeof(trampoline))) {
			if (plt_entry_is_initialized(dst)) {
				pr_err("ftrace: far branches to multiple entry points unsupported inside a single module\n");
				return -EINVAL;
			}

			/* point the trampoline to our ftrace entry point */
			module_disable_ro(mod);
			*mod->arch.ftrace_trampoline = trampoline;
			*dst = trampoline;
			module_enable_ro(mod, true);

			/* update trampoline before patching in the branch */
			smp_wmb();
			/*
			 * Ensure updated trampoline is visible to instruction
			 * fetch before we patch in the branch.
			 */
			__flush_icache_range((unsigned long)&dst[0],
					     (unsigned long)&dst[1]);
		}
		addr = (unsigned long)(void *)mod->arch.ftrace_trampoline;
		addr = (unsigned long)dst;
#else /* CONFIG_ARM64_MODULE_PLTS */
		return -EINVAL;
#endif /* CONFIG_ARM64_MODULE_PLTS */