riscv: add riscv rethook implementation

Implement the kretprobes on riscv arch by using rethook machenism
which abstracts general kretprobe info into a struct rethook_node
to be embedded in the struct kretprobe_instance.

Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Binglei Wang <l3b2w1@gmail.com>
Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
Link: https://lore.kernel.org/r/20221025151831.1097417-1-conor@kernel.org
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
Binglei Wang 2022-10-25 16:18:32 +01:00 committed by Palmer Dabbelt
parent d8bf77a1dc
commit b57c2f1240
No known key found for this signature in database
GPG Key ID: 2E1319F35FBB1889
7 changed files with 40 additions and 19 deletions

View File

@ -101,6 +101,7 @@ config RISCV
select HAVE_KPROBES if !XIP_KERNEL select HAVE_KPROBES if !XIP_KERNEL
select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL select HAVE_KPROBES_ON_FTRACE if !XIP_KERNEL
select HAVE_KRETPROBES if !XIP_KERNEL select HAVE_KRETPROBES if !XIP_KERNEL
select HAVE_RETHOOK if !XIP_KERNEL
select HAVE_MOVE_PMD select HAVE_MOVE_PMD
select HAVE_MOVE_PUD select HAVE_MOVE_PUD
select HAVE_PCI select HAVE_PCI

View File

@ -40,8 +40,6 @@ void arch_remove_kprobe(struct kprobe *p);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr); int kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr);
bool kprobe_breakpoint_handler(struct pt_regs *regs); bool kprobe_breakpoint_handler(struct pt_regs *regs);
bool kprobe_single_step_handler(struct pt_regs *regs); bool kprobe_single_step_handler(struct pt_regs *regs);
void __kretprobe_trampoline(void);
void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
#endif /* CONFIG_KPROBES */ #endif /* CONFIG_KPROBES */
#endif /* _ASM_RISCV_KPROBES_H */ #endif /* _ASM_RISCV_KPROBES_H */

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o simulate-insn.o obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o simulate-insn.o
obj-$(CONFIG_KPROBES) += kprobes_trampoline.o obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o
obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o
obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o simulate-insn.o obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o simulate-insn.o
CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE)

View File

@ -345,19 +345,6 @@ int __init arch_populate_kprobe_blacklist(void)
return ret; return ret;
} }
void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
{
return (void *)kretprobe_trampoline_handler(regs, NULL);
}
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
ri->ret_addr = (kprobe_opcode_t *)regs->ra;
ri->fp = NULL;
regs->ra = (unsigned long) &__kretprobe_trampoline;
}
int __kprobes arch_trampoline_kprobe(struct kprobe *p) int __kprobes arch_trampoline_kprobe(struct kprobe *p)
{ {
return 0; return 0;

View File

@ -0,0 +1,27 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Generic return hook for riscv.
*/
#include <linux/kprobes.h>
#include <linux/rethook.h>
#include "rethook.h"
/* This is called from arch_rethook_trampoline() */
unsigned long __used arch_rethook_trampoline_callback(struct pt_regs *regs)
{
return rethook_trampoline_handler(regs, regs->s0);
}
NOKPROBE_SYMBOL(arch_rethook_trampoline_callback);
void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount)
{
rhn->ret_addr = regs->ra;
rhn->frame = regs->s0;
/* replace return addr with trampoline */
regs->ra = (unsigned long)arch_rethook_trampoline;
}
NOKPROBE_SYMBOL(arch_rethook_prepare);

View File

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __RISCV_RETHOOK_H
#define __RISCV_RETHOOK_H
unsigned long arch_rethook_trampoline_callback(struct pt_regs *regs);
void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount);
#endif

View File

@ -75,13 +75,13 @@
REG_L x31, PT_T6(sp) REG_L x31, PT_T6(sp)
.endm .endm
ENTRY(__kretprobe_trampoline) ENTRY(arch_rethook_trampoline)
addi sp, sp, -(PT_SIZE_ON_STACK) addi sp, sp, -(PT_SIZE_ON_STACK)
save_all_base_regs save_all_base_regs
move a0, sp /* pt_regs */ move a0, sp /* pt_regs */
call trampoline_probe_handler call arch_rethook_trampoline_callback
/* use the result as the return-address */ /* use the result as the return-address */
move ra, a0 move ra, a0
@ -90,4 +90,4 @@ ENTRY(__kretprobe_trampoline)
addi sp, sp, PT_SIZE_ON_STACK addi sp, sp, PT_SIZE_ON_STACK
ret ret
ENDPROC(__kretprobe_trampoline) ENDPROC(arch_rethook_trampoline)