Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 6ca445d

Browse files
Alexandre Ghitipalmer-dabbelt
authored andcommitted
riscv: Fix early ftrace nop patching
Commit c97bf62 ("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: c97bf62 ("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>
1 parent 46cad6c commit 6ca445d

File tree

2 files changed

+9
-0
lines changed

2 files changed

+9
-0
lines changed

arch/riscv/include/asm/cacheflush.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ static inline void local_flush_icache_all(void)
1313
asm volatile ("fence.i" ::: "memory");
1414
}
1515

16+
static inline void local_flush_icache_range(unsigned long start,
17+
unsigned long end)
18+
{
19+
local_flush_icache_all();
20+
}
21+
1622
#define PG_dcache_clean PG_arch_1
1723

1824
static inline void flush_dcache_folio(struct folio *folio)

arch/riscv/kernel/ftrace.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
120120
out = ftrace_make_nop(mod, rec, MCOUNT_ADDR);
121121
mutex_unlock(&text_mutex);
122122

123+
if (!mod)
124+
local_flush_icache_range(rec->ip, rec->ip + MCOUNT_INSN_SIZE);
125+
123126
return out;
124127
}
125128

0 commit comments

Comments
 (0)