Skip to content

Commit e3ef9a2

Browse files
seehearfeelchenhuacai
authored andcommitted
LoongArch: kprobes: Use larch_insn_text_copy() to patch instructions
On SMP systems, kprobe handlers would occasionally fail to execute on certain CPU cores. The issue is hard to reproduce and typically occurs randomly under high system load. The root cause is a software-side instruction hazard. According to the LoongArch Reference Manual, while the cache coherency is maintained by hardware, software must explicitly use the "IBAR" instruction to ensure the instruction fetch unit (IFU) observes the effects of recent stores. The current arch_arm_kprobe() and arch_disarm_kprobe() only execute the "IBAR" barrier (via flush_insn_slot -> local_flush_icache_range) on the local CPU. This leaves a vulnerable window where remote CPU cores may continue executing stale instructions from their pipelines or prefetch buffers, as they have not executed an "IBAR" since the code modification. Switch to larch_insn_text_copy() to fix this: 1. Synchronization: It uses stop_machine_cpuslocked() to synchronize all online CPUs, ensuring no CPU is executing the target code area during modification. 2. Visibility: By passing cpu_online_mask to stop_machine_cpuslocked(), the callback text_copy_cb() is executed on all online cores. Each CPU core invokes local_flush_icache_range() to execute "IBAR", clearing instruction hazards system-wide and ensuring the "break" instruction is visible to the fetch units of all cores. 3. Robustness: It properly manages memory write permissions (ROX/RW) for the kernel text segment during patching, ensuring compatibility with CONFIG_STRICT_KERNEL_RWX. Cc: <stable@vger.kernel.org> # 6.18+ Fixes: 6d4cc40 ("LoongArch: Add kprobes support") Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
1 parent 0ccc9d4 commit e3ef9a2

1 file changed

Lines changed: 6 additions & 4 deletions

File tree

arch/loongarch/kernel/kprobes.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,18 @@ NOKPROBE_SYMBOL(arch_prepare_kprobe);
6060
/* Install breakpoint in text */
6161
void arch_arm_kprobe(struct kprobe *p)
6262
{
63-
*p->addr = KPROBE_BP_INSN;
64-
flush_insn_slot(p);
63+
u32 insn = KPROBE_BP_INSN;
64+
65+
larch_insn_text_copy(p->addr, &insn, LOONGARCH_INSN_SIZE);
6566
}
6667
NOKPROBE_SYMBOL(arch_arm_kprobe);
6768

6869
/* Remove breakpoint from text */
6970
void arch_disarm_kprobe(struct kprobe *p)
7071
{
71-
*p->addr = p->opcode;
72-
flush_insn_slot(p);
72+
u32 insn = p->opcode;
73+
74+
larch_insn_text_copy(p->addr, &insn, LOONGARCH_INSN_SIZE);
7375
}
7476
NOKPROBE_SYMBOL(arch_disarm_kprobe);
7577

0 commit comments

Comments
 (0)