From: abelvesa@gmail.com (Abel Vesa)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCHv4] arm: ftrace: Adds support for CONFIG_DYNAMIC_FTRACE_WITH_REGS
Date: Tue, 28 Feb 2017 00:56:36 +0000 [thread overview]
Message-ID: <20170228005636.GA23251@nuc> (raw)
In-Reply-To: <87r32jiqc9.fsf@d080-213.cis.zmaw.de>
On Mon, Feb 27, 2017 at 04:52:06PM +0100, Nicolai Stange wrote:
> Hi Abel,
>
> On Fri, Feb 24 2017, Abel Vesa wrote:
>
> <snip>
>
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index fda6a46..877df5b 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -55,6 +55,7 @@ config ARM
> > select HAVE_DMA_API_DEBUG
> > select HAVE_DMA_CONTIGUOUS if MMU
> > select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU
> > + select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE && OLD_MCOUNT
>
>
> AFAICS, your code depends on the __gnu_mcount_nc calling conventions,
> i.e. on gcc pushing the original lr on the stack. In particular, there's
> no implementation of a ftrace_regs_caller_old or so.
>
> So shouldn't this read as !OLD_MCOUNT instead?
The implementation of __ftrace_modify_code which sets the kernel text to rw
needs OLD_MCOUNT (that is, the arch specific one, not the generic one).
>
> Also, at least the ldmia ..., {..., sp, ...} insn needs a !THUMB2_KERNEL.
>
>
> > select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU
> > select HAVE_EXIT_THREAD
> > select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
>
> <snip>
>
> > diff --git a/arch/arm/kernel/entry-ftrace.S b/arch/arm/kernel/entry-ftrace.S
> > index c73c403..3916dd6 100644
> > --- a/arch/arm/kernel/entry-ftrace.S
> > +++ b/arch/arm/kernel/entry-ftrace.S
> > @@ -92,12 +92,78 @@
> > 2: mcount_exit
> > .endm
> >
> > +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
> > +
> > +.macro __ftrace_regs_caller
> > +
> > + sub sp, sp, #8 @ space for CPSR and OLD_R0 (not used)
> > +
> > + add ip, sp, #12 @ move in IP the value of SP as it was
> > + @ before the push {lr} of the mcount mechanism
> > + stmdb sp!, {ip,lr,pc}
> > + stmdb sp!, {r0-r11,lr}
> > +
> > + @ stack content at this point:
> > + @ 0 4 48 52 56 60 64 68 72
> > + @ R0 | R1 | ... | LR | SP + 4 | LR | PC | PSR | OLD_R0 | previous LR |
>
> Being a constant, the saved pc is not very useful, I think.
So you're saying skip it ? But you still need to leave space for it. So why not
just save it even if the value is not useful?
>
> Wouldn't it be better (and more consistent with other archs) to have
>
> pt_regs->ARM_lr = original lr
> pt_refs->ARM_pc = current lr
>
> instead?
>
> A (hypothetical) klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
> would do the more intuitive
>
> regs->ARM_pc = ip;
>
> rather than a
>
> regs->ARM_lr = ip
>
> then.
You are right. There is a subsequent patch I'm currently working on that will
enable livepatch and will bring an implementation for klp_arch_set_pc as you
described it. I still don't get what is wrong with the code though?
>
> In addition, the original lr register would be made available to ftrace
> handlers this way.
>
>
> > + mov r3, sp @ struct pt_regs*
> > + ldr r2, =function_trace_op
> > + ldr r2, [r2] @ pointer to the current
> > + @ function tracing op
> > + ldr r1, [sp, #PT_REGS_SIZE] @ lr of instrumented func
> > + mcount_adjust_addr r0, lr @ instrumented function
> > +
> > + .globl ftrace_regs_call
> > +ftrace_regs_call:
> > + bl ftrace_stub
> > +
> > +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> > + .globl ftrace_graph_regs_call
> > +ftrace_graph_regs_call:
> > + mov r0, r0
> > +#endif
> > + @ pop saved regs
> > + @ first, get the previous LR value from stack
> > + ldr lr, [sp, #PT_REGS_SIZE]
> > + @ now pop the rest of the saved registers INCLUDING stack pointer
> > + ldmia sp, {r0-r11, ip, sp, pc}
> > +.endm
> > +
>
>
> > +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> > +.macro __ftrace_graph_regs_caller
> > +
> > + sub r0, fp, #4 @ lr of instrumented routine (parent)
> > +
> > + @ called from __ftrace_regs_caller
> > + ldr r1, [sp, #S_LR] @ instrumented routine (func)
> > + mcount_adjust_addr r1, r1
> > +
> > + sub r2, r0, #4 @ frame pointer
>
> Given that r2 is prepare_ftrace_return()'s frame_pointer argument, is
>
> r2 = fp - 4 - 4 = fp - 8
>
> really correct / what is wanted here?
>
You are right.
- sub r2, r0, #4 @ frame pointer
+ mov r2, fp @ frame pointer
> > + bl prepare_ftrace_return
> > +
> > + @ pop registers saved in ftrace_regs_caller
> > + @ first, get the previous LR value from stack
> > + ldr lr, [sp, #PT_REGS_SIZE]
> > + @ now pop the rest of the saved registers INCLUDING stack pointer
> > + ldmia sp, {r0-r11, ip, sp, pc}
> > +.endm
> > +#endif
> > +#endif
> > +
>
> <snip>
>
>
> Thanks,
>
> Nicolai
Thanks
WARNING: multiple messages have this Message-ID (diff)
From: Abel Vesa <abelvesa@gmail.com>
To: Nicolai Stange <nicstange@gmail.com>
Cc: Abel Vesa <abelvesa@linux.com>,
robin.murphy@arm.com, jjhiblot@traphandler.com,
Russell King <linux@armlinux.org.uk>,
Steven Rostedt <rostedt@goodmis.org>,
Ingo Molnar <mingo@redhat.com>,
pmladek@suse.com, mhiramat@kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCHv4] arm: ftrace: Adds support for CONFIG_DYNAMIC_FTRACE_WITH_REGS
Date: Tue, 28 Feb 2017 00:56:36 +0000 [thread overview]
Message-ID: <20170228005636.GA23251@nuc> (raw)
In-Reply-To: <87r32jiqc9.fsf@d080-213.cis.zmaw.de>
On Mon, Feb 27, 2017 at 04:52:06PM +0100, Nicolai Stange wrote:
> Hi Abel,
>
> On Fri, Feb 24 2017, Abel Vesa wrote:
>
> <snip>
>
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index fda6a46..877df5b 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -55,6 +55,7 @@ config ARM
> > select HAVE_DMA_API_DEBUG
> > select HAVE_DMA_CONTIGUOUS if MMU
> > select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) && !CPU_ENDIAN_BE32 && MMU
> > + select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE && OLD_MCOUNT
>
>
> AFAICS, your code depends on the __gnu_mcount_nc calling conventions,
> i.e. on gcc pushing the original lr on the stack. In particular, there's
> no implementation of a ftrace_regs_caller_old or so.
>
> So shouldn't this read as !OLD_MCOUNT instead?
The implementation of __ftrace_modify_code which sets the kernel text to rw
needs OLD_MCOUNT (that is, the arch specific one, not the generic one).
>
> Also, at least the ldmia ..., {..., sp, ...} insn needs a !THUMB2_KERNEL.
>
>
> > select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU
> > select HAVE_EXIT_THREAD
> > select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL)
>
> <snip>
>
> > diff --git a/arch/arm/kernel/entry-ftrace.S b/arch/arm/kernel/entry-ftrace.S
> > index c73c403..3916dd6 100644
> > --- a/arch/arm/kernel/entry-ftrace.S
> > +++ b/arch/arm/kernel/entry-ftrace.S
> > @@ -92,12 +92,78 @@
> > 2: mcount_exit
> > .endm
> >
> > +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
> > +
> > +.macro __ftrace_regs_caller
> > +
> > + sub sp, sp, #8 @ space for CPSR and OLD_R0 (not used)
> > +
> > + add ip, sp, #12 @ move in IP the value of SP as it was
> > + @ before the push {lr} of the mcount mechanism
> > + stmdb sp!, {ip,lr,pc}
> > + stmdb sp!, {r0-r11,lr}
> > +
> > + @ stack content at this point:
> > + @ 0 4 48 52 56 60 64 68 72
> > + @ R0 | R1 | ... | LR | SP + 4 | LR | PC | PSR | OLD_R0 | previous LR |
>
> Being a constant, the saved pc is not very useful, I think.
So you're saying skip it ? But you still need to leave space for it. So why not
just save it even if the value is not useful?
>
> Wouldn't it be better (and more consistent with other archs) to have
>
> pt_regs->ARM_lr = original lr
> pt_refs->ARM_pc = current lr
>
> instead?
>
> A (hypothetical) klp_arch_set_pc(struct pt_regs *regs, unsigned long ip)
> would do the more intuitive
>
> regs->ARM_pc = ip;
>
> rather than a
>
> regs->ARM_lr = ip
>
> then.
You are right. There is a subsequent patch I'm currently working on that will
enable livepatch and will bring an implementation for klp_arch_set_pc as you
described it. I still don't get what is wrong with the code though?
>
> In addition, the original lr register would be made available to ftrace
> handlers this way.
>
>
> > + mov r3, sp @ struct pt_regs*
> > + ldr r2, =function_trace_op
> > + ldr r2, [r2] @ pointer to the current
> > + @ function tracing op
> > + ldr r1, [sp, #PT_REGS_SIZE] @ lr of instrumented func
> > + mcount_adjust_addr r0, lr @ instrumented function
> > +
> > + .globl ftrace_regs_call
> > +ftrace_regs_call:
> > + bl ftrace_stub
> > +
> > +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> > + .globl ftrace_graph_regs_call
> > +ftrace_graph_regs_call:
> > + mov r0, r0
> > +#endif
> > + @ pop saved regs
> > + @ first, get the previous LR value from stack
> > + ldr lr, [sp, #PT_REGS_SIZE]
> > + @ now pop the rest of the saved registers INCLUDING stack pointer
> > + ldmia sp, {r0-r11, ip, sp, pc}
> > +.endm
> > +
>
>
> > +#ifdef CONFIG_FUNCTION_GRAPH_TRACER
> > +.macro __ftrace_graph_regs_caller
> > +
> > + sub r0, fp, #4 @ lr of instrumented routine (parent)
> > +
> > + @ called from __ftrace_regs_caller
> > + ldr r1, [sp, #S_LR] @ instrumented routine (func)
> > + mcount_adjust_addr r1, r1
> > +
> > + sub r2, r0, #4 @ frame pointer
>
> Given that r2 is prepare_ftrace_return()'s frame_pointer argument, is
>
> r2 = fp - 4 - 4 = fp - 8
>
> really correct / what is wanted here?
>
You are right.
- sub r2, r0, #4 @ frame pointer
+ mov r2, fp @ frame pointer
> > + bl prepare_ftrace_return
> > +
> > + @ pop registers saved in ftrace_regs_caller
> > + @ first, get the previous LR value from stack
> > + ldr lr, [sp, #PT_REGS_SIZE]
> > + @ now pop the rest of the saved registers INCLUDING stack pointer
> > + ldmia sp, {r0-r11, ip, sp, pc}
> > +.endm
> > +#endif
> > +#endif
> > +
>
> <snip>
>
>
> Thanks,
>
> Nicolai
Thanks
next prev parent reply other threads:[~2017-02-28 0:56 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-02-24 22:58 [PATCHv4] arm: ftrace: Adds support for CONFIG_DYNAMIC_FTRACE_WITH_REGS Abel Vesa
2017-02-24 22:58 ` Abel Vesa
2017-02-27 15:52 ` Nicolai Stange
2017-02-27 15:52 ` Nicolai Stange
2017-02-28 0:56 ` Abel Vesa [this message]
2017-02-28 0:56 ` Abel Vesa
2017-02-28 10:58 ` Nicolai Stange
2017-02-28 10:58 ` Nicolai Stange
2017-02-28 11:22 ` Abel Vesa
2017-02-28 11:22 ` Abel Vesa
2017-02-28 11:46 ` Russell King - ARM Linux
2017-02-28 11:46 ` Russell King - ARM Linux
2017-02-28 11:54 ` Abel Vesa
2017-02-28 11:54 ` Abel Vesa
2017-03-02 21:01 ` Abel Vesa
2017-03-02 21:01 ` Abel Vesa
2017-03-02 23:03 ` Russell King - ARM Linux
2017-03-02 23:03 ` Russell King - ARM Linux
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20170228005636.GA23251@nuc \
--to=abelvesa@gmail.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.