[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