aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-10-30 11:12:26 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2018-10-31 08:57:51 -0400
commite9024d519d892b38176cafd46f68a7cdddd77412 (patch)
tree0f597c45f6bab115102633212d96b0ac1447301e /tools
parentd6c9c05fe1eb4b213b183d8a1e79416256dc833a (diff)
perf callchain: Honour the ordering of PERF_CONTEXT_{USER,KERNEL,etc}
When processing using 'perf report -g caller', which is the default, we ended up reverting the callchain entries received from the kernel, but simply reverting throws away the information that tells that from a point onwards the addresses are for userspace, kernel, guest kernel, guest user, hypervisor. The idea is that if we are walking backwards, for each cluster of non-cpumode entries we have to first scan backwards for the next one and use that for the cluster. This seems silly and more expensive than it needs to be but it is enough for a initial fix. The code here is really complicated because it is intimately intertwined with the lbr and branch handling, as well as this callchain order, further fixes will be needed to properly take into account the cpumode in those cases. Another problem with ORDER_CALLER is that the NULL "0" IP that is at the end of most callchains shows up at the top of the histogram because every callchain contains it and with ORDER_CALLER it is the first entry. Signed-off-by: David S. Miller <davem@davemloft.net> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Adrian Hunter <adrian.hunter@intel.com> Cc: David Ahern <dsahern@gmail.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Souvik Banerjee <souvik1997@gmail.com> Cc: Wang Nan <wangnan0@huawei.com> Cc: stable@vger.kernel.org # 4.19 Link: https://lkml.kernel.org/n/tip-2wt3ayp6j2y2f2xowixa8y6y@git.kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/machine.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 111ae858cbcb..8ee8ab39d8ac 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -2140,6 +2140,27 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
2140 return 0; 2140 return 0;
2141} 2141}
2142 2142
2143static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,
2144 struct callchain_cursor *cursor,
2145 struct symbol **parent,
2146 struct addr_location *root_al,
2147 u8 *cpumode, int ent)
2148{
2149 int err = 0;
2150
2151 while (--ent >= 0) {
2152 u64 ip = chain->ips[ent];
2153
2154 if (ip >= PERF_CONTEXT_MAX) {
2155 err = add_callchain_ip(thread, cursor, parent,
2156 root_al, cpumode, ip,
2157 false, NULL, NULL, 0);
2158 break;
2159 }
2160 }
2161 return err;
2162}
2163
2143static int thread__resolve_callchain_sample(struct thread *thread, 2164static int thread__resolve_callchain_sample(struct thread *thread,
2144 struct callchain_cursor *cursor, 2165 struct callchain_cursor *cursor,
2145 struct perf_evsel *evsel, 2166 struct perf_evsel *evsel,
@@ -2246,6 +2267,12 @@ static int thread__resolve_callchain_sample(struct thread *thread,
2246 } 2267 }
2247 2268
2248check_calls: 2269check_calls:
2270 if (callchain_param.order != ORDER_CALLEE) {
2271 err = find_prev_cpumode(chain, thread, cursor, parent, root_al,
2272 &cpumode, chain->nr - first_call);
2273 if (err)
2274 return (err < 0) ? err : 0;
2275 }
2249 for (i = first_call, nr_entries = 0; 2276 for (i = first_call, nr_entries = 0;
2250 i < chain_nr && nr_entries < max_stack; i++) { 2277 i < chain_nr && nr_entries < max_stack; i++) {
2251 u64 ip; 2278 u64 ip;
@@ -2260,9 +2287,15 @@ check_calls:
2260 continue; 2287 continue;
2261#endif 2288#endif
2262 ip = chain->ips[j]; 2289 ip = chain->ips[j];
2263
2264 if (ip < PERF_CONTEXT_MAX) 2290 if (ip < PERF_CONTEXT_MAX)
2265 ++nr_entries; 2291 ++nr_entries;
2292 else if (callchain_param.order != ORDER_CALLEE) {
2293 err = find_prev_cpumode(chain, thread, cursor, parent,
2294 root_al, &cpumode, j);
2295 if (err)
2296 return (err < 0) ? err : 0;
2297 continue;
2298 }
2266 2299
2267 err = add_callchain_ip(thread, cursor, parent, 2300 err = add_callchain_ip(thread, cursor, parent,
2268 root_al, &cpumode, ip, 2301 root_al, &cpumode, ip,