LoongArch/ftrace: Add HAVE_DYNAMIC_FTRACE_WITH_ARGS support
authorQing Zhang <zhangqing@loongson.cn>
Sat, 10 Dec 2022 14:40:16 +0000 (22:40 +0800)
committerHuacai Chen <chenhuacai@loongson.cn>
Wed, 14 Dec 2022 00:41:53 +0000 (08:41 +0800)
Allow for arguments to be passed in to ftrace_regs by default. If this
is set, then arguments and stack can be found from the pt_regs.

1. HAVE_DYNAMIC_FTRACE_WITH_ARGS don't need special hook for graph
tracer entry point, but instead we can use graph_ops::func function to
install the return_hooker.

2. Livepatch requires this option in the future.

Signed-off-by: Qing Zhang <zhangqing@loongson.cn>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
arch/loongarch/Kconfig
arch/loongarch/include/asm/ftrace.h
arch/loongarch/kernel/ftrace_dyn.c

index f2d1b2a..a36bb0f 100644 (file)
@@ -89,6 +89,7 @@ config LOONGARCH
        select HAVE_DEBUG_STACKOVERFLOW
        select HAVE_DMA_CONTIGUOUS
        select HAVE_DYNAMIC_FTRACE
+       select HAVE_DYNAMIC_FTRACE_WITH_ARGS
        select HAVE_DYNAMIC_FTRACE_WITH_REGS
        select HAVE_EBPF_JIT
        select HAVE_EXIT_THREAD
index dd4a0c8..ee7fefa 100644 (file)
@@ -37,6 +37,23 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent);
 
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
+#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
+struct ftrace_ops;
+
+struct ftrace_regs {
+       struct pt_regs regs;
+};
+
+static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs)
+{
+       return &fregs->regs;
+}
+
+#define ftrace_graph_func ftrace_graph_func
+void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
+                      struct ftrace_ops *op, struct ftrace_regs *fregs);
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* CONFIG_FUNCTION_TRACER */
index d6f3091..439ba82 100644 (file)
@@ -139,6 +139,16 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent)
                *parent = return_hooker;
 }
 
+#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
+void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
+                      struct ftrace_ops *op, struct ftrace_regs *fregs)
+{
+       struct pt_regs *regs = &fregs->regs;
+       unsigned long *parent = (unsigned long *)&regs->regs[1];
+
+       prepare_ftrace_return(ip, (unsigned long *)parent);
+}
+#else
 static int ftrace_modify_graph_caller(bool enable)
 {
        u32 branch, nop;
@@ -166,4 +176,5 @@ int ftrace_disable_ftrace_graph_caller(void)
 {
        return ftrace_modify_graph_caller(false);
 }
+#endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS */
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */