mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
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:
parent
d8bf77a1dc
commit
b57c2f1240
@ -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
|
||||||
|
@ -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 */
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
27
arch/riscv/kernel/probes/rethook.c
Normal file
27
arch/riscv/kernel/probes/rethook.c
Normal 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);
|
8
arch/riscv/kernel/probes/rethook.h
Normal file
8
arch/riscv/kernel/probes/rethook.h
Normal 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
|
@ -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)
|
Loading…
Reference in New Issue
Block a user