[PATCH v2 5/5] powerpc64/ftrace: Implement support for ftrace_regs_caller()
Steven Rostedt
rostedt at goodmis.org
Thu Mar 22 00:59:11 AEDT 2018
On Wed, 21 Mar 2018 16:13:22 +0530
"Naveen N. Rao" <naveen.n.rao at linux.vnet.ibm.com> wrote:
> int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs)
> {
> mod->arch.toc = my_r2(sechdrs, mod);
> - mod->arch.tramp = create_ftrace_stub(sechdrs, mod);
> + mod->arch.tramp = create_ftrace_stub(sechdrs, mod,
> + (unsigned long)ftrace_caller);
> +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
> + mod->arch.tramp_regs = create_ftrace_stub(sechdrs, mod,
> + (unsigned long)ftrace_regs_caller);
So you only reference ftrace_regs_caller if you have
DYNAMIC_FTRACE_WITH_REGS defined?
> + if (!mod->arch.tramp_regs)
> + return -ENOENT;
> +#endif
>
> if (!mod->arch.tramp)
> return -ENOENT;
> diff --git a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
> index 8f2380304ef1..7b81db85f76e 100644
> --- a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
> +++ b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S
> @@ -20,8 +20,8 @@
> #ifdef CONFIG_DYNAMIC_FTRACE
> /*
> *
> - * ftrace_caller() is the function that replaces _mcount() when ftrace is
> - * active.
> + * ftrace_caller()/ftrace_regs_caller() is the function that replaces _mcount()
> + * when ftrace is active.
> *
> * We arrive here after a function A calls function B, and we are the trace
> * function for B. When we enter r1 points to A's stack frame, B has not yet
> @@ -37,7 +37,7 @@
> * Our job is to save the register state into a struct pt_regs (on the stack)
> * and then arrange for the ftrace function to be called.
> */
Perhaps you want to add:
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
here.
> -_GLOBAL(ftrace_caller)
> +_GLOBAL(ftrace_regs_caller)
> /* Save the original return address in A's stack frame */
> std r0,LRSAVE(r1)
>
> @@ -100,8 +100,8 @@ _GLOBAL(ftrace_caller)
> addi r6, r1 ,STACK_FRAME_OVERHEAD
>
> /* ftrace_call(r3, r4, r5, r6) */
> -.globl ftrace_call
> -ftrace_call:
> +.globl ftrace_regs_call
> +ftrace_regs_call:
> bl ftrace_stub
> nop
>
> @@ -162,6 +162,7 @@ ftrace_call:
> bne- livepatch_handler
> #endif
>
> +ftrace_caller_common:
> #ifdef CONFIG_FUNCTION_GRAPH_TRACER
> .globl ftrace_graph_call
> ftrace_graph_call:
> @@ -182,6 +183,66 @@ ftrace_no_trace:
> mtlr r0
> bctr
>
> +_GLOBAL(ftrace_caller)
> + /* Save the original return address in A's stack frame */
> + std r0, LRSAVE(r1)
> +
> + /* Create our stack frame + pt_regs */
> + stdu r1, -SWITCH_FRAME_SIZE(r1)
> +
> + /* Save all gprs to pt_regs */
> + SAVE_8GPRS(3, r1)
> +
> + lbz r3, PACA_FTRACE_DISABLED(r13)
> + cmpdi r3, 0
> + beq ftrace_no_trace
Of course you would need to keep the ftrace_no_trace part out of the
#if block then.
-- Steve
> +
> + /* Get the _mcount() call site out of LR */
> + mflr r7
> + std r7, _NIP(r1)
> +
> + /* Save callee's TOC in the ABI compliant location */
> + std r2, 24(r1)
> + ld r2, PACATOC(r13) /* get kernel TOC in r2 */
> +
> + addis r3, r2, function_trace_op at toc@ha
> + addi r3, r3, function_trace_op at toc@l
> + ld r5, 0(r3)
> +
> + /* Calculate ip from nip-4 into r3 for call below */
> + subi r3, r7, MCOUNT_INSN_SIZE
> +
> + /* Put the original return address in r4 as parent_ip */
> + mr r4, r0
> +
> + /* Set pt_regs to NULL */
> + li r6, 0
> +
> + /* ftrace_call(r3, r4, r5, r6) */
> +.globl ftrace_call
> +ftrace_call:
> + bl ftrace_stub
> + nop
> +
> + ld r3, _NIP(r1)
> + mtctr r3
> +
> + /* Restore gprs */
> + REST_8GPRS(3,r1)
> +
> + /* Restore callee's TOC */
> + ld r2, 24(r1)
> +
> + /* Pop our stack frame */
> + addi r1, r1, SWITCH_FRAME_SIZE
> +
> + /* Reload original LR */
> + ld r0, LRSAVE(r1)
> + mtlr r0
> +
> + /* Handle function_graph or go back */
> + b ftrace_caller_common
> +
> #ifdef CONFIG_LIVEPATCH
> /*
> * This function runs in the mcount context, between two functions. As
More information about the Linuxppc-dev
mailing list