LoongArch: Replace kretprobe with rethook
authorHaoran Jiang <jianghaoran@kylinos.cn>
Thu, 29 Jun 2023 12:58:44 +0000 (20:58 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Thu, 29 Jun 2023 12:58:44 +0000 (20:58 +0800)
This is an adaptation of commit f3a112c0c40d ("x86,rethook,kprobes:
Replace kretprobe with rethook on x86") and commit b57c2f124098 ("riscv:
add riscv rethook implementation") to LoongArch. Mainly refer to commit
b57c2f124098 ("riscv: add riscv rethook implementation").

Replaces the kretprobe code with rethook on LoongArch. With this patch,
kretprobe on LoongArch uses the rethook instead of kretprobe specific
trampoline code.

Signed-off-by: Haoran Jiang <jianghaoran@kylinos.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/Kconfig
arch/loongarch/include/asm/kprobes.h
arch/loongarch/kernel/Makefile
arch/loongarch/kernel/kprobes.c
arch/loongarch/kernel/kprobes_trampoline.S [deleted file]
arch/loongarch/kernel/rethook.c [new file with mode: 0644]
arch/loongarch/kernel/rethook.h [new file with mode: 0644]
arch/loongarch/kernel/rethook_trampoline.S [new file with mode: 0644]

index 64cdc68022954b28ae5f258c6efaeff0413a01ba..b787f8fcbac7642af06e9c53d70c913ba4cf2b3e 100644 (file)
@@ -127,6 +127,7 @@ config LOONGARCH
        select HAVE_PERF_REGS
        select HAVE_PERF_USER_STACK_DUMP
        select HAVE_REGS_AND_STACK_ACCESS_API
+       select HAVE_RETHOOK
        select HAVE_RSEQ
        select HAVE_SAMPLE_FTRACE_DIRECT
        select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
index 798020ae02c694b8623206383ebb5d1417e6683c..7b9fc3ed71c378c0607540c77d3d90b6e9f21eca 100644 (file)
@@ -49,9 +49,6 @@ bool kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 bool kprobe_breakpoint_handler(struct pt_regs *regs);
 bool kprobe_singlestep_handler(struct pt_regs *regs);
 
-void __kretprobe_trampoline(void);
-void *trampoline_probe_handler(struct pt_regs *regs);
-
 #else /* !CONFIG_KPROBES */
 
 static inline bool kprobe_breakpoint_handler(struct pt_regs *regs) { return false; }
index 64ea76f60e2c6abd952df8a72650bbddcaddd0a2..1061c36f5ad5275ec4ea9e6640825d2b557128e0 100644 (file)
@@ -28,6 +28,8 @@ ifdef CONFIG_FUNCTION_TRACER
   CFLAGS_REMOVE_inst.o = $(CC_FLAGS_FTRACE)
   CFLAGS_REMOVE_time.o = $(CC_FLAGS_FTRACE)
   CFLAGS_REMOVE_perf_event.o = $(CC_FLAGS_FTRACE)
+  CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE)
+  CFLAGS_REMOVE_rethook_trampoline.o = $(CC_FLAGS_FTRACE)
 endif
 
 obj-$(CONFIG_MODULES)          += module.o module-sections.o
@@ -52,7 +54,8 @@ obj-$(CONFIG_UNWINDER_PROLOGUE) += unwind_prologue.o
 obj-$(CONFIG_PERF_EVENTS)      += perf_event.o perf_regs.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += hw_breakpoint.o
 
-obj-$(CONFIG_KPROBES)          += kprobes.o kprobes_trampoline.o
+obj-$(CONFIG_KPROBES)          += kprobes.o
+obj-$(CONFIG_RETHOOK)          += rethook.o rethook_trampoline.o
 
 obj-$(CONFIG_JUMP_LABEL)       += jump_label.o
 
index 56c8c4b09a4299652e10cf65c9073a016a93891f..83467232ca3c50d816a3be76f4659a2aec8c8a6d 100644 (file)
@@ -378,27 +378,6 @@ int __init arch_init_kprobes(void)
        return 0;
 }
 
-/* ASM function that handles the kretprobes must not be probed */
-NOKPROBE_SYMBOL(__kretprobe_trampoline);
-
-/* Called from __kretprobe_trampoline */
-void __used *trampoline_probe_handler(struct pt_regs *regs)
-{
-       return (void *)kretprobe_trampoline_handler(regs, NULL);
-}
-NOKPROBE_SYMBOL(trampoline_probe_handler);
-
-void arch_prepare_kretprobe(struct kretprobe_instance *ri,
-                           struct pt_regs *regs)
-{
-       ri->ret_addr = (kprobe_opcode_t *)regs->regs[1];
-       ri->fp = NULL;
-
-       /* Replace the return addr with trampoline addr */
-       regs->regs[1] = (unsigned long)&__kretprobe_trampoline;
-}
-NOKPROBE_SYMBOL(arch_prepare_kretprobe);
-
 int arch_trampoline_kprobe(struct kprobe *p)
 {
        return 0;
diff --git a/arch/loongarch/kernel/kprobes_trampoline.S b/arch/loongarch/kernel/kprobes_trampoline.S
deleted file mode 100644 (file)
index af94b0d..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-#include <linux/linkage.h>
-#include <asm/stackframe.h>
-
-       .text
-
-       .macro save_all_base_regs
-       cfi_st  ra, PT_R1
-       cfi_st  tp, PT_R2
-       cfi_st  a0, PT_R4
-       cfi_st  a1, PT_R5
-       cfi_st  a2, PT_R6
-       cfi_st  a3, PT_R7
-       cfi_st  a4, PT_R8
-       cfi_st  a5, PT_R9
-       cfi_st  a6, PT_R10
-       cfi_st  a7, PT_R11
-       cfi_st  t0, PT_R12
-       cfi_st  t1, PT_R13
-       cfi_st  t2, PT_R14
-       cfi_st  t3, PT_R15
-       cfi_st  t4, PT_R16
-       cfi_st  t5, PT_R17
-       cfi_st  t6, PT_R18
-       cfi_st  t7, PT_R19
-       cfi_st  t8, PT_R20
-       cfi_st  u0, PT_R21
-       cfi_st  fp, PT_R22
-       cfi_st  s0, PT_R23
-       cfi_st  s1, PT_R24
-       cfi_st  s2, PT_R25
-       cfi_st  s3, PT_R26
-       cfi_st  s4, PT_R27
-       cfi_st  s5, PT_R28
-       cfi_st  s6, PT_R29
-       cfi_st  s7, PT_R30
-       cfi_st  s8, PT_R31
-       csrrd   t0, LOONGARCH_CSR_CRMD
-       andi    t0, t0, 0x7 /* extract bit[1:0] PLV, bit[2] IE */
-       LONG_S  t0, sp, PT_CRMD
-       .endm
-
-       .macro restore_all_base_regs
-       cfi_ld  tp, PT_R2
-       cfi_ld  a0, PT_R4
-       cfi_ld  a1, PT_R5
-       cfi_ld  a2, PT_R6
-       cfi_ld  a3, PT_R7
-       cfi_ld  a4, PT_R8
-       cfi_ld  a5, PT_R9
-       cfi_ld  a6, PT_R10
-       cfi_ld  a7, PT_R11
-       cfi_ld  t0, PT_R12
-       cfi_ld  t1, PT_R13
-       cfi_ld  t2, PT_R14
-       cfi_ld  t3, PT_R15
-       cfi_ld  t4, PT_R16
-       cfi_ld  t5, PT_R17
-       cfi_ld  t6, PT_R18
-       cfi_ld  t7, PT_R19
-       cfi_ld  t8, PT_R20
-       cfi_ld  u0, PT_R21
-       cfi_ld  fp, PT_R22
-       cfi_ld  s0, PT_R23
-       cfi_ld  s1, PT_R24
-       cfi_ld  s2, PT_R25
-       cfi_ld  s3, PT_R26
-       cfi_ld  s4, PT_R27
-       cfi_ld  s5, PT_R28
-       cfi_ld  s6, PT_R29
-       cfi_ld  s7, PT_R30
-       cfi_ld  s8, PT_R31
-       LONG_L  t0, sp, PT_CRMD
-       li.d    t1, 0x7 /* mask bit[1:0] PLV, bit[2] IE */
-       csrxchg t0, t1, LOONGARCH_CSR_CRMD
-       .endm
-
-SYM_CODE_START(__kretprobe_trampoline)
-       addi.d  sp, sp, -PT_SIZE
-       save_all_base_regs
-
-       addi.d  t0, sp, PT_SIZE
-       LONG_S  t0, sp, PT_R3
-
-       move a0, sp /* pt_regs */
-
-       bl trampoline_probe_handler
-
-       /* use the result as the return-address */
-       move ra, a0
-
-       restore_all_base_regs
-       addi.d  sp, sp, PT_SIZE
-
-       jr ra
-SYM_CODE_END(__kretprobe_trampoline)
diff --git a/arch/loongarch/kernel/rethook.c b/arch/loongarch/kernel/rethook.c
new file mode 100644 (file)
index 0000000..db1c5f5
--- /dev/null
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generic return hook for LoongArch.
+ */
+
+#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, 0);
+}
+NOKPROBE_SYMBOL(arch_rethook_trampoline_callback);
+
+void arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount)
+{
+       rhn->frame = 0;
+       rhn->ret_addr = regs->regs[1];
+
+       /* replace return addr with trampoline */
+       regs->regs[1] = (unsigned long)arch_rethook_trampoline;
+}
+NOKPROBE_SYMBOL(arch_rethook_prepare);
+
+/* ASM function that handles the rethook must not be probed itself */
+NOKPROBE_SYMBOL(arch_rethook_trampoline);
diff --git a/arch/loongarch/kernel/rethook.h b/arch/loongarch/kernel/rethook.h
new file mode 100644 (file)
index 0000000..3f1c1ed
--- /dev/null
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LOONGARCH_RETHOOK_H
+#define __LOONGARCH_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
diff --git a/arch/loongarch/kernel/rethook_trampoline.S b/arch/loongarch/kernel/rethook_trampoline.S
new file mode 100644 (file)
index 0000000..bd5772c
--- /dev/null
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#include <linux/linkage.h>
+#include <asm/stackframe.h>
+
+       .text
+
+       .macro save_all_base_regs
+       cfi_st  ra, PT_R1
+       cfi_st  tp, PT_R2
+       cfi_st  a0, PT_R4
+       cfi_st  a1, PT_R5
+       cfi_st  a2, PT_R6
+       cfi_st  a3, PT_R7
+       cfi_st  a4, PT_R8
+       cfi_st  a5, PT_R9
+       cfi_st  a6, PT_R10
+       cfi_st  a7, PT_R11
+       cfi_st  t0, PT_R12
+       cfi_st  t1, PT_R13
+       cfi_st  t2, PT_R14
+       cfi_st  t3, PT_R15
+       cfi_st  t4, PT_R16
+       cfi_st  t5, PT_R17
+       cfi_st  t6, PT_R18
+       cfi_st  t7, PT_R19
+       cfi_st  t8, PT_R20
+       cfi_st  u0, PT_R21
+       cfi_st  fp, PT_R22
+       cfi_st  s0, PT_R23
+       cfi_st  s1, PT_R24
+       cfi_st  s2, PT_R25
+       cfi_st  s3, PT_R26
+       cfi_st  s4, PT_R27
+       cfi_st  s5, PT_R28
+       cfi_st  s6, PT_R29
+       cfi_st  s7, PT_R30
+       cfi_st  s8, PT_R31
+       csrrd   t0, LOONGARCH_CSR_CRMD
+       andi    t0, t0, 0x7 /* extract bit[1:0] PLV, bit[2] IE */
+       LONG_S  t0, sp, PT_CRMD
+       .endm
+
+       .macro restore_all_base_regs
+       cfi_ld  tp, PT_R2
+       cfi_ld  a0, PT_R4
+       cfi_ld  a1, PT_R5
+       cfi_ld  a2, PT_R6
+       cfi_ld  a3, PT_R7
+       cfi_ld  a4, PT_R8
+       cfi_ld  a5, PT_R9
+       cfi_ld  a6, PT_R10
+       cfi_ld  a7, PT_R11
+       cfi_ld  t0, PT_R12
+       cfi_ld  t1, PT_R13
+       cfi_ld  t2, PT_R14
+       cfi_ld  t3, PT_R15
+       cfi_ld  t4, PT_R16
+       cfi_ld  t5, PT_R17
+       cfi_ld  t6, PT_R18
+       cfi_ld  t7, PT_R19
+       cfi_ld  t8, PT_R20
+       cfi_ld  u0, PT_R21
+       cfi_ld  fp, PT_R22
+       cfi_ld  s0, PT_R23
+       cfi_ld  s1, PT_R24
+       cfi_ld  s2, PT_R25
+       cfi_ld  s3, PT_R26
+       cfi_ld  s4, PT_R27
+       cfi_ld  s5, PT_R28
+       cfi_ld  s6, PT_R29
+       cfi_ld  s7, PT_R30
+       cfi_ld  s8, PT_R31
+       LONG_L  t0, sp, PT_CRMD
+       li.d    t1, 0x7 /* mask bit[1:0] PLV, bit[2] IE */
+       csrxchg t0, t1, LOONGARCH_CSR_CRMD
+       .endm
+
+SYM_CODE_START(arch_rethook_trampoline)
+       addi.d  sp, sp, -PT_SIZE
+       save_all_base_regs
+
+       addi.d  t0, sp, PT_SIZE
+       LONG_S  t0, sp, PT_R3
+
+       move a0, sp /* pt_regs */
+
+       bl arch_rethook_trampoline_callback
+
+       /* use the result as the return-address */
+       move ra, a0
+
+       restore_all_base_regs
+       addi.d  sp, sp, PT_SIZE
+
+       jr ra
+SYM_CODE_END(arch_rethook_trampoline)