aboutsummaryrefslogtreecommitdiff
path: root/arch/riscv/kernel
diff options
context:
space:
mode:
authorGravatar Alexandre Ghiti <alexghiti@rivosinc.com> 2024-05-23 13:51:34 +0200
committerGravatar Palmer Dabbelt <palmer@rivosinc.com> 2024-05-23 08:22:17 -0700
commit6ca445d8af0ed5950ebf899415fd6bfcd7d9d7a3 (patch)
tree0927a03832641e507c08fbec6ed867cae878fc1c /arch/riscv/kernel
parentirqchip: riscv-imsic: Fixup riscv_ipi_set_virq_range() conflict (diff)
downloadlinux-6ca445d8af0ed5950ebf899415fd6bfcd7d9d7a3.tar.gz
linux-6ca445d8af0ed5950ebf899415fd6bfcd7d9d7a3.tar.bz2
linux-6ca445d8af0ed5950ebf899415fd6bfcd7d9d7a3.zip
riscv: Fix early ftrace nop patching
Commit c97bf629963e ("riscv: Fix text patching when IPI are used") converted ftrace_make_nop() to use patch_insn_write() which does not emit any icache flush relying entirely on __ftrace_modify_code() to do that. But we missed that ftrace_make_nop() was called very early directly when converting mcount calls into nops (actually on riscv it converts 2B nops emitted by the compiler into 4B nops). This caused crashes on multiple HW as reported by Conor and Björn since the booting core could have half-patched instructions in its icache which would trigger an illegal instruction trap: fix this by emitting a local flush icache when early patching nops. Fixes: c97bf629963e ("riscv: Fix text patching when IPI are used") Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com> Reported-by: Conor Dooley <conor.dooley@microchip.com> Tested-by: Conor Dooley <conor.dooley@microchip.com> Reviewed-by: Björn Töpel <bjorn@rivosinc.com> Tested-by: Björn Töpel <bjorn@rivosinc.com> Link: https://lore.kernel.org/r/20240523115134.70380-1-alexghiti@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
Diffstat (limited to 'arch/riscv/kernel')
-rw-r--r--arch/riscv/kernel/ftrace.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index 4d14eadcd765..87cbd86576b2 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -120,6 +120,9 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
out = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
mutex_unlock(&text_mutex);
+ if (!mod)
+ local_flush_icache_range(rec->ip, rec->ip + MCOUNT_INSN_SIZE);
+
return out;
}