RE: [PATCH v1] perf callchain: fix kernel symbol resolution by remembering the cpumode

From: Liang, Kan
Date: Fri Mar 27 2015 - 12:12:03 EST




> Commit 2e77784bb7d8 ("perf callchain: Move cpumode resolve code to
> add_callchain_ip") promised "No change in behavior.".
>
> As this commit breaks callchains on s390x (symbols not getting resolved,
> observed when profiling the kernel), this statement is wrong. The
> cpumode must be kept when iterating over all ips, otherwise the default
> (PERF_RECORD_MISC_USER) will be used by error.

Indeed.
Besides thread__resolve_callchain_sample, lbr path also need to
be patched.

@@ -1538,6 +1536,7 @@ static int resolve_lbr_callchain_sample
(struct thread *thread,
{
struct ip_callchain *chain = sample->callchain;
int chain_nr = min(max_stack, (int)chain->nr);
+ u8 cpumode = PERF_RECORD_MISC_USER;
int i, j, err;
u64 ip;

@@ -1584,7 +1583,7 @@ static int resolve_lbr_callchain_sample
(struct thread *thread,
ip = lbr_stack->entries[0].to;
}

- err = add_callchain_ip(thread, parent, root_al, false, ip);
+ err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
if (err)
return (err < 0) ? err : 0;
}

Thanks,
Kan

>
> Signed-off-by: David Hildenbrand <dahi@xxxxxxxxxxxxxxxxxx>
> ---
> tools/perf/util/machine.c | 25 ++++++++++++-------------
> 1 file changed, 12 insertions(+), 13 deletions(-)
>
> diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index
> e335330..c843652 100644
> --- a/tools/perf/util/machine.c
> +++ b/tools/perf/util/machine.c
> @@ -1408,29 +1408,27 @@ struct mem_info
> *sample__resolve_mem(struct perf_sample *sample, static int
> add_callchain_ip(struct thread *thread,
> struct symbol **parent,
> struct addr_location *root_al,
> - bool branch_history,
> + u8 *cpumode,
> u64 ip)
> {
> struct addr_location al;
>
> al.filtered = 0;
> al.sym = NULL;
> - if (branch_history)
> + if (!cpumode) {
> thread__find_cpumode_addr_location(thread,
> MAP__FUNCTION,
> ip, &al);
> - else {
> - u8 cpumode = PERF_RECORD_MISC_USER;
> -
> + } else {
> if (ip >= PERF_CONTEXT_MAX) {
> switch (ip) {
> case PERF_CONTEXT_HV:
> - cpumode =
> PERF_RECORD_MISC_HYPERVISOR;
> + *cpumode =
> PERF_RECORD_MISC_HYPERVISOR;
> break;
> case PERF_CONTEXT_KERNEL:
> - cpumode = PERF_RECORD_MISC_KERNEL;
> + *cpumode = PERF_RECORD_MISC_KERNEL;
> break;
> case PERF_CONTEXT_USER:
> - cpumode = PERF_RECORD_MISC_USER;
> + *cpumode = PERF_RECORD_MISC_USER;
> break;
> default:
> pr_debug("invalid callchain context: "
> @@ -1444,8 +1442,8 @@ static int add_callchain_ip(struct thread *thread,
> }
> return 0;
> }
> - thread__find_addr_location(thread, cpumode,
> MAP__FUNCTION,
> - ip, &al);
> + thread__find_addr_location(thread, *cpumode,
> MAP__FUNCTION,
> + ip, &al);
> }
>
> if (al.sym != NULL) {
> @@ -1604,6 +1602,7 @@ static int
> thread__resolve_callchain_sample(struct thread *thread,
> struct branch_stack *branch = sample->branch_stack;
> struct ip_callchain *chain = sample->callchain;
> int chain_nr = min(max_stack, (int)chain->nr);
> + u8 cpumode = PERF_RECORD_MISC_USER;
> int i, j, err;
> int skip_idx = -1;
> int first_call = 0;
> @@ -1669,10 +1668,10 @@ static int
> thread__resolve_callchain_sample(struct thread *thread,
>
> for (i = 0; i < nr; i++) {
> err = add_callchain_ip(thread, parent, root_al,
> - true, be[i].to);
> + NULL, be[i].to);
> if (!err)
> err = add_callchain_ip(thread, parent,
> root_al,
> - true, be[i].from);
> + NULL, be[i].from);
> if (err == -EINVAL)
> break;
> if (err)
> @@ -1701,7 +1700,7 @@ check_calls:
> #endif
> ip = chain->ips[j];
>
> - err = add_callchain_ip(thread, parent, root_al, false, ip);
> + err = add_callchain_ip(thread, parent, root_al, &cpumode,
> ip);
>
> if (err)
> return (err < 0) ? err : 0;
> --
> 2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/