Message ID | 20221024140846.3555435-2-mark.rutland@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | arm64/ftrace: move to DYNAMIC_FTRACE_WITH_ARGS | expand |
On Mon, 24 Oct 2022 15:08:43 +0100 Mark Rutland <mark.rutland@arm.com> wrote: > --- a/include/linux/ftrace.h > +++ b/include/linux/ftrace.h > @@ -429,6 +429,7 @@ static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsi > } > #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ > > +#ifdef CONFIG_FUNCTION_TRACER Instead of adding the above preprocessor check, the below chunk should be moved into the CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS block above. -- Steve > #ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS > /* > * This must be implemented by the architecture. > @@ -443,9 +444,10 @@ static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsi > * the return from the trampoline jump to the direct caller > * instead of going back to the function it just traced. > */ > -static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, > +static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, > unsigned long addr) { } > #endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ > +#endif /* CONFIG_FUNCTION_TRACER */ > > #ifdef CONFIG_STACK_TRACER > > diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c > index fbf2543111c0..234c5414deee 100644
On Mon, Oct 24, 2022 at 10:48:45AM -0400, Steven Rostedt wrote: > On Mon, 24 Oct 2022 15:08:43 +0100 > Mark Rutland <mark.rutland@arm.com> wrote: > > > --- a/include/linux/ftrace.h > > +++ b/include/linux/ftrace.h > > @@ -429,6 +429,7 @@ static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsi > > } > > #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ > > > > +#ifdef CONFIG_FUNCTION_TRACER > > Instead of adding the above preprocessor check, the below chunk should be > moved into the CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS block above. Sure; but note that doing that naively means 'struct ftrace_regs' won't always be declared (e.g. if !CONFIG_FUNCTION_TRACER), and will result in warnings, e.g. | CC arch/x86/kernel/asm-offsets.s | In file included from ./include/linux/kvm_host.h:32, | from arch/x86/kernel/../kvm/vmx/vmx.h:5, | from arch/x86/kernel/asm-offsets.c:22: | ./include/linux/ftrace.h:444:57: error: ‘struct ftrace_regs’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror] | 444 | static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, | | ^~~~~~~~~~~ | cc1: all warnings being treated as errors | make[1]: *** [scripts/Makefile.build:118: arch/x86/kernel/asm-offsets.s] Error 1 | make: *** [Makefile:1270: prepare0] Error 2 ... so I'll either need to add some ifdeffery, for CONFIG_FUNCTION_TRACER, or I can hoist the declaration of 'struct ftrace_regs' to not depend on CONFIG_FUNCTION_TRACER. I guess the latter is preferable, e.g. | diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h | index 2b34fec40a39..f201fcbfffb0 100644 | --- a/include/linux/ftrace.h | +++ b/include/linux/ftrace.h | @@ -37,9 +37,10 @@ extern void ftrace_boot_snapshot(void); | static inline void ftrace_boot_snapshot(void) { } | #endif | | -#ifdef CONFIG_FUNCTION_TRACER | struct ftrace_ops; | struct ftrace_regs; | + | +#ifdef CONFIG_FUNCTION_TRACER | /* | * If the arch's mcount caller does not support all of ftrace's | * features, then it must call an indirect function that ... so I've done that locally for now. Thanks, Mark.
On Mon, Oct 24, 2022 at 4:08 PM Mark Rutland <mark.rutland@arm.com> wrote: > --- a/kernel/trace/ftrace.c > +++ b/kernel/trace/ftrace.c > @@ -2487,14 +2487,13 @@ ftrace_add_rec_direct(unsigned long ip, unsigned long addr, > static void call_direct_funcs(unsigned long ip, unsigned long pip, > struct ftrace_ops *ops, struct ftrace_regs *fregs) > { > - struct pt_regs *regs = ftrace_get_regs(fregs); Was this ftrace_get_regs() the only reason why we have config DYNAMIC_FTRACE_WITH_DIRECT_CALLS depends on DYNAMIC_FTRACE_WITH_REGS ? If we no longer use it, maybe this should be: depends on DYNAMIC_FTRACE_WITH_REGS || DYNAMIC_FTRACE_WITH_ARGS ?
On Mon, Oct 24, 2022 at 06:04:49PM +0100, Mark Rutland wrote: > On Mon, Oct 24, 2022 at 10:48:45AM -0400, Steven Rostedt wrote: > > On Mon, 24 Oct 2022 15:08:43 +0100 > > Mark Rutland <mark.rutland@arm.com> wrote: > > > > > --- a/include/linux/ftrace.h > > > +++ b/include/linux/ftrace.h > > > @@ -429,6 +429,7 @@ static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsi > > > } > > > #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ > > > > > > +#ifdef CONFIG_FUNCTION_TRACER > > > > Instead of adding the above preprocessor check, the below chunk should be > > moved into the CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS block above. > > Sure; but note that doing that naively means 'struct ftrace_regs' won't always > be declared (e.g. if !CONFIG_FUNCTION_TRACER), and will result in warnings, e.g. > > | CC arch/x86/kernel/asm-offsets.s > | In file included from ./include/linux/kvm_host.h:32, > | from arch/x86/kernel/../kvm/vmx/vmx.h:5, > | from arch/x86/kernel/asm-offsets.c:22: > | ./include/linux/ftrace.h:444:57: error: ‘struct ftrace_regs’ declared inside parameter list will not be visible outside of this definition or declaration [-Werror] > | 444 | static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, > | | ^~~~~~~~~~~ > | cc1: all warnings being treated as errors > | make[1]: *** [scripts/Makefile.build:118: arch/x86/kernel/asm-offsets.s] Error 1 > | make: *** [Makefile:1270: prepare0] Error 2 > > ... so I'll either need to add some ifdeffery, for CONFIG_FUNCTION_TRACER, or I > can hoist the declaration of 'struct ftrace_regs' to not depend on > CONFIG_FUNCTION_TRACER. > > I guess the latter is preferable, e.g. > > | diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h > | index 2b34fec40a39..f201fcbfffb0 100644 > | --- a/include/linux/ftrace.h > | +++ b/include/linux/ftrace.h > | @@ -37,9 +37,10 @@ extern void ftrace_boot_snapshot(void); > | static inline void ftrace_boot_snapshot(void) { } > | #endif > | > | -#ifdef CONFIG_FUNCTION_TRACER > | struct ftrace_ops; > | struct ftrace_regs; > | + > | +#ifdef CONFIG_FUNCTION_TRACER > | /* > | * If the arch's mcount caller does not support all of ftrace's > | * features, then it must call an indirect function that > > ... so I've done that locally for now. The kbuild robot complained that this led to x86 getting multiple definitions of arch_ftrace_set_direct_caller(), so I've also added the below: | diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h | index 788e7c1f6463c..6f9b9fee04132 100644 | --- a/arch/x86/include/asm/ftrace.h | +++ b/arch/x86/include/asm/ftrace.h | @@ -59,6 +59,7 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, | #define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR | #endif | | +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS | /* | * When a ftrace registered caller is tracing a function that is | * also set by a register_ftrace_direct() call, it needs to be | @@ -71,6 +72,7 @@ static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsi | /* Emulate a call */ | fregs->regs.orig_ax = addr; | } | +#endif | | #ifdef CONFIG_DYNAMIC_FTRACE ... AFAICT s390 doesn't need similar treatment. Thanks, Mark.
diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h index 6f80ec9c04be..53c4d1257549 100644 --- a/arch/s390/include/asm/ftrace.h +++ b/arch/s390/include/asm/ftrace.h @@ -67,8 +67,9 @@ static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *f * place the direct caller in the ORIG_GPR2 part of pt_regs. This * tells the ftrace_caller that there's a direct caller. */ -static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) +static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr) { + struct pt_regs *regs = &fregs->regs; regs->orig_gpr2 = addr; } diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h index 908d99b127d3..788e7c1f6463 100644 --- a/arch/x86/include/asm/ftrace.h +++ b/arch/x86/include/asm/ftrace.h @@ -34,19 +34,6 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) return addr; } -/* - * When a ftrace registered caller is tracing a function that is - * also set by a register_ftrace_direct() call, it needs to be - * differentiated in the ftrace_caller trampoline. To do this, we - * place the direct caller in the ORIG_AX part of pt_regs. This - * tells the ftrace_caller that there's a direct caller. - */ -static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr) -{ - /* Emulate a call */ - regs->orig_ax = addr; -} - #ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS struct ftrace_regs { struct pt_regs regs; @@ -72,6 +59,19 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, #define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR #endif +/* + * When a ftrace registered caller is tracing a function that is + * also set by a register_ftrace_direct() call, it needs to be + * differentiated in the ftrace_caller trampoline. To do this, we + * place the direct caller in the ORIG_AX part of pt_regs. This + * tells the ftrace_caller that there's a direct caller. + */ +static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr) +{ + /* Emulate a call */ + fregs->regs.orig_ax = addr; +} + #ifdef CONFIG_DYNAMIC_FTRACE struct dyn_arch_ftrace { diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 62557d4bffc2..5ca6c6680460 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -429,6 +429,7 @@ static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsi } #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ +#ifdef CONFIG_FUNCTION_TRACER #ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS /* * This must be implemented by the architecture. @@ -443,9 +444,10 @@ static inline int modify_ftrace_direct_multi_nolock(struct ftrace_ops *ops, unsi * the return from the trampoline jump to the direct caller * instead of going back to the function it just traced. */ -static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, +static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr) { } #endif /* CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ +#endif /* CONFIG_FUNCTION_TRACER */ #ifdef CONFIG_STACK_TRACER diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index fbf2543111c0..234c5414deee 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2487,14 +2487,13 @@ ftrace_add_rec_direct(unsigned long ip, unsigned long addr, static void call_direct_funcs(unsigned long ip, unsigned long pip, struct ftrace_ops *ops, struct ftrace_regs *fregs) { - struct pt_regs *regs = ftrace_get_regs(fregs); unsigned long addr; addr = ftrace_find_rec_direct(ip); if (!addr) return; - arch_ftrace_set_direct_caller(regs, addr); + arch_ftrace_set_direct_caller(fregs, addr); } struct ftrace_ops direct_ops = {
In subsequent patches we'll arrange for architectures to have an ftrace_regs which is entirely distinct from pt_regs. In preparation for this, we need to minimize the use of pt_regs to where strictly necessary in the core ftrace code. This patch changes the prototype of arch_ftrace_set_direct_caller() to take ftrace_regs rather than pt_regs, and moves the extraction of the pt_regs into arch_ftrace_set_direct_caller(). For x86, we need to move arch_ftrace_set_direct_caller() after the definition of struct ftrace_regs. As arch_ftrace_set_direct_caller() is always called with a non-NULL pt_regs by call_direct_funcs() whose ops have FTRACE_OPS_FL_SAVE_REGS, it's not necessary to add an additional NULL check. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Florent Revest <revest@chromium.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Steven Rostedt <rostedt@goodmis.org> --- arch/s390/include/asm/ftrace.h | 3 ++- arch/x86/include/asm/ftrace.h | 26 +++++++++++++------------- include/linux/ftrace.h | 4 +++- kernel/trace/ftrace.c | 3 +-- 4 files changed, 19 insertions(+), 17 deletions(-)