riscv: Fix text patching when IPI are used
BugLink: https://bugs.launchpad.net/bugs/2106770 [ Upstream commit c97bf629963e52b205ed5fbaf151e5bd342f9c63 ] For now, we use stop_machine() to patch the text and when we use IPIs for remote icache flushes (which is emitted in patch_text_nosync()), the system hangs. So instead, make sure every CPU executes the stop_machine() patching function and emit a local icache flush there. Co-developed-by: Björn Töpel <bjorn@rivosinc.com> Signed-off-by: Björn Töpel <bjorn@rivosinc.com> Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com> Reviewed-by: Andrea Parri <parri.andrea@gmail.com> Link: https://lore.kernel.org/r/20240229121056.203419-3-alexghiti@rivosinc.com Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com> Stable-dep-of: 13134cc94914 ("riscv: kprobes: Fix incorrect address calculation") Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Manuel Diewald <manuel.diewald@canonical.com> Signed-off-by: Mehmet Basaran <mehmet.basaran@canonical.com>
This commit is contained in:
committed by
Mehmet Basaran
parent
8f51c0715e
commit
d2d85f20ee
@@ -196,7 +196,7 @@ int patch_text_set_nosync(void *addr, u8 c, size_t len)
|
||||
}
|
||||
NOKPROBE_SYMBOL(patch_text_set_nosync);
|
||||
|
||||
static int patch_insn_write(void *addr, const void *insn, size_t len)
|
||||
int patch_insn_write(void *addr, const void *insn, size_t len)
|
||||
{
|
||||
size_t patched = 0;
|
||||
size_t size;
|
||||
@@ -240,16 +240,24 @@ static int patch_text_cb(void *data)
|
||||
if (atomic_inc_return(&patch->cpu_count) == num_online_cpus()) {
|
||||
for (i = 0; ret == 0 && i < patch->ninsns; i++) {
|
||||
len = GET_INSN_LENGTH(patch->insns[i]);
|
||||
ret = patch_text_nosync(patch->addr + i * len,
|
||||
&patch->insns[i], len);
|
||||
ret = patch_insn_write(patch->addr + i * len, &patch->insns[i], len);
|
||||
}
|
||||
atomic_inc(&patch->cpu_count);
|
||||
/*
|
||||
* Make sure the patching store is effective *before* we
|
||||
* increment the counter which releases all waiting CPUs
|
||||
* by using the release variant of atomic increment. The
|
||||
* release pairs with the call to local_flush_icache_all()
|
||||
* on the waiting CPU.
|
||||
*/
|
||||
atomic_inc_return_release(&patch->cpu_count);
|
||||
} else {
|
||||
while (atomic_read(&patch->cpu_count) <= num_online_cpus())
|
||||
cpu_relax();
|
||||
smp_mb();
|
||||
}
|
||||
|
||||
local_flush_icache_all();
|
||||
|
||||
return ret;
|
||||
}
|
||||
NOKPROBE_SYMBOL(patch_text_cb);
|
||||
|
||||
Reference in New Issue
Block a user