Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1602685 > unrolled thread
| Started by | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| First post | 2017-03-16 18:30 +0100 |
| Last post | 2017-03-16 21:20 +0100 |
| Articles | 12 — 2 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCH 4/5 v2] ftrace/x86_32: Clean up ftrace_regs_caller Steven Rostedt <rostedt@goodmis.org> - 2017-03-16 18:30 +0100
Re: [PATCH 4/5 v2] ftrace/x86_32: Clean up ftrace_regs_caller Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-16 18:50 +0100
Re: [PATCH 4/5 v2] ftrace/x86_32: Clean up ftrace_regs_caller Steven Rostedt <rostedt@goodmis.org> - 2017-03-16 19:00 +0100
[PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller Steven Rostedt <rostedt@goodmis.org> - 2017-03-16 19:10 +0100
Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-16 19:30 +0100
Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-16 20:30 +0100
Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller Steven Rostedt <rostedt@goodmis.org> - 2017-03-16 20:50 +0100
Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller Steven Rostedt <rostedt@goodmis.org> - 2017-03-16 20:30 +0100
Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller Linus Torvalds <torvalds@linux-foundation.org> - 2017-03-16 20:40 +0100
Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller Steven Rostedt <rostedt@goodmis.org> - 2017-03-16 21:00 +0100
Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller Steven Rostedt <rostedt@goodmis.org> - 2017-03-16 20:30 +0100
[PATCH 4/5 v3.1] ftrace/x86_32: Clean up ftrace_regs_caller Steven Rostedt <rostedt@goodmis.org> - 2017-03-16 21:20 +0100
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-03-16 18:30 +0100 |
| Subject | [PATCH 4/5 v2] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlHnQ-1ze-15@gated-at.bofh.it> |
From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> When ftrace_regs_caller was created, it was designed to preserve flags as much as possible as it needed to act just like a breakpoint triggered on the same location. But the design is over complicated as it treated all operations as modifying flags. But push, mov and lea do not modify flags. This means the code can become more simplified by allowing flags to be stored further down. Making ftrace_regs_caller simpler will also be useful in implementing fentry logic. Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> --- arch/x86/kernel/ftrace_32.S | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S index 6f855dfb786d..2002aadd25f8 100644 --- a/arch/x86/kernel/ftrace_32.S +++ b/arch/x86/kernel/ftrace_32.S @@ -55,23 +55,30 @@ WEAK(ftrace_stub) END(ftrace_caller) ENTRY(ftrace_regs_caller) - pushf /* push flags before compare (in cs location) */ - /* * i386 does not save SS and ESP when coming from kernel. * Instead, to get sp, ®s->sp is used (see ptrace.h). * Unfortunately, that means eflags must be at the same location * as the current return ip is. We move the return ip into the - * ip location, and move flags into the return ip location. - */ - pushl 4(%esp) /* save return ip into ip slot */ + * regs->ip location, and move flags into the return ip location. + */ + pushl $__KERNEL_CS + pushl 4(%esp) /* Save the return ip */ + + /* temporarily save flags in the orig_ax location */ + pushf - pushl $0 /* Load 0 into orig_ax */ pushl %gs pushl %fs pushl %es pushl %ds pushl %eax + + /* move flags into the location of where the return ip was */ + movl 5*4(%esp), %eax + movl $0, 5*4(%esp) /* Load 0 into orig_ax */ + movl %eax, 8*4(%esp) /* Load flags in return ip */ + pushl %ebp pushl %edi pushl %esi @@ -79,11 +86,6 @@ ENTRY(ftrace_regs_caller) pushl %ecx pushl %ebx - movl 13*4(%esp), %eax /* Get the saved flags */ - movl %eax, 14*4(%esp) /* Move saved flags into regs->flags location */ - /* clobbering return ip */ - movl $__KERNEL_CS, 13*4(%esp) - movl 12*4(%esp), %eax /* Load ip (1st parameter) */ subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ @@ -94,10 +96,14 @@ GLOBAL(ftrace_regs_call) call ftrace_stub addl $4, %esp /* Skip pt_regs */ - movl 14*4(%esp), %eax /* Move flags back into cs */ - movl %eax, 13*4(%esp) /* Needed to keep addl from modifying flags */ - movl 12*4(%esp), %eax /* Get return ip from regs->ip */ - movl %eax, 14*4(%esp) /* Put return ip back for ret */ + + /* Since we don't care about cs, move flags there to simplify return */ + movl 14*4(%esp), %eax + movl %eax, 13*4(%esp) + + /* Move return ip back to its original location */ + movl 12*4(%esp), %eax + movl %eax, 14*4(%esp) popl %ebx popl %ecx @@ -110,12 +116,11 @@ GLOBAL(ftrace_regs_call) popl %es popl %fs popl %gs - addl $8, %esp /* Skip orig_ax and ip */ - popf /* Pop flags at end (no addl to corrupt flags) */ - jmp .Lftrace_ret + addl $8, %esp /* Skip orig_ax and old ip */ - popf - jmp ftrace_stub + popf /* flags is in the cs location */ + + jmp .Lftrace_ret #else /* ! CONFIG_DYNAMIC_FTRACE */ ENTRY(mcount) -- 2.10.2
[toc] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2017-03-16 18:50 +0100 |
| Message-ID | <tlHHc-1ID-17@gated-at.bofh.it> |
| In reply to | #1602685 |
On Thu, Mar 16, 2017 at 10:20 AM, Steven Rostedt <rostedt@goodmis.org> wrote:
>
> When ftrace_regs_caller was created, it was designed to preserve flags as
> much as possible as it needed to act just like a breakpoint triggered on the
> same location. But the design is over complicated as it treated all
> operations as modifying flags. But push, mov and lea do not modify flags.
> This means the code can become more simplified by allowing flags to be
> stored further down.
It still looks overly complicated to me.
The snippet below is the patch without the "-" lines, so it's the end result:
> ENTRY(ftrace_regs_caller)
> /*
> * i386 does not save SS and ESP when coming from kernel.
> * Instead, to get sp, ®s->sp is used (see ptrace.h).
> * Unfortunately, that means eflags must be at the same location
> * as the current return ip is. We move the return ip into the
> + * regs->ip location, and move flags into the return ip location.
> + */
> + pushl $__KERNEL_CS
> + pushl 4(%esp) /* Save the return ip */
> +
> + /* temporarily save flags in the orig_ax location */
> + pushf
>
> pushl %gs
> pushl %fs
> pushl %es
> pushl %ds
> pushl %eax
> +
> + /* move flags into the location of where the return ip was */
> + movl 5*4(%esp), %eax
> + movl $0, 5*4(%esp) /* Load 0 into orig_ax */
> + movl %eax, 8*4(%esp) /* Load flags in return ip */
Why do you do that silly "temporarily save flags" thing?
Why not just push $0 there?
Afaik, the sequence could/should be:
pushl $__KERNEL_CS
pushl 4(%esp) /* Save the return ip */
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl %eax
/* Fix up eflags now that we have a scratch register */
pushfl
popl %eax
movl %eax,8(%rsp)
Or something. There's no point in the unnecessary "shuffle values back
and forth with odd stack offsets".
Linus
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-03-16 19:00 +0100 |
| Message-ID | <tlHQR-1Mk-19@gated-at.bofh.it> |
| In reply to | #1602708 |
[ Resending again with a "reply-all" instead of just "reply" ] On Thu, 16 Mar 2017 10:40:24 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote: > On Thu, Mar 16, 2017 at 10:20 AM, Steven Rostedt <rostedt@goodmis.org> wrote: > > > > When ftrace_regs_caller was created, it was designed to preserve flags as > > much as possible as it needed to act just like a breakpoint triggered on the > > same location. But the design is over complicated as it treated all > > operations as modifying flags. But push, mov and lea do not modify flags. > > This means the code can become more simplified by allowing flags to be > > stored further down. > > It still looks overly complicated to me. > > The snippet below is the patch without the "-" lines, so it's the end result: > > > ENTRY(ftrace_regs_caller) > > /* > > * i386 does not save SS and ESP when coming from kernel. > > * Instead, to get sp, ®s->sp is used (see ptrace.h). > > * Unfortunately, that means eflags must be at the same location > > * as the current return ip is. We move the return ip into the > > + * regs->ip location, and move flags into the return ip location. > > + */ > > + pushl $__KERNEL_CS > > + pushl 4(%esp) /* Save the return ip */ > > + > > + /* temporarily save flags in the orig_ax location */ > > + pushf > > > > pushl %gs > > pushl %fs > > pushl %es > > pushl %ds > > pushl %eax > > + > > + /* move flags into the location of where the return ip was */ > > + movl 5*4(%esp), %eax > > + movl $0, 5*4(%esp) /* Load 0 into orig_ax */ > > + movl %eax, 8*4(%esp) /* Load flags in return ip */ > > Why do you do that silly "temporarily save flags" thing? > > Why not just push $0 there? > > Afaik, the sequence could/should be: > > pushl $__KERNEL_CS > pushl 4(%esp) /* Save the return ip */ > pushl $0 > pushl %gs > pushl %fs > pushl %es > pushl %ds > pushl %eax > > /* Fix up eflags now that we have a scratch register */ > pushfl > popl %eax > movl %eax,8(%rsp) > > Or something. There's no point in the unnecessary "shuffle values back > and forth with odd stack offsets". Sure, I can do this. This is the issue of trying to do too much at first and then eliminating what you don't need. :-p I think previous versions (where I was trying to horribly add a stack frame here) had some more logic. -- Steve
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-03-16 19:10 +0100 |
| Subject | [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlI0y-25v-33@gated-at.bofh.it> |
| In reply to | #1602708 |
[ I'll wait to post the full v3 series in case there is more comments ] From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> When ftrace_regs_caller was created, it was designed to preserve flags as much as possible as it needed to act just like a breakpoint triggered on the same location. But the design is over complicated as it treated all operations as modifying flags. But push, mov and lea do not modify flags. This means the code can become more simplified by allowing flags to be stored further down. Making ftrace_regs_caller simpler will also be useful in implementing fentry logic. Link: http://lkml.kernel.org/r/20170316135328.36123c3e@gandalf.local.home [ simpler logic to save flags ] Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> --- arch/x86/kernel/ftrace_32.S | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S index 6f855df..691897e 100644 --- a/arch/x86/kernel/ftrace_32.S +++ b/arch/x86/kernel/ftrace_32.S @@ -55,23 +55,27 @@ WEAK(ftrace_stub) END(ftrace_caller) ENTRY(ftrace_regs_caller) - pushf /* push flags before compare (in cs location) */ - /* * i386 does not save SS and ESP when coming from kernel. * Instead, to get sp, ®s->sp is used (see ptrace.h). * Unfortunately, that means eflags must be at the same location * as the current return ip is. We move the return ip into the - * ip location, and move flags into the return ip location. - */ - pushl 4(%esp) /* save return ip into ip slot */ - + * regs->ip location, and move flags into the return ip location. + */ + pushl $__KERNEL_CS + pushl 4(%esp) /* Save the return ip */ pushl $0 /* Load 0 into orig_ax */ pushl %gs pushl %fs pushl %es pushl %ds pushl %eax + + /* Get flags and place them into the return ip slot */ + pushf + popl %eax + movl %eax, 8*4(%esp) + pushl %ebp pushl %edi pushl %esi @@ -79,11 +83,6 @@ ENTRY(ftrace_regs_caller) pushl %ecx pushl %ebx - movl 13*4(%esp), %eax /* Get the saved flags */ - movl %eax, 14*4(%esp) /* Move saved flags into regs->flags location */ - /* clobbering return ip */ - movl $__KERNEL_CS, 13*4(%esp) - movl 12*4(%esp), %eax /* Load ip (1st parameter) */ subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ @@ -94,10 +93,14 @@ GLOBAL(ftrace_regs_call) call ftrace_stub addl $4, %esp /* Skip pt_regs */ - movl 14*4(%esp), %eax /* Move flags back into cs */ - movl %eax, 13*4(%esp) /* Needed to keep addl from modifying flags */ - movl 12*4(%esp), %eax /* Get return ip from regs->ip */ - movl %eax, 14*4(%esp) /* Put return ip back for ret */ + + /* Since we don't care about cs, move flags there to simplify return */ + movl 14*4(%esp), %eax + movl %eax, 13*4(%esp) + + /* Move return ip back to its original location */ + movl 12*4(%esp), %eax + movl %eax, 14*4(%esp) popl %ebx popl %ecx @@ -110,12 +113,11 @@ GLOBAL(ftrace_regs_call) popl %es popl %fs popl %gs - addl $8, %esp /* Skip orig_ax and ip */ - popf /* Pop flags at end (no addl to corrupt flags) */ - jmp .Lftrace_ret + addl $8, %esp /* Skip orig_ax and old ip */ - popf - jmp ftrace_stub + popf /* flags is in the cs location */ + + jmp .Lftrace_ret #else /* ! CONFIG_DYNAMIC_FTRACE */ ENTRY(mcount) -- 2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2017-03-16 19:30 +0100 |
| Subject | Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlIjV-2f6-53@gated-at.bofh.it> |
| In reply to | #1602728 |
On Thu, Mar 16, 2017 at 11:09 AM, Steven Rostedt <rostedt@goodmis.org> wrote:
> +
> + /* Since we don't care about cs, move flags there to simplify return */
> + movl 14*4(%esp), %eax
> + movl %eax, 13*4(%esp)
> +
> + /* Move return ip back to its original location */
> + movl 12*4(%esp), %eax
> + movl %eax, 14*4(%esp)
Could this perhaps be removed entirely?
The return code could instead do:
... restore all the normal registers ..
# Now restore flags that is under the return address and our
fake __KERNEL_CS
pushl 8(%esp)
popfl
# and then return, skipping __KERNEL_CS and %flasg
ret $8
which is smaller and simpler than (again) playing games with stack entries.
Linus
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2017-03-16 20:30 +0100 |
| Subject | Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlJfX-2Un-1@gated-at.bofh.it> |
| In reply to | #1602747 |
On Thu, Mar 16, 2017 at 12:19 PM, Steven Rostedt <rostedt@goodmis.org> wrote:
>
> The thing is we don't return, we jump to the location that may be
> modified to run the function graph tracer.
Hmm.
How about just making the stack frame a tiny bit bigger, and getting
rid of *all* the games.
IOW, just duplicate the return address, and make the entry code do
pushfl
pushl $__KERNEL_CS
pushl 8(%esp) /* Save the return ip *again* */
pushl $0
pushl %gs
pushl %fs
pushl %es
pushl %ds
pushl %eax
....
and not have any silly code to modify the old stack frame at all. Just
skip the values (all the segments, ORIG_EAX, duplicated return
address, __KERNEL_CS), and you can finish off with a "popf", and all
you have left i the original return ip that you didn't touch.
Hmm?
Linus
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-03-16 20:50 +0100 |
| Subject | Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlJzj-33w-5@gated-at.bofh.it> |
| In reply to | #1602794 |
On Thu, 16 Mar 2017 12:28:13 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote: > On Thu, Mar 16, 2017 at 12:19 PM, Steven Rostedt <rostedt@goodmis.org> wrote: > > > > The thing is we don't return, we jump to the location that may be > > modified to run the function graph tracer. > > Hmm. > > How about just making the stack frame a tiny bit bigger, and getting > rid of *all* the games. Unfortunately, x86_32 causes us to play these games. The ftrace_regs_caller is used by kprobes to simulate an int3 breakpoint. That means I need to have it behave exactly the same as int3. On x86_32, the int3 does not save ESP or SS for that matter, but instead kprobes, et al. uses the address of the regs->sp parameter to get the stack location when the interrupt triggered (coming from kernel). That means, I can't duplicate pt_regs any place else. The pt_regs passed into the caller (kprobes) has to have ®s->esp be equal to the stack address when the int3 was hit. Or in this case, when fentry was called. > > IOW, just duplicate the return address, and make the entry code do > > pushfl > pushl $__KERNEL_CS > pushl 8(%esp) /* Save the return ip *again* */ > pushl $0 > pushl %gs > pushl %fs > pushl %es > pushl %ds > pushl %eax > .... > > and not have any silly code to modify the old stack frame at all. Just > skip the values (all the segments, ORIG_EAX, duplicated return > address, __KERNEL_CS), and you can finish off with a "popf", and all > you have left i the original return ip that you didn't touch. Most likely those will not be touched, but as ftrace_regs_caller (which is much heavier weight than ftrace_caller) must act the same as an int3. If a kprobes callback modifies any of those, the ftrace_regs_caller must act the same as if it was done by int3. Now, most likely a kprobe's callback will never touch those. But we never know. -- Steve
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-03-16 20:30 +0100 |
| Subject | Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlJfY-2Un-17@gated-at.bofh.it> |
| In reply to | #1602747 |
On Thu, 16 Mar 2017 15:19:32 -0400 Steven Rostedt <rostedt@goodmis.org> wrote: > > > The thing is we don't return, we jump to the location that may be > modified to run the function graph tracer. That said, maybe the below is better? /* restore flags */ pushl 14*4(%esp) popf /* Move return ip back to its original location */ movl 12*4(%esp), %eax movl %eax, 14*4(%esp) popl %ebx popl %ecx popl %edx popl %esi popl %edi popl %ebp popl %eax popl %ds popl %es popl %fs popl %gs /* use lea to not affect flags */ lea (3*4)%esp, %esp /* Skip orig_ax, ip and flags */ jmp .Lftrace_ret -- Steve
[toc] | [prev] | [next] | [standalone]
| From | Linus Torvalds <torvalds@linux-foundation.org> |
|---|---|
| Date | 2017-03-16 20:40 +0100 |
| Subject | Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlJpE-2Zo-9@gated-at.bofh.it> |
| In reply to | #1602796 |
On Thu, Mar 16, 2017 at 12:24 PM, Steven Rostedt <rostedt@goodmis.org> wrote:
> popl %ds
> popl %es
> popl %fs
> popl %gs
Do you even need these? Can they be changed by ftrace?
And see the previous email about not touching the original location at
all, adn just duplicating that entry, avoiding all the need for
shuffling. I *really* hope that ftrace doesn't depend on changing the
return %eip on the stack. That would be truly nasty.
Linus
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-03-16 21:00 +0100 |
| Subject | Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlJJ0-379-13@gated-at.bofh.it> |
| In reply to | #1602805 |
On Thu, 16 Mar 2017 12:30:25 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote: > On Thu, Mar 16, 2017 at 12:24 PM, Steven Rostedt <rostedt@goodmis.org> wrote: > > popl %ds > > popl %es > > popl %fs > > popl %gs > > Do you even need these? Can they be changed by ftrace? ftrace no, kprobes, maybe. > > And see the previous email about not touching the original location at > all, adn just duplicating that entry, avoiding all the need for > shuffling. I *really* hope that ftrace doesn't depend on changing the > return %eip on the stack. That would be truly nasty. How do you think the live patching works? -- Steve
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-03-16 20:30 +0100 |
| Subject | Re: [PATCH 4/5 v3] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlJfX-2Un-3@gated-at.bofh.it> |
| In reply to | #1602747 |
On Thu, 16 Mar 2017 11:19:44 -0700 Linus Torvalds <torvalds@linux-foundation.org> wrote: > On Thu, Mar 16, 2017 at 11:09 AM, Steven Rostedt <rostedt@goodmis.org> wrote: > > + > > + /* Since we don't care about cs, move flags there to simplify return */ > > + movl 14*4(%esp), %eax > > + movl %eax, 13*4(%esp) > > + > > + /* Move return ip back to its original location */ > > + movl 12*4(%esp), %eax > > + movl %eax, 14*4(%esp) > > Could this perhaps be removed entirely? > > The return code could instead do: > > ... restore all the normal registers .. > > # Now restore flags that is under the return address and our > fake __KERNEL_CS > pushl 8(%esp) > popfl > > # and then return, skipping __KERNEL_CS and %flasg > ret $8 > > which is smaller and simpler than (again) playing games with stack entries. > > Linus The thing is we don't return, we jump to the location that may be modified to run the function graph tracer. .Lftrace_ret: #ifdef CONFIG_FUNCTION_GRAPH_TRACER .globl ftrace_graph_call ftrace_graph_call: jmp ftrace_stub <- this can turn to a jump to function graph tracing #endif WEAK(ftrace_stub) ret END(ftrace_caller) [...] popf /* flags is in the cs location */ jmp .Lftrace_ret -- Steve
[toc] | [prev] | [next] | [standalone]
| From | Steven Rostedt <rostedt@goodmis.org> |
|---|---|
| Date | 2017-03-16 21:20 +0100 |
| Subject | [PATCH 4/5 v3.1] ftrace/x86_32: Clean up ftrace_regs_caller |
| Message-ID | <tlK2l-3uf-1@gated-at.bofh.it> |
| In reply to | #1602747 |
[ Unless we come up with something else, here's the latest ] From: "Steven Rostedt (VMware)" <rostedt@goodmis.org> When ftrace_regs_caller was created, it was designed to preserve flags as much as possible as it needed to act just like a breakpoint triggered on the same location. But the design is over complicated as it treated all operations as modifying flags. But push, mov and lea do not modify flags. This means the code can become more simplified by allowing flags to be stored further down. Making ftrace_regs_caller simpler will also be useful in implementing fentry logic. Link: http://lkml.kernel.org/r/20170316135328.36123c3e@gandalf.local.home [ simpler logic to save flags ] Suggested-by: Linus Torvalds <torvalds@linux-foundation.org> Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org> --- arch/x86/kernel/ftrace_32.S | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/ftrace_32.S b/arch/x86/kernel/ftrace_32.S index 6f855df..068a582 100644 --- a/arch/x86/kernel/ftrace_32.S +++ b/arch/x86/kernel/ftrace_32.S @@ -55,23 +55,27 @@ WEAK(ftrace_stub) END(ftrace_caller) ENTRY(ftrace_regs_caller) - pushf /* push flags before compare (in cs location) */ - /* * i386 does not save SS and ESP when coming from kernel. * Instead, to get sp, ®s->sp is used (see ptrace.h). * Unfortunately, that means eflags must be at the same location * as the current return ip is. We move the return ip into the - * ip location, and move flags into the return ip location. + * regs->ip location, and move flags into the return ip location. */ - pushl 4(%esp) /* save return ip into ip slot */ - + pushl $__KERNEL_CS + pushl 4(%esp) /* Save the return ip */ pushl $0 /* Load 0 into orig_ax */ pushl %gs pushl %fs pushl %es pushl %ds pushl %eax + + /* Get flags and place them into the return ip slot */ + pushf + popl %eax + movl %eax, 8*4(%esp) + pushl %ebp pushl %edi pushl %esi @@ -79,11 +83,6 @@ ENTRY(ftrace_regs_caller) pushl %ecx pushl %ebx - movl 13*4(%esp), %eax /* Get the saved flags */ - movl %eax, 14*4(%esp) /* Move saved flags into regs->flags location */ - /* clobbering return ip */ - movl $__KERNEL_CS, 13*4(%esp) - movl 12*4(%esp), %eax /* Load ip (1st parameter) */ subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ @@ -94,10 +93,14 @@ GLOBAL(ftrace_regs_call) call ftrace_stub addl $4, %esp /* Skip pt_regs */ - movl 14*4(%esp), %eax /* Move flags back into cs */ - movl %eax, 13*4(%esp) /* Needed to keep addl from modifying flags */ - movl 12*4(%esp), %eax /* Get return ip from regs->ip */ - movl %eax, 14*4(%esp) /* Put return ip back for ret */ + + /* restore flags */ + push 14*4(%esp) + popf + + /* Move return ip back to its original location */ + movl 12*4(%esp), %eax + movl %eax, 14*4(%esp) popl %ebx popl %ecx @@ -110,12 +113,11 @@ GLOBAL(ftrace_regs_call) popl %es popl %fs popl %gs - addl $8, %esp /* Skip orig_ax and ip */ - popf /* Pop flags at end (no addl to corrupt flags) */ - jmp .Lftrace_ret - popf - jmp ftrace_stub + /* use lea to not affect flags */ + lea 3*4(%esp), %esp /* Skip orig_ax, ip and flags */ + + jmp .Lftrace_ret #else /* ! CONFIG_DYNAMIC_FTRACE */ ENTRY(mcount) -- 2.9.3
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web