diff options
author | Paul Mackerras <paulus@samba.org> | 2010-03-18 01:05:13 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-03-18 01:48:29 -0400 |
commit | 9eff26ea48bfbe2885b158742a7512a097ec911b (patch) | |
tree | a914f959b78bdf4ee9eca897a743d727c27faf4f /arch/powerpc/kernel/misc.S | |
parent | 00909e955125e90a6ebb34671c56c4c851e62951 (diff) |
powerpc/perf_events: Fix call-graph recording, add perf_arch_fetch_caller_regs
This implements a powerpc version of perf_arch_fetch_caller_regs
to get correct call-graphs.
It's implemented in assembly because that way we can be sure there isn't
a stack frame for perf_arch_fetch_caller_regs. If it was in C, gcc might
or might not create a stack frame for it, which would affect the number
of levels we have to skip.
With this, we see results from perf record -e lock:lock_acquire like
this:
# Samples: 24878
#
# Overhead Command Shared Object Symbol
# ........ .............. ................. ......
#
14.99% perf [kernel.kallsyms] [k] ._raw_spin_lock
|
--- ._raw_spin_lock
|
|--25.00%-- .alloc_fd
| (nil)
| |
| |--50.00%-- .anon_inode_getfd
| | .sys_perf_event_open
| | syscall_exit
| | syscall
| | create_counter
| | __cmd_record
| | run_builtin
| | main
| | 0xfd2e704
| | 0xfd2e8c0
| | (nil)
... etc.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: anton@samba.org
Cc: linuxppc-dev@ozlabs.org
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
LKML-Reference: <20100318050513.GA6575@drongo>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/powerpc/kernel/misc.S')
-rw-r--r-- | arch/powerpc/kernel/misc.S | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index 2d29752cbe16..b485a87c94e1 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S | |||
@@ -127,3 +127,31 @@ _GLOBAL(__setup_cpu_power7) | |||
127 | _GLOBAL(__restore_cpu_power7) | 127 | _GLOBAL(__restore_cpu_power7) |
128 | /* place holder */ | 128 | /* place holder */ |
129 | blr | 129 | blr |
130 | |||
131 | #ifdef CONFIG_EVENT_TRACING | ||
132 | /* | ||
133 | * Get a minimal set of registers for our caller's nth caller. | ||
134 | * r3 = regs pointer, r5 = n. | ||
135 | * | ||
136 | * We only get R1 (stack pointer), NIP (next instruction pointer) | ||
137 | * and LR (link register). These are all we can get in the | ||
138 | * general case without doing complicated stack unwinding, but | ||
139 | * fortunately they are enough to do a stack backtrace, which | ||
140 | * is all we need them for. | ||
141 | */ | ||
142 | _GLOBAL(perf_arch_fetch_caller_regs) | ||
143 | mr r6,r1 | ||
144 | cmpwi r5,0 | ||
145 | mflr r4 | ||
146 | ble 2f | ||
147 | mtctr r5 | ||
148 | 1: PPC_LL r6,0(r6) | ||
149 | bdnz 1b | ||
150 | PPC_LL r4,PPC_LR_STKOFF(r6) | ||
151 | 2: PPC_LL r7,0(r6) | ||
152 | PPC_LL r7,PPC_LR_STKOFF(r7) | ||
153 | PPC_STL r6,GPR1-STACK_FRAME_OVERHEAD(r3) | ||
154 | PPC_STL r4,_NIP-STACK_FRAME_OVERHEAD(r3) | ||
155 | PPC_STL r7,_LINK-STACK_FRAME_OVERHEAD(r3) | ||
156 | blr | ||
157 | #endif /* CONFIG_EVENT_TRACING */ | ||