Skip to content

Commit e48b831

Browse files
Kan Liangacmel
authored andcommitted
perf machine: Refine the function for LBR call stack reconstruction
LBR only collect the user call stack. To reconstruct a call stack, both kernel call stack and user call stack are required. The function resolve_lbr_callchain_sample() mix the kernel call stack and user call stack. Now, with the help of HW idx, perf tool can reconstruct a more complete call stack by adding some user call stack from previous sample. However, current implementation is hard to be extended to support it. Current code path for resolve_lbr_callchain_sample() for (j = 0; j < mix_chain_nr; j++) { if (ORDER_CALLEE) { if (kernel callchain) Fill callchain info else if (LBR callchain) Fill callchain info } else { if (LBR callchain) Fill callchain info else if (kernel callchain) Fill callchain info } add_callchain_ip(); } With the patch, if (ORDER_CALLEE) { for (j = 0; j < NUM of kernel callchain) { Fill callchain info add_callchain_ip(); } for (; j < mix_chain_nr) { Fill callchain info add_callchain_ip(); } } else { for (; j < NUM of LBR callchain) { Fill callchain info add_callchain_ip(); } for (j = 0; j < mix_chain_nr) { Fill callchain info add_callchain_ip(); } } No functional changes. Signed-off-by: Kan Liang <[email protected]> Reviewed-by: Andi Kleen <[email protected]> Acked-by: Jiri Olsa <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexey Budankov <[email protected]> Cc: Mathieu Poirier <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Pavel Gerasimov <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Vitaly Slobodskoy <[email protected]> Link: http://lore.kernel.org/lkml/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent f860326 commit e48b831

File tree

1 file changed

+76
-35
lines changed

1 file changed

+76
-35
lines changed

tools/perf/util/machine.c

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,6 +2214,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
22142214
bool branch;
22152215
struct branch_flags *flags;
22162216
int mix_chain_nr;
2217+
int err;
22172218

22182219
for (i = 0; i < chain_nr; i++) {
22192220
if (chain->ips[i] == PERF_CONTEXT_USER)
@@ -2239,50 +2240,90 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
22392240
*/
22402241
mix_chain_nr = i + 1 + lbr_nr + 1;
22412242

2242-
for (j = 0; j < mix_chain_nr; j++) {
2243-
int err;
2244-
2245-
branch = false;
2246-
flags = NULL;
2247-
2248-
if (callchain_param.order == ORDER_CALLEE) {
2249-
if (j < i + 1)
2250-
ip = chain->ips[j];
2251-
else if (j > i + 1) {
2252-
k = j - i - 2;
2253-
ip = entries[k].from;
2254-
branch = true;
2255-
flags = &entries[k].flags;
2256-
} else {
2257-
ip = entries[0].to;
2258-
branch = true;
2259-
flags = &entries[0].flags;
2260-
branch_from = entries[0].from;
2261-
}
2262-
} else {
2263-
if (j < lbr_nr) {
2264-
k = lbr_nr - j - 1;
2265-
ip = entries[k].from;
2266-
branch = true;
2267-
flags = &entries[k].flags;
2268-
} else if (j > lbr_nr)
2269-
ip = chain->ips[i + 1 - (j - lbr_nr)];
2270-
else {
2271-
ip = entries[0].to;
2272-
branch = true;
2273-
flags = &entries[0].flags;
2274-
branch_from = entries[0].from;
2275-
}
2243+
if (callchain_param.order == ORDER_CALLEE) {
2244+
/* Add kernel ip */
2245+
for (j = 0; j < i + 1; j++) {
2246+
ip = chain->ips[j];
2247+
branch = false;
2248+
flags = NULL;
2249+
err = add_callchain_ip(thread, cursor, parent,
2250+
root_al, &cpumode, ip,
2251+
branch, flags, NULL,
2252+
branch_from);
2253+
if (err)
2254+
goto error;
22762255
}
2256+
/* Add LBR ip from first entries.to */
2257+
ip = entries[0].to;
2258+
branch = true;
2259+
flags = &entries[0].flags;
2260+
branch_from = entries[0].from;
2261+
err = add_callchain_ip(thread, cursor, parent,
2262+
root_al, &cpumode, ip,
2263+
branch, flags, NULL,
2264+
branch_from);
2265+
if (err)
2266+
goto error;
22772267

2268+
/* Add LBR ip from entries.from one by one. */
2269+
for (j = i + 2; j < mix_chain_nr; j++) {
2270+
k = j - i - 2;
2271+
ip = entries[k].from;
2272+
branch = true;
2273+
flags = &entries[k].flags;
2274+
2275+
err = add_callchain_ip(thread, cursor, parent,
2276+
root_al, &cpumode, ip,
2277+
branch, flags, NULL,
2278+
branch_from);
2279+
if (err)
2280+
goto error;
2281+
}
2282+
} else {
2283+
/* Add LBR ip from entries.from one by one. */
2284+
for (j = 0; j < lbr_nr; j++) {
2285+
k = lbr_nr - j - 1;
2286+
ip = entries[k].from;
2287+
branch = true;
2288+
flags = &entries[k].flags;
2289+
2290+
err = add_callchain_ip(thread, cursor, parent,
2291+
root_al, &cpumode, ip,
2292+
branch, flags, NULL,
2293+
branch_from);
2294+
if (err)
2295+
goto error;
2296+
}
2297+
2298+
/* Add LBR ip from first entries.to */
2299+
ip = entries[0].to;
2300+
branch = true;
2301+
flags = &entries[0].flags;
2302+
branch_from = entries[0].from;
22782303
err = add_callchain_ip(thread, cursor, parent,
22792304
root_al, &cpumode, ip,
22802305
branch, flags, NULL,
22812306
branch_from);
22822307
if (err)
2283-
return (err < 0) ? err : 0;
2308+
goto error;
2309+
2310+
/* Add kernel ip */
2311+
for (j = lbr_nr + 1; j < mix_chain_nr; j++) {
2312+
ip = chain->ips[i + 1 - (j - lbr_nr)];
2313+
branch = false;
2314+
flags = NULL;
2315+
err = add_callchain_ip(thread, cursor, parent,
2316+
root_al, &cpumode, ip,
2317+
branch, flags, NULL,
2318+
branch_from);
2319+
if (err)
2320+
goto error;
2321+
}
22842322
}
22852323
return 1;
2324+
2325+
error:
2326+
return (err < 0) ? err : 0;
22862327
}
22872328

22882329
static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,

0 commit comments

Comments
 (0)