mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-18 18:43:59 +08:00
arm64: rethook: Add arm64 rethook implementation
Add rethook arm64 implementation. Most of the code has been copied from kretprobes on arm64. Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Tested-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Link: https://lore.kernel.org/bpf/164735287344.1084943.9787335632585653418.stgit@devnote2
This commit is contained in:
parent
75caf33eda
commit
83acdce689
@ -201,6 +201,7 @@ config ARM64
|
||||
select HAVE_SYSCALL_TRACEPOINTS
|
||||
select HAVE_KPROBES
|
||||
select HAVE_KRETPROBES
|
||||
select HAVE_RETHOOK
|
||||
select HAVE_GENERIC_VDSO
|
||||
select IOMMU_DMA if IOMMU_SUPPORT
|
||||
select IRQ_DOMAIN
|
||||
|
@ -58,7 +58,7 @@ struct stackframe {
|
||||
DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
|
||||
unsigned long prev_fp;
|
||||
enum stack_type prev_type;
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
#if defined(CONFIG_KRETPROBES) || defined(CONFIG_RETHOOK)
|
||||
struct llist_node *kr_cur;
|
||||
#endif
|
||||
};
|
||||
|
@ -4,3 +4,4 @@ obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o \
|
||||
simulate-insn.o
|
||||
obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o \
|
||||
simulate-insn.o
|
||||
obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o
|
||||
|
25
arch/arm64/kernel/probes/rethook.c
Normal file
25
arch/arm64/kernel/probes/rethook.c
Normal file
@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Generic return hook for arm64.
|
||||
* Most of the code is copied from arch/arm64/kernel/probes/kprobes.c
|
||||
*/
|
||||
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/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->regs[29]);
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_rethook_trampoline_callback);
|
||||
|
||||
void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount)
|
||||
{
|
||||
rhn->ret_addr = regs->regs[30];
|
||||
rhn->frame = regs->regs[29];
|
||||
|
||||
/* replace return addr (x30) with trampoline */
|
||||
regs->regs[30] = (u64)arch_rethook_trampoline;
|
||||
}
|
||||
NOKPROBE_SYMBOL(arch_rethook_prepare);
|
87
arch/arm64/kernel/probes/rethook_trampoline.S
Normal file
87
arch/arm64/kernel/probes/rethook_trampoline.S
Normal file
@ -0,0 +1,87 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* trampoline entry and return code for rethook.
|
||||
* Copied from arch/arm64/kernel/probes/kprobes_trampoline.S
|
||||
*/
|
||||
|
||||
#include <linux/linkage.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/assembler.h>
|
||||
|
||||
.text
|
||||
|
||||
.macro save_all_base_regs
|
||||
stp x0, x1, [sp, #S_X0]
|
||||
stp x2, x3, [sp, #S_X2]
|
||||
stp x4, x5, [sp, #S_X4]
|
||||
stp x6, x7, [sp, #S_X6]
|
||||
stp x8, x9, [sp, #S_X8]
|
||||
stp x10, x11, [sp, #S_X10]
|
||||
stp x12, x13, [sp, #S_X12]
|
||||
stp x14, x15, [sp, #S_X14]
|
||||
stp x16, x17, [sp, #S_X16]
|
||||
stp x18, x19, [sp, #S_X18]
|
||||
stp x20, x21, [sp, #S_X20]
|
||||
stp x22, x23, [sp, #S_X22]
|
||||
stp x24, x25, [sp, #S_X24]
|
||||
stp x26, x27, [sp, #S_X26]
|
||||
stp x28, x29, [sp, #S_X28]
|
||||
add x0, sp, #PT_REGS_SIZE
|
||||
stp lr, x0, [sp, #S_LR]
|
||||
/*
|
||||
* Construct a useful saved PSTATE
|
||||
*/
|
||||
mrs x0, nzcv
|
||||
mrs x1, daif
|
||||
orr x0, x0, x1
|
||||
mrs x1, CurrentEL
|
||||
orr x0, x0, x1
|
||||
mrs x1, SPSel
|
||||
orr x0, x0, x1
|
||||
stp xzr, x0, [sp, #S_PC]
|
||||
.endm
|
||||
|
||||
.macro restore_all_base_regs
|
||||
ldr x0, [sp, #S_PSTATE]
|
||||
and x0, x0, #(PSR_N_BIT | PSR_Z_BIT | PSR_C_BIT | PSR_V_BIT)
|
||||
msr nzcv, x0
|
||||
ldp x0, x1, [sp, #S_X0]
|
||||
ldp x2, x3, [sp, #S_X2]
|
||||
ldp x4, x5, [sp, #S_X4]
|
||||
ldp x6, x7, [sp, #S_X6]
|
||||
ldp x8, x9, [sp, #S_X8]
|
||||
ldp x10, x11, [sp, #S_X10]
|
||||
ldp x12, x13, [sp, #S_X12]
|
||||
ldp x14, x15, [sp, #S_X14]
|
||||
ldp x16, x17, [sp, #S_X16]
|
||||
ldp x18, x19, [sp, #S_X18]
|
||||
ldp x20, x21, [sp, #S_X20]
|
||||
ldp x22, x23, [sp, #S_X22]
|
||||
ldp x24, x25, [sp, #S_X24]
|
||||
ldp x26, x27, [sp, #S_X26]
|
||||
ldp x28, x29, [sp, #S_X28]
|
||||
.endm
|
||||
|
||||
SYM_CODE_START(arch_rethook_trampoline)
|
||||
sub sp, sp, #PT_REGS_SIZE
|
||||
|
||||
save_all_base_regs
|
||||
|
||||
/* Setup a frame pointer. */
|
||||
add x29, sp, #S_FP
|
||||
|
||||
mov x0, sp
|
||||
bl arch_rethook_trampoline_callback
|
||||
/*
|
||||
* Replace trampoline address in lr with actual orig_ret_addr return
|
||||
* address.
|
||||
*/
|
||||
mov lr, x0
|
||||
|
||||
/* The frame pointer (x29) is restored with other registers. */
|
||||
restore_all_base_regs
|
||||
|
||||
add sp, sp, #PT_REGS_SIZE
|
||||
ret
|
||||
|
||||
SYM_CODE_END(arch_rethook_trampoline)
|
@ -8,6 +8,7 @@
|
||||
#include <linux/export.h>
|
||||
#include <linux/ftrace.h>
|
||||
#include <linux/kprobes.h>
|
||||
#include <linux/rethook.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/debug.h>
|
||||
#include <linux/sched/task_stack.h>
|
||||
@ -38,7 +39,7 @@ static notrace void start_backtrace(struct stackframe *frame, unsigned long fp,
|
||||
{
|
||||
frame->fp = fp;
|
||||
frame->pc = pc;
|
||||
#ifdef CONFIG_KRETPROBES
|
||||
#if defined(CONFIG_KRETPROBES) || defined(CONFIG_RETHOOK)
|
||||
frame->kr_cur = NULL;
|
||||
#endif
|
||||
|
||||
@ -138,6 +139,10 @@ static int notrace unwind_frame(struct task_struct *tsk,
|
||||
if (is_kretprobe_trampoline(frame->pc))
|
||||
frame->pc = kretprobe_find_ret_addr(tsk, (void *)frame->fp, &frame->kr_cur);
|
||||
#endif
|
||||
#ifdef CONFIG_RETHOOK
|
||||
if (is_rethook_trampoline(frame->pc))
|
||||
frame->pc = rethook_find_ret_addr(tsk, frame->fp, &frame->kr_cur);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user