[PATCH -next] arm64: ftrace: Add DYNAMIC_FTRACE_WITH_ARGS support

Li Huafei lihuafei1 at huawei.com
Tue Apr 19 19:09:42 PDT 2022


DYNAMIC_FTRACE_WITH_ARGS allows ftrace_ops without the FL_SAVE_REGS flag
set (via the "ftrace_caller" trampoline) to fetch all parameters and
stack pointer. On arm64, under the DYNAMIC_FTRACE_WITH_REGS
implementation, ftrace_caller() already supports filling the above
registers into pt_regs, all that remains to be done is to ensure that
arch_ftrace_get_regs() returns NULL when FL_SAVE_REGS is not set. We use
pt_regs::regs[10] to identify whether the FL_SAVE_REGS flag is set.

The mcount-based implementation supports DYNAMIC_FTRACE_WITH_ARGS with
some difficulty, as some registers (e.g. X0) are already clobbered
before entering the trampoline. We need to rely on gcc's
"-fpatchable-function-entry" feature, so here we have
DYNAMIC_FTRACE_WITH_ARGS depending on DYNAMIC_FTRACE_WITH_REGS, and the
mcount-based implementation is unaffected.

Signed-off-by: Li Huafei <lihuafei1 at huawei.com>
---
 arch/arm64/Kconfig               |  2 ++
 arch/arm64/include/asm/ftrace.h  | 17 +++++++++++++++++
 arch/arm64/kernel/entry-ftrace.S |  5 +++++
 3 files changed, 24 insertions(+)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 18a18a0e855d..a1b4c5800b38 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -177,6 +177,8 @@ config ARM64
 	select HAVE_DEBUG_KMEMLEAK
 	select HAVE_DMA_CONTIGUOUS
 	select HAVE_DYNAMIC_FTRACE
+	select HAVE_DYNAMIC_FTRACE_WITH_ARGS \
+		if HAVE_DYNAMIC_FTRACE_WITH_REGS
 	select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY \
 		if DYNAMIC_FTRACE_WITH_REGS
 	select HAVE_EFFICIENT_UNALIGNED_ACCESS
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 1494cfa8639b..2b4cd442c843 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -78,6 +78,23 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
 	return addr;
 }
 
+#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
+struct ftrace_regs {
+	struct pt_regs		regs;
+};
+
+static __always_inline struct pt_regs *
+arch_ftrace_get_regs(struct ftrace_regs *fregs)
+{
+	struct pt_regs *regs = &fregs->regs;
+
+	/* When FL_SAVE_REGS is not set, X10 is set to zero */
+	if (!pt_regs_read_reg(regs, 10))
+		return NULL;
+	return regs;
+}
+#endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS */
+
 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
 struct dyn_ftrace;
 int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index e535480a4069..805287fedb01 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -46,6 +46,8 @@
 
 	/* Optionally save the callee-saved registers, always save the FP */
 	.if \allregs == 1
+	/* Set X10 to 1 (just non-zero) for ops with FL_SAVE_REGS flag set */
+	mov	x10, #1
 	stp	x10, x11, [sp, #S_X10]
 	stp	x12, x13, [sp, #S_X12]
 	stp	x14, x15, [sp, #S_X14]
@@ -57,6 +59,9 @@
 	stp	x26, x27, [sp, #S_X26]
 	stp	x28, x29, [sp, #S_X28]
 	.else
+	/* Set X10 to 0 for ops without FL_SAVE_REGS flag */
+	mov	x10, #0
+	str	x10, [sp, #S_X10]
 	str	x29, [sp, #S_FP]
 	.endif
 
-- 
2.17.1




More information about the linux-arm-kernel mailing list