Re: [PATCH v14 08/19] tracing: Add ftrace_partial_regs() for converting ftrace_regs to pt_regs

Steven Rostedt
2024-09-15T09:22:13Z

Can I get an Acked-by from the AARCH64 maintainers for this patch?

Thanks!

-- Steve

On Fri, 13 Sep 2024 00:09:35 +0900
"Masami Hiramatsu (Google)" <mhiramat@kernel.org> wrote:

> From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
>
> Add ftrace_partial_regs() which converts the ftrace_regs to pt_regs.
> This is for the eBPF which needs this to keep the same pt_regs interface
> to access registers.
> Thus when replacing the pt_regs with ftrace_regs in fprobes (which is
> used by kprobe_multi eBPF event), this will be used.
>
> If the architecture defines its own ftrace_regs, this copies partial
> registers to pt_regs and returns it. If not, ftrace_regs is the same as
> pt_regs and ftrace_partial_regs() will return ftrace_regs::regs.
>
> Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
> Acked-by: Florent Revest <revest@chromium.org>
> ---
> Changes in v14:
> - Add riscv change.
> Changes in v8:
> - Add the reason why this required in changelog.
> Changes from previous series: NOTHING, just forward ported.
> ---
> arch/arm64/include/asm/ftrace.h | 11 +++++++++++
> arch/riscv/include/asm/ftrace.h | 12 ++++++++++++
> include/linux/ftrace.h | 17 +++++++++++++++++
> 3 files changed, 40 insertions(+)
>
> diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
> index dffaab3dd1f1..5cd587afab6d 100644
> --- a/arch/arm64/include/asm/ftrace.h
> +++ b/arch/arm64/include/asm/ftrace.h
> @@ -132,6 +132,17 @@ ftrace_regs_get_frame_pointer(const struct ftrace_regs *fregs)
> return fregs->fp;
> }
>
> +static __always_inline struct pt_regs *
> +ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> + memcpy(regs->regs, fregs->regs, sizeof(u64) * 9);
> + regs->sp = fregs->sp;
> + regs->pc = fregs->pc;
> + regs->regs[29] = fregs->fp;
> + regs->regs[30] = fregs->lr;
> + return regs;
> +}
> +
> int ftrace_regs_query_register_offset(const char *name);
>
> int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
> diff --git a/arch/riscv/include/asm/ftrace.h b/arch/riscv/include/asm/ftrace.h
> index e9f364ce9fe8..897779dec402 100644
> --- a/arch/riscv/include/asm/ftrace.h
> +++ b/arch/riscv/include/asm/ftrace.h
> @@ -193,6 +193,18 @@ static __always_inline void ftrace_override_function_with_return(struct ftrace_r
> fregs->epc = fregs->ra;
> }
>
> +static __always_inline struct pt_regs *
> +ftrace_partial_regs(const struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> + memcpy(&regs->a0, fregs->args, sizeof(u64) * 8);
> + regs->epc = fregs->epc;
> + regs->ra = fregs->ra;
> + regs->sp = fregs->sp;
> + regs->s0 = fregs->s0;
> + regs->t1 = fregs->t1;
> + return regs;
> +}
> +
> int ftrace_regs_query_register_offset(const char *name);
>
> void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
> diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
> index a1b2ef492c7f..bd9a26bdf660 100644
> --- a/include/linux/ftrace.h
> +++ b/include/linux/ftrace.h
> @@ -176,6 +176,23 @@ static __always_inline struct pt_regs *ftrace_get_regs(struct ftrace_regs *fregs
> return arch_ftrace_get_regs(fregs);
> }
>
> +#if !defined(CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS) || \
> + defined(CONFIG_HAVE_PT_REGS_TO_FTRACE_REGS_CAST)
> +
> +static __always_inline struct pt_regs *
> +ftrace_partial_regs(struct ftrace_regs *fregs, struct pt_regs *regs)
> +{
> + /*
> + * If CONFIG_HAVE_PT_REGS_TO_FTRACE_REGS_CAST=y, ftrace_regs memory
> + * layout is the same as pt_regs. So always returns that address.
> + * Since arch_ftrace_get_regs() will check some members and may return
> + * NULL, we can not use it.
> + */
> + return &fregs->regs;
> +}
> +
> +#endif /* !CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS || CONFIG_HAVE_PT_REGS_TO_FTRACE_REGS_CAST */
> +
> /*
> * When true, the ftrace_regs_{get,set}_*() functions may be used on fregs.
> * Note: this can be true even when ftrace_get_regs() cannot provide a pt_regs.