From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 01:15:23
The following set of patches are RFC and not for inclusion
(unless everyone is fine with them as is).
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
1) get generic code ready for other archs
2) get PowerPC 64-bit working with just static function tracing
3) get PowerPC 64-bit working with dynamic function tracing
4) get PowerPC 32-bit working with just static function tracing
5) get PowerPC 32-bit working with dynamic function tracing
(with some clean ups in between)
The function graph tracer not only traces the start of a function
(uses the function tracer part for that) but also uses the kprobes
trick to replace the return address with a hook to trace the exit
of the function. These hooks are generic in that other tracers
can also use them. But the function graph tracer itself is very
powerful. Simply doing the following:
# echo function_graph > /debug/tracing/current_tracer
# cat /debug/tracing/trace
# tracer: function_graph
#
# CPU OVERHEAD/DURATION FUNCTION CALLS
# | | | | | | |
------------------------------------------
0) less-2228 => cat-2229
------------------------------------------
0) | .__do_fault() {
0) | .filemap_fault() {
0) | .find_lock_page() {
0) | .find_get_page() {
0) 3.168 us | .__rcu_read_lock();
0) 2.704 us | .__rcu_read_unlock();
0) + 14.640 us | }
0) + 20.112 us | }
0) + 26.464 us | }
0) 2.912 us | ._spin_lock();
0) 2.656 us | .page_add_file_rmap();
0) | .update_mmu_cache() {
0) | .hash_preload() {
0) 2.368 us | .get_slice_psize();
0) 2.752 us | .hash_page_do_lazy_icache();
0) 3.568 us | .native_hpte_insert();
0) + 19.680 us | }
0) + 24.960 us | }
0) 2.336 us | ._spin_unlock();
0) | .unlock_page() {
0) 2.688 us | .page_waitqueue();
0) 2.608 us | .__wake_up_bit();
0) + 12.912 us | }
0) ! 351.776 us | }
0) ! 357.392 us | }
0) 3.040 us | .up_read();
0) | .compat_sys_ioctl() {
0) 3.024 us | .fget_light();
0) | .tty_compat_ioctl() {
0) 2.704 us | .tty_paranoia_check();
0) | .tty_ldisc_ref_wait() {
0) | .tty_ldisc_try() {
0) 2.880 us | ._spin_lock_irqsave();
0) 2.928 us | ._spin_unlock_irqrestore();
0) + 13.776 us | }
0) + 19.424 us | }
[...]
As you can see, it gives a nice call trace of the functions being called
at run time, as well as a time stamp of how much time the function
took to execute.
Adding dynamic tracing to the mix, we can trace a single function:
# echo .do_fork > /debug/tracing/set_graph_function
# echo function_graph > /debug/tracing/current_tracer
# cat /debug/tracing/trace
# tracer: function_graph
#
# CPU OVERHEAD/DURATION FUNCTION CALLS
# | | | | | | |
1) | .do_fork() {
1) | .copy_process() {
1) | .prepare_to_copy() {
1) 2.944 us | .flush_fp_to_thread();
1) 2.800 us | .flush_altivec_to_thread();
1) 2.608 us | .flush_vsx_to_thread();
1) + 19.184 us | }
1) | .kmem_cache_alloc() {
1) 2.464 us | .slab_should_failslab();
1) 8.304 us | }
1) | .alloc_thread_info() {
1) | .kmem_cache_alloc() {
1) 2.512 us | .slab_should_failslab();
1) 8.224 us | }
1) + 13.344 us | }
1) 7.584 us | .arch_dup_task_struct();
1) | .copy_creds() {
1) 2.736 us | .__mutex_init();
1) | .prepare_creds() {
1) | .kmem_cache_alloc() {
1) 2.640 us | .slab_should_failslab();
1) 8.368 us | }
[...]
Note, the '.' in the '.do_fork' is a PowerPC64 thing. PowerPC32 and
other archs just need to do 'do_fork', without the dot.
The following patches are in:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace.git
branch: rfc/ppc/ftrace
Steven Rostedt (7):
tracing/function-graph-tracer: make arch generic push pop functions
powerpc64: port of the function graph tracer
powerpc64, tracing: add function graph tracer with dynamic tracing
powerpc64, ftrace: save toc only on modules for function graph
powerpc32, ftrace: save and restore mcount regs with macro
powerpc32, ftrace: port function graph tracer to ppc32, static only
powerpc32, ftrace: dynamic function graph tracer
----
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/ftrace.h | 39 ++++++++++-
arch/powerpc/kernel/Makefile | 9 +-
arch/powerpc/kernel/entry_32.S | 115 ++++++++++++++---------------
arch/powerpc/kernel/entry_64.S | 89 +++++++++++++++++++++-
arch/powerpc/kernel/ftrace.c | 135 ++++++++++++++++++++++++++++++++--
arch/powerpc/kernel/process.c | 16 ++++
arch/powerpc/kernel/vmlinux.lds.S | 1 +
arch/x86/include/asm/ftrace.h | 25 ------
arch/x86/kernel/ftrace.c | 75 +------------------
include/linux/ftrace.h | 24 ++++++
kernel/trace/trace_functions_graph.c | 75 +++++++++++++++++++
12 files changed, 428 insertions(+), 176 deletions(-)
--
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 01:13:59
From: Steven Rostedt <redacted>
The TOCS used by modules are different than the one used by
the core kernel code. The function graph tracer must save and
restore the TOC whenever it traces a module call. But this
is an added overhead to burden the majority of core kernel
code being traced.
Benjamin Herrenschmidt suggested in testing the entry of
the call to tell if it is a core kernel function or a module.
He recommended using the REGION_ID() macro to perform this test.
This patch implements Benjamin's idea, and uses a different
return_to_handler routine dependent on if the entry is a core
kernel function or not. The module version saves the TOC, where as
the core kernel version does not.
Signed-off-by: Steven Rostedt <redacted>
---
arch/powerpc/kernel/entry_64.S | 27 ++++++++++++++++++++++++++-
arch/powerpc/kernel/ftrace.c | 13 +++++++++++--
2 files changed, 37 insertions(+), 3 deletions(-)
@@ -567,6 +567,10 @@ int ftrace_disable_ftrace_graph_caller(void)}#endif /* CONFIG_DYNAMIC_FTRACE */+#ifdef CONFIG_PPC64+externvoidmod_return_to_handler(void);+#endif+/**Hookthereturnaddressandpushitinthestackofreturnaddrs*incurrentthreadinfo.
@@ -577,12 +581,17 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)unsignedlonglongcalltime;intfaulted;structftrace_graph_enttrace;-unsignedlongreturn_hooker=(unsignedlong)-&return_to_handler;+unsignedlongreturn_hooker=(unsignedlong)&return_to_handler;if(unlikely(atomic_read(¤t->tracing_graph_pause)))return;+#if CONFIG_PPC64+/* non core kernel code needs to save and restore the TOC */+if(REGION_ID(self_addr)!=KERNEL_REGION_ID)+return_hooker=(unsignedlong)&mod_return_to_handler;+#endif+return_hooker=GET_ADDR(return_hooker);/*
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 01:14:23
From: Steven Rostedt <rostedt@gollum.(none)>
This patch gets function graph tracing working with dynamic function
tracer on PowerPC32.
Signed-off-by: Steven Rostedt <rostedt@gollum.(none)>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_32.S | 8 ++++++--
2 files changed, 7 insertions(+), 3 deletions(-)
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 01:14:37
From: Steven Rostedt <rostedt@goodmis.org>
This patch ports the function graph tracer for PowerPC, but only
for static function tracing.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_32.S | 43 +++++++++++++++++++++++++++++++++++++++-
arch/powerpc/kernel/ftrace.c | 2 +-
3 files changed, 44 insertions(+), 3 deletions(-)
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 01:14:55
From: Steven Rostedt <rostedt@gollum.(none)>
Impact: clean up
Use a macro to save and restore the registers for PowerPC32,
since that code is duplicated.
This is similar to the work done by Cyrill Gorcunov for the
mcount code in x86_64.
Signed-off-by: Steven Rostedt <rostedt@gollum.(none)>
---
arch/powerpc/include/asm/ftrace.h | 39 ++++++++++++++++++++-
arch/powerpc/kernel/entry_32.S | 68 +++++--------------------------------
2 files changed, 47 insertions(+), 60 deletions(-)
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 01:15:47
From: Steven Rostedt <redacted>
This is the port of the function graph tracer to PowerPC with
dynamic tracing.
Signed-off-by: Steven Rostedt <redacted>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/kernel/entry_64.S | 8 ++++++-
arch/powerpc/kernel/ftrace.c | 47 ++++++++++++++++++++++++++++++++++-----
3 files changed, 49 insertions(+), 8 deletions(-)
@@ -55,8 +56,9 @@ static unsigned char *ftrace_call_replace(unsigned long ip, unsigned long addr)*/addr=GET_ADDR(addr);-/* Set to "bl addr" */-op=0x48000001|(ftrace_calc_offset(ip,addr)&0x03fffffc);+/* if (link) set op to 'bl' else 'b' */+op=0x48000000|(link?1:0);+op|=(ftrace_calc_offset(ip,addr)&0x03fffffc);/**Nolockingneeded,thismustbecalledviakstop_machine
@@ -344,7 +346,7 @@ int ftrace_make_nop(struct module *mod,*/if(test_24bit_addr(ip,addr)){/* within range */-old=ftrace_call_replace(ip,addr);+old=ftrace_call_replace(ip,addr,1);new=ftrace_nop_replace();returnftrace_modify_code(ip,old,new);}
@@ -484,7 +486,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)if(test_24bit_addr(ip,addr)){/* within range */old=ftrace_nop_replace();-new=ftrace_call_replace(ip,addr);+new=ftrace_call_replace(ip,addr,1);returnftrace_modify_code(ip,old,new);}
@@ -513,7 +515,7 @@ int ftrace_update_ftrace_func(ftrace_func_t func)intret;memcpy(old,&ftrace_call,MCOUNT_INSN_SIZE);-new=ftrace_call_replace(ip,(unsignedlong)func);+new=ftrace_call_replace(ip,(unsignedlong)func,1);ret=ftrace_modify_code(ip,old,new);returnret;
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 01:16:11
From: Steven Rostedt <redacted>
This is a port of the function graph tracer that was written by
Frederic Weisbecker for the x86.
This only works for PPC64 at the moment and only for static tracing.
PPC32 and dynamic function graph tracing support will come later.
The trace produces a visual calling of functions:
# tracer: function_graph
#
# CPU DURATION FUNCTION CALLS
# | | | | | | |
0) 2.224 us | }
0) ! 271.024 us | }
0) ! 320.080 us | }
0) ! 324.656 us | }
0) ! 329.136 us | }
0) | .put_prev_task_fair() {
0) | .update_curr() {
0) 2.240 us | .update_min_vruntime();
0) 6.512 us | }
0) 2.528 us | .__enqueue_entity();
0) + 15.536 us | }
0) | .pick_next_task_fair() {
0) 2.032 us | .__pick_next_entity();
0) 2.064 us | .__clear_buddies();
0) | .set_next_entity() {
0) 2.672 us | .__dequeue_entity();
0) 6.864 us | }
Signed-off-by: Steven Rostedt <redacted>
---
arch/powerpc/Kconfig | 1 +
arch/powerpc/kernel/Makefile | 9 ++--
arch/powerpc/kernel/entry_64.S | 58 +++++++++++++++++++++++++-
arch/powerpc/kernel/ftrace.c | 79 ++++++++++++++++++++++++++++++++++++-
arch/powerpc/kernel/process.c | 16 +++++++
arch/powerpc/kernel/vmlinux.lds.S | 1 +
6 files changed, 154 insertions(+), 10 deletions(-)
@@ -29,6 +30,8 @@ static unsigned int ftrace_nop = PPC_NOP_INSTR;# define GET_ADDR(addr) (*(unsigned long *)addr)#endif+#ifdef CONFIG_DYNAMIC_FTRACE+staticunsignedintftrace_nop=PPC_NOP_INSTR;staticunsignedintftrace_calc_offset(longip,longaddr){
@@ -525,3 +528,75 @@ int __init ftrace_dyn_arch_init(void *data)return0;}+#endif /* CONFIG_DYNAMIC_FTRACE */++#ifdef CONFIG_FUNCTION_GRAPH_TRACER++/*+*Hookthereturnaddressandpushitinthestackofreturnaddrs+*incurrentthreadinfo.+*/+voidprepare_ftrace_return(unsignedlong*parent,unsignedlongself_addr)+{+unsignedlongold;+unsignedlonglongcalltime;+intfaulted;+structftrace_graph_enttrace;+unsignedlongreturn_hooker=(unsignedlong)+&return_to_handler;++if(unlikely(atomic_read(¤t->tracing_graph_pause)))+return;++return_hooker=GET_ADDR(return_hooker);++/*+*Protectagainstfault,evenifitshouldn't+*happen.Thistoolistoomuchintrusiveto+*ignoresuchaprotection.+*/+asmvolatile(+"1: "PPC_LL"%[old], 0(%[parent])\n"+"2: "PPC_STL"%[return_hooker], 0(%[parent])\n"+" li %[faulted], 0\n"+"3:"++".section .fixup, \"ax\"\n"+"4: li %[faulted], 1\n"+" b 3b\n"+".previous\n"++".section __ex_table,\"a\"\n"+PPC_LONG_ALIGN"\n"+PPC_LONG"1b,4b\n"+PPC_LONG"2b,4b\n"+".previous"++:[old]"=r"(old),[faulted]"=r"(faulted)+:[parent]"r"(parent),[return_hooker]"r"(return_hooker)+:"memory"+);++if(unlikely(faulted)){+ftrace_graph_stop();+WARN_ON(1);+return;+}++calltime=cpu_clock(raw_smp_processor_id());++if(ftrace_push_return_trace(old,calltime,+self_addr,&trace.depth)==-EBUSY){+*parent=old;+return;+}++trace.func=self_addr;++/* Only trace if the calling function expects to */+if(!ftrace_graph_entry(&trace)){+current->curr_ret_stack--;+*parent=old;+}+}+#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 01:16:30
From: Steven Rostedt <redacted>
There is nothing really arch specific of the push and pop functions
used by the function graph tracer. This patch moves them to generic
code.
Signed-off-by: Steven Rostedt <redacted>
---
arch/x86/include/asm/ftrace.h | 25 -----------
arch/x86/kernel/ftrace.c | 75 +---------------------------------
include/linux/ftrace.h | 24 +++++++++++
kernel/trace/trace_functions_graph.c | 75 ++++++++++++++++++++++++++++++++++
4 files changed, 100 insertions(+), 99 deletions(-)
@@ -389,79 +389,6 @@ void ftrace_nmi_exit(void)#endif /* !CONFIG_DYNAMIC_FTRACE */-/* Add a function return address to the trace stack on thread info.*/-staticintpush_return_trace(unsignedlongret,unsignedlonglongtime,-unsignedlongfunc,int*depth)-{-intindex;--if(!current->ret_stack)-return-EBUSY;--/* The return trace stack is full */-if(current->curr_ret_stack==FTRACE_RETFUNC_DEPTH-1){-atomic_inc(¤t->trace_overrun);-return-EBUSY;-}--index=++current->curr_ret_stack;-barrier();-current->ret_stack[index].ret=ret;-current->ret_stack[index].func=func;-current->ret_stack[index].calltime=time;-*depth=index;--return0;-}--/* Retrieve a function return address to the trace stack on thread info.*/-staticvoidpop_return_trace(structftrace_graph_ret*trace,unsignedlong*ret)-{-intindex;--index=current->curr_ret_stack;--if(unlikely(index<0)){-ftrace_graph_stop();-WARN_ON(1);-/* Might as well panic, otherwise we have no where to go */-*ret=(unsignedlong)panic;-return;-}--*ret=current->ret_stack[index].ret;-trace->func=current->ret_stack[index].func;-trace->calltime=current->ret_stack[index].calltime;-trace->overrun=atomic_read(¤t->trace_overrun);-trace->depth=index;-barrier();-current->curr_ret_stack--;--}--/*-*Sendthetracetothering-buffer.-*@returntheoriginalreturnaddress.-*/-unsignedlongftrace_return_to_handler(void)-{-structftrace_graph_rettrace;-unsignedlongret;--pop_return_trace(&trace,&ret);-trace.rettime=cpu_clock(raw_smp_processor_id());-ftrace_graph_return(&trace);--if(unlikely(!ret)){-ftrace_graph_stop();-WARN_ON(1);-/* Might as well panic. What else to do? */-ret=(unsignedlong)panic;-}--returnret;-}-/**Hookthereturnaddressandpushitinthestackofreturnaddrs*incurrentthreadinfo.
@@ -520,7 +447,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)calltime=cpu_clock(raw_smp_processor_id());-if(push_return_trace(old,calltime,+if(ftrace_push_return_trace(old,calltime,self_addr,&trace.depth)==-EBUSY){*parent=old;return;
@@ -42,6 +42,81 @@ static struct tracer_flags tracer_flags = {/* pid on the last trace processed */staticpid_tlast_pid[NR_CPUS]={[0...NR_CPUS-1]=-1};+/* Add a function return address to the trace stack on thread info.*/+int+ftrace_push_return_trace(unsignedlongret,unsignedlonglongtime,+unsignedlongfunc,int*depth)+{+intindex;++if(!current->ret_stack)+return-EBUSY;++/* The return trace stack is full */+if(current->curr_ret_stack==FTRACE_RETFUNC_DEPTH-1){+atomic_inc(¤t->trace_overrun);+return-EBUSY;+}++index=++current->curr_ret_stack;+barrier();+current->ret_stack[index].ret=ret;+current->ret_stack[index].func=func;+current->ret_stack[index].calltime=time;+*depth=index;++return0;+}++/* Retrieve a function return address to the trace stack on thread info.*/+void+ftrace_pop_return_trace(structftrace_graph_ret*trace,unsignedlong*ret)+{+intindex;++index=current->curr_ret_stack;++if(unlikely(index<0)){+ftrace_graph_stop();+WARN_ON(1);+/* Might as well panic, otherwise we have no where to go */+*ret=(unsignedlong)panic;+return;+}++*ret=current->ret_stack[index].ret;+trace->func=current->ret_stack[index].func;+trace->calltime=current->ret_stack[index].calltime;+trace->overrun=atomic_read(¤t->trace_overrun);+trace->depth=index;+barrier();+current->curr_ret_stack--;++}++/*+*Sendthetracetothering-buffer.+*@returntheoriginalreturnaddress.+*/+unsignedlongftrace_return_to_handler(void)+{+structftrace_graph_rettrace;+unsignedlongret;++ftrace_pop_return_trace(&trace,&ret);+trace.rettime=cpu_clock(raw_smp_processor_id());+ftrace_graph_return(&trace);++if(unlikely(!ret)){+ftrace_graph_stop();+WARN_ON(1);+/* Might as well panic. What else to do? */+ret=(unsignedlong)panic;+}++returnret;+}+staticintgraph_trace_init(structtrace_array*tr){intcpu,ret;
On Wed, Feb 11, 2009 at 08:10:51PM -0500, Steven Rostedt wrote:
The following set of patches are RFC and not for inclusion
(unless everyone is fine with them as is).
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
1) get generic code ready for other archs
2) get PowerPC 64-bit working with just static function tracing
3) get PowerPC 64-bit working with dynamic function tracing
4) get PowerPC 32-bit working with just static function tracing
5) get PowerPC 32-bit working with dynamic function tracing
(with some clean ups in between)
Thanks a lot Steven!
I'm sad to not having a Power Pc to test it...
The function graph tracer not only traces the start of a function
(uses the function tracer part for that) but also uses the kprobes
trick to replace the return address with a hook to trace the exit
of the function. These hooks are generic in that other tracers
can also use them. But the function graph tracer itself is very
powerful. Simply doing the following:
# echo function_graph > /debug/tracing/current_tracer
# cat /debug/tracing/trace
# tracer: function_graph
#
# CPU OVERHEAD/DURATION FUNCTION CALLS
# | | | | | | |
------------------------------------------
0) less-2228 => cat-2229
------------------------------------------
0) | .__do_fault() {
0) | .filemap_fault() {
0) | .find_lock_page() {
0) | .find_get_page() {
0) 3.168 us | .__rcu_read_lock();
0) 2.704 us | .__rcu_read_unlock();
0) + 14.640 us | }
0) + 20.112 us | }
0) + 26.464 us | }
0) 2.912 us | ._spin_lock();
0) 2.656 us | .page_add_file_rmap();
0) | .update_mmu_cache() {
0) | .hash_preload() {
0) 2.368 us | .get_slice_psize();
0) 2.752 us | .hash_page_do_lazy_icache();
0) 3.568 us | .native_hpte_insert();
0) + 19.680 us | }
0) + 24.960 us | }
0) 2.336 us | ._spin_unlock();
0) | .unlock_page() {
0) 2.688 us | .page_waitqueue();
0) 2.608 us | .__wake_up_bit();
0) + 12.912 us | }
0) ! 351.776 us | }
0) ! 357.392 us | }
0) 3.040 us | .up_read();
0) | .compat_sys_ioctl() {
0) 3.024 us | .fget_light();
0) | .tty_compat_ioctl() {
0) 2.704 us | .tty_paranoia_check();
0) | .tty_ldisc_ref_wait() {
0) | .tty_ldisc_try() {
0) 2.880 us | ._spin_lock_irqsave();
0) 2.928 us | ._spin_unlock_irqrestore();
0) + 13.776 us | }
0) + 19.424 us | }
[...]
As you can see, it gives a nice call trace of the functions being called
at run time, as well as a time stamp of how much time the function
took to execute.
Adding dynamic tracing to the mix, we can trace a single function:
# echo .do_fork > /debug/tracing/set_graph_function
# echo function_graph > /debug/tracing/current_tracer
# cat /debug/tracing/trace
# tracer: function_graph
#
# CPU OVERHEAD/DURATION FUNCTION CALLS
# | | | | | | |
1) | .do_fork() {
1) | .copy_process() {
1) | .prepare_to_copy() {
1) 2.944 us | .flush_fp_to_thread();
1) 2.800 us | .flush_altivec_to_thread();
1) 2.608 us | .flush_vsx_to_thread();
1) + 19.184 us | }
1) | .kmem_cache_alloc() {
1) 2.464 us | .slab_should_failslab();
1) 8.304 us | }
1) | .alloc_thread_info() {
1) | .kmem_cache_alloc() {
1) 2.512 us | .slab_should_failslab();
1) 8.224 us | }
1) + 13.344 us | }
1) 7.584 us | .arch_dup_task_struct();
1) | .copy_creds() {
1) 2.736 us | .__mutex_init();
1) | .prepare_creds() {
1) | .kmem_cache_alloc() {
1) 2.640 us | .slab_should_failslab();
1) 8.368 us | }
[...]
Note, the '.' in the '.do_fork' is a PowerPC64 thing. PowerPC32 and
other archs just need to do 'do_fork', without the dot.
The following patches are in:
git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-2.6-trace.git
branch: rfc/ppc/ftrace
Steven Rostedt (7):
tracing/function-graph-tracer: make arch generic push pop functions
powerpc64: port of the function graph tracer
powerpc64, tracing: add function graph tracer with dynamic tracing
powerpc64, ftrace: save toc only on modules for function graph
powerpc32, ftrace: save and restore mcount regs with macro
powerpc32, ftrace: port function graph tracer to ppc32, static only
powerpc32, ftrace: dynamic function graph tracer
----
arch/powerpc/Kconfig | 1 +
arch/powerpc/include/asm/ftrace.h | 39 ++++++++++-
arch/powerpc/kernel/Makefile | 9 +-
arch/powerpc/kernel/entry_32.S | 115 ++++++++++++++---------------
arch/powerpc/kernel/entry_64.S | 89 +++++++++++++++++++++-
arch/powerpc/kernel/ftrace.c | 135 ++++++++++++++++++++++++++++++++--
arch/powerpc/kernel/process.c | 16 ++++
arch/powerpc/kernel/vmlinux.lds.S | 1 +
arch/x86/include/asm/ftrace.h | 25 ------
arch/x86/kernel/ftrace.c | 75 +------------------
include/linux/ftrace.h | 24 ++++++
kernel/trace/trace_functions_graph.c | 75 +++++++++++++++++++
12 files changed, 428 insertions(+), 176 deletions(-)
--
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 02:17:21
On Thu, 12 Feb 2009, Frederic Weisbecker wrote:
On Wed, Feb 11, 2009 at 08:10:51PM -0500, Steven Rostedt wrote:
quoted
The following set of patches are RFC and not for inclusion
(unless everyone is fine with them as is).
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
1) get generic code ready for other archs
2) get PowerPC 64-bit working with just static function tracing
3) get PowerPC 64-bit working with dynamic function tracing
4) get PowerPC 32-bit working with just static function tracing
5) get PowerPC 32-bit working with dynamic function tracing
(with some clean ups in between)
Thanks a lot Steven!
I'm sad to not having a Power Pc to test it...
If you had a PowerPC, I doubt I would have been the one to port it ;-)
-- Steve
From: Michael Ellerman <hidden> Date: 2009-02-12 02:23:38
On Wed, 2009-02-11 at 20:10 -0500, Steven Rostedt wrote:
The following set of patches are RFC and not for inclusion
(unless everyone is fine with them as is).
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
1) get generic code ready for other archs
2) get PowerPC 64-bit working with just static function tracing
3) get PowerPC 64-bit working with dynamic function tracing
4) get PowerPC 32-bit working with just static function tracing
5) get PowerPC 32-bit working with dynamic function tracing
(with some clean ups in between)
The function graph tracer not only traces the start of a function
(uses the function tracer part for that) but also uses the kprobes
trick to replace the return address with a hook to trace the exit
of the function.
You use the "kprobes trick", but none of the kprobes code (AFAICS).
Couldn't there be some common code between the two?
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 02:38:12
On Thu, 12 Feb 2009, Michael Ellerman wrote:
quoted
The function graph tracer not only traces the start of a function
(uses the function tracer part for that) but also uses the kprobes
trick to replace the return address with a hook to trace the exit
of the function.
You use the "kprobes trick", but none of the kprobes code (AFAICS).
Couldn't there be some common code between the two?
I'm not 100% sure how kprobes work, but I believe they use traps. And then
they set the return address to take another trap, to fix it. I could be
totally off here, on how kprobes does this.
But ftrace is about executing the code directly. The return code jumps to
a another function in asm that will set up the call to do the tracing, and
then fix the return pointer back. The only thing that is similar between
the two approaches that I can tell, is that we both modify the return
address of the function. I took a quick peek at the kprobes code and I
see no easy way to share it.
-- Steve
On Wed, Feb 11, 2009 at 09:16:57PM -0500, Steven Rostedt wrote:
On Thu, 12 Feb 2009, Frederic Weisbecker wrote:
quoted
On Wed, Feb 11, 2009 at 08:10:51PM -0500, Steven Rostedt wrote:
quoted
The following set of patches are RFC and not for inclusion
(unless everyone is fine with them as is).
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
1) get generic code ready for other archs
2) get PowerPC 64-bit working with just static function tracing
3) get PowerPC 64-bit working with dynamic function tracing
4) get PowerPC 32-bit working with just static function tracing
5) get PowerPC 32-bit working with dynamic function tracing
(with some clean ups in between)
Thanks a lot Steven!
I'm sad to not having a Power Pc to test it...
If you had a PowerPC, I doubt I would have been the one to port it ;-)
Especially since you already implemented ftrace on PowerPc :)
I will acquire an Arm board soon to adapt function graph on Arm...
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 16:31:55
On Thu, 12 Feb 2009, Frederic Weisbecker wrote:
On Wed, Feb 11, 2009 at 08:10:51PM -0500, Steven Rostedt wrote:
quoted
The following set of patches are RFC and not for inclusion
(unless everyone is fine with them as is).
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
1) get generic code ready for other archs
2) get PowerPC 64-bit working with just static function tracing
3) get PowerPC 64-bit working with dynamic function tracing
4) get PowerPC 32-bit working with just static function tracing
5) get PowerPC 32-bit working with dynamic function tracing
(with some clean ups in between)
Thanks a lot Steven!
I'm sad to not having a Power Pc to test it...
BTW, Can I count that as an Acked-by: for the first patch. Since the first
patch does modify your code.
-- Steve
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 16:35:41
On Wed, 11 Feb 2009, Steven Rostedt wrote:
The following set of patches are RFC and not for inclusion
(unless everyone is fine with them as is).
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
1) get generic code ready for other archs
2) get PowerPC 64-bit working with just static function tracing
3) get PowerPC 64-bit working with dynamic function tracing
4) get PowerPC 32-bit working with just static function tracing
5) get PowerPC 32-bit working with dynamic function tracing
(with some clean ups in between)
Ben, if you get some time (no rush really), can you give an acked-by
on each of the PPC patches. The first patch is ftrace generic, so
you can ignore that one.
I'll keep it in the RFC state, until I have an ack from either you or
Paul.
I'm not sure if these changes should go via you or Ingo. I'm thinking
that, since the first change modifies core ftrace code, I'll send it
towards tip, since all the rest depends on that first change.
Thanks,
-- Steve
On Thu, Feb 12, 2009 at 11:31:44AM -0500, Steven Rostedt wrote:
On Thu, 12 Feb 2009, Frederic Weisbecker wrote:
quoted
On Wed, Feb 11, 2009 at 08:10:51PM -0500, Steven Rostedt wrote:
quoted
The following set of patches are RFC and not for inclusion
(unless everyone is fine with them as is).
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
1) get generic code ready for other archs
2) get PowerPC 64-bit working with just static function tracing
3) get PowerPC 64-bit working with dynamic function tracing
4) get PowerPC 32-bit working with just static function tracing
5) get PowerPC 32-bit working with dynamic function tracing
(with some clean ups in between)
Thanks a lot Steven!
I'm sad to not having a Power Pc to test it...
BTW, Can I count that as an Acked-by: for the first patch. Since the first
patch does modify your code.
-- Steve
Yes of course, I knew most of it was architecture independant but I delayed
this TODO for future ports, and you've done it.
Thanks.
Just a micro detail: the ftrace_push/pop_return_trace are parts of
the core of the entry/return probe, something that could be used
by other users than the function graph tracer itself.
Perhaps it would be better to put them in kernel/trace/ftrace.c
What do you think?
Anyway, Acked-by: Frederic Weisbecker [off-list ref]
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 16:58:25
On Thu, 12 Feb 2009, Frederic Weisbecker wrote:
Yes of course, I knew most of it was architecture independant but I delayed
this TODO for future ports, and you've done it.
Thanks.
Just a micro detail: the ftrace_push/pop_return_trace are parts of
the core of the entry/return probe, something that could be used
by other users than the function graph tracer itself.
Perhaps it would be better to put them in kernel/trace/ftrace.c
What do you think?
I'll go with your above method. We'll move it when it comes to that ;-)
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
I added these to my ps3-linux.git tree. Very casual testing shows
they seem to work OK.
Tested-by: Geoff Levand <redacted> Working OK on PS3.
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 23:41:36
On Thu, 12 Feb 2009, Geoff Levand wrote:
On 02/11/2009 05:10 PM, Steven Rostedt wrote:
quoted
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
I added these to my ps3-linux.git tree. Very casual testing shows
they seem to work OK.
Tested-by: Geoff Levand <redacted> Working OK on PS3.
Thanks!
Is the ps3 64 or 32 bit? I'll put your tested by on the appropriate
patches.
-- Steve
On Thu, Feb 12, 2009 at 06:41:26PM -0500, Steven Rostedt wrote:
On Thu, 12 Feb 2009, Geoff Levand wrote:
quoted
On 02/11/2009 05:10 PM, Steven Rostedt wrote:
quoted
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
I added these to my ps3-linux.git tree. Very casual testing shows
they seem to work OK.
Tested-by: Geoff Levand <redacted> Working OK on PS3.
Thanks!
Is the ps3 64 or 32 bit? I'll put your tested by on the appropriate
patches.
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
I added these to my ps3-linux.git tree. Very casual testing shows
they seem to work OK.
Tested-by: Geoff Levand <redacted> Working OK on PS3.
Thanks!
Is the ps3 64 or 32 bit? I'll put your tested by on the appropriate
patches.
It uses the Cell processor, which is 64 bit.
-Geoff
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-12 23:51:46
On Thu, 12 Feb 2009, Geoff Levand wrote:
On 02/12/2009 03:41 PM, Steven Rostedt wrote:
quoted
On Thu, 12 Feb 2009, Geoff Levand wrote:
quoted
On 02/11/2009 05:10 PM, Steven Rostedt wrote:
quoted
This is the port to PowerPC of the function graph tracer that was written
by Frederic Weisbecker for the x86 architecture. It is broken up
into a series of logical steps.
I added these to my ps3-linux.git tree. Very casual testing shows
they seem to work OK.
Tested-by: Geoff Levand <redacted> Working OK on PS3.
Thanks!
Is the ps3 64 or 32 bit? I'll put your tested by on the appropriate
patches.
From: Benjamin Herrenschmidt <benh@kernel.crashing.org> Date: 2009-02-13 04:13:00
On Wed, 2009-02-11 at 20:10 -0500, Steven Rostedt wrote:
+# timers used by tracing
+CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog
endif
That means no tracing of the timer interrupts etc... maybe we should
just move the specific function that we don't want traced out to a
separate file ?
Appart from that, it looks ok, though I might have missed something :-)
Cheers,
Ben.
long ip, unsigned long addr)
*/
addr = GET_ADDR(addr);
- /* Set to "bl addr" */
- op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc);
+ /* if (link) set op to 'bl' else 'b' */
+ op = 0x48000000 | (link ? 1 : 0);
+ op |= (ftrace_calc_offset(ip, addr) & 0x03fffffc);
Any reason why you aren't using the code in
arch/powerpc/lib/code-patching.c here ?
From: Steven Rostedt <rostedt@goodmis.org> Date: 2009-02-13 04:19:18
On Fri, 13 Feb 2009, Benjamin Herrenschmidt wrote:
quoted
On Wed, 2009-02-11 at 20:10 -0500, Steven Rostedt wrote:
+# timers used by tracing
+CFLAGS_REMOVE_time.o = -pg -mno-sched-epilog
endif
That means no tracing of the timer interrupts etc... maybe we should
just move the specific function that we don't want traced out to a
separate file ?
The function graph tracer calls cpu_clock, which calls sched_clock,
to get the times. There's no protection against recursion here, since
we want to let interrupts still be recorded, and we do not need to disable
interrupts.
But if the cpu_clock calls something that is traced, it will recurse, and
cause a lockup. What ever functions those are, we could annotate with
notrace. I just used the x86 blind method of 'dont trace this file'.
Appart from that, it looks ok, though I might have missed something :-)
long ip, unsigned long addr)
*/
addr = GET_ADDR(addr);
- /* Set to "bl addr" */
- op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc);
+ /* if (link) set op to 'bl' else 'b' */
+ op = 0x48000000 | (link ? 1 : 0);
+ op |= (ftrace_calc_offset(ip, addr) & 0x03fffffc);
Any reason why you aren't using the code in
arch/powerpc/lib/code-patching.c here ?
Heh, memcpy of 4 bytes :-) I hope gcc is smart enough to turn that into
a simple load/store ..
hehe, I hated writing that. I just did not want to touch the (already
working code) of the dynamic ftrace. I guess I could still use longs and
then typecast them to char pointers for the ftrace_modify_code.
Thanks,
-- Steve
long ip, unsigned long addr)
*/
addr = GET_ADDR(addr);
- /* Set to "bl addr" */
- op = 0x48000001 | (ftrace_calc_offset(ip, addr) & 0x03fffffc);
+ /* if (link) set op to 'bl' else 'b' */
+ op = 0x48000000 | (link ? 1 : 0);
+ op |= (ftrace_calc_offset(ip, addr) & 0x03fffffc);
Any reason why you aren't using the code in
arch/powerpc/lib/code-patching.c here ?
Yes, because I did not know about it ;-)
I'll write up a patch to change this. But I'll post this series as is for
now.
Thanks,
-- Steve