Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf script: Enable printing of branch stack

This patch improves perf script by enabling printing of the
branch stack via the 'brstack' and 'brstacksym' arguments to
the field selection option -F. The option is off by default
and operates only if the perf.data file has branch stack content.

The branches are printed in to/from pairs. The most recent branch
is printed first. The number of branch entries vary based on the
underlying hardware and filtering used.

The brstack prints FROM/TO addresses in raw hexadecimal format.
The brstacksym prints FROM/TO addresses in symbolic form wherever
possible.

$ perf script -F ip,brstack
5d3000 0x401aa0/0x5d2000/M/-/-/-/0 ...

$ perf script -F ip,brstacksym
4011e0 noploop+0x0/noploop+0x0/P/-/-/0

The notation F/T/M/X/A/C describes the attributes of the branch.
F=from, T=to, M/P=misprediction/prediction, X=TSX, A=TSX abort, C=cycles (SKL)

Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Yuanfang Chen <cyfmxc@gmail.com>
Link: http://lkml.kernel.org/r/1441039273-16260-5-git-send-email-eranian@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Stephane Eranian and committed by
Arnaldo Carvalho de Melo
dc323ce8 729a7841

+93 -3
+12 -2
tools/perf/Documentation/perf-script.txt
··· 112 112 --debug-mode:: 113 113 Do various checks like samples ordering and lost events. 114 114 115 - -f:: 115 + -F:: 116 116 --fields:: 117 117 Comma separated list of fields to print. Options are: 118 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 119 - srcline, period, iregs, flags. 119 + srcline, period, iregs, brstack, brstacksym, flags. 120 120 Field list can be prepended with the type, trace, sw or hw, 121 121 to indicate to which event type the field list applies. 122 122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace ··· 174 174 175 175 Finally, a user may not set fields to none for all event types. 176 176 i.e., -f "" is not allowed. 177 + 178 + The brstack output includes branch related information with raw addresses using the 179 + /v/v/v/v/ syntax in the following order: 180 + FROM: branch source instruction 181 + TO : branch target instruction 182 + M/P/-: M=branch target mispredicted or branch direction was mispredicted, P=target predicted or direction predicted, -=not supported 183 + X/- : X=branch inside a transactional region, -=not in transaction region or not supported 184 + A/- : A=TSX abort entry, -=not aborted region or not supported 185 + 186 + The brstacksym is identical to brstack, except that the FROM and TO addresses are printed in a symbolic form if possible. 177 187 178 188 -k:: 179 189 --vmlinux=<file>::
+81 -1
tools/perf/builtin-script.c
··· 51 51 PERF_OUTPUT_SRCLINE = 1U << 12, 52 52 PERF_OUTPUT_PERIOD = 1U << 13, 53 53 PERF_OUTPUT_IREGS = 1U << 14, 54 + PERF_OUTPUT_BRSTACK = 1U << 15, 55 + PERF_OUTPUT_BRSTACKSYM = 1U << 16, 54 56 }; 55 57 56 58 struct output_option { ··· 74 72 {.str = "srcline", .field = PERF_OUTPUT_SRCLINE}, 75 73 {.str = "period", .field = PERF_OUTPUT_PERIOD}, 76 74 {.str = "iregs", .field = PERF_OUTPUT_IREGS}, 75 + {.str = "brstack", .field = PERF_OUTPUT_BRSTACK}, 76 + {.str = "brstacksym", .field = PERF_OUTPUT_BRSTACKSYM}, 77 77 }; 78 78 79 79 /* default set to maintain compatibility with current format */ ··· 429 425 } 430 426 } 431 427 428 + static inline char 429 + mispred_str(struct branch_entry *br) 430 + { 431 + if (!(br->flags.mispred || br->flags.predicted)) 432 + return '-'; 433 + 434 + return br->flags.predicted ? 'P' : 'M'; 435 + } 436 + 437 + static void print_sample_brstack(union perf_event *event __maybe_unused, 438 + struct perf_sample *sample, 439 + struct thread *thread __maybe_unused, 440 + struct perf_event_attr *attr __maybe_unused) 441 + { 442 + struct branch_stack *br = sample->branch_stack; 443 + u64 i; 444 + 445 + if (!(br && br->nr)) 446 + return; 447 + 448 + for (i = 0; i < br->nr; i++) { 449 + printf(" 0x%"PRIx64"/0x%"PRIx64"/%c/%c/%c/%d ", 450 + br->entries[i].from, 451 + br->entries[i].to, 452 + mispred_str( br->entries + i), 453 + br->entries[i].flags.in_tx? 'X' : '-', 454 + br->entries[i].flags.abort? 'A' : '-', 455 + br->entries[i].flags.cycles); 456 + } 457 + } 458 + 459 + static void print_sample_brstacksym(union perf_event *event __maybe_unused, 460 + struct perf_sample *sample, 461 + struct thread *thread __maybe_unused, 462 + struct perf_event_attr *attr __maybe_unused) 463 + { 464 + struct branch_stack *br = sample->branch_stack; 465 + struct addr_location alf, alt; 466 + u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 467 + u64 i, from, to; 468 + 469 + if (!(br && br->nr)) 470 + return; 471 + 472 + for (i = 0; i < br->nr; i++) { 473 + 474 + memset(&alf, 0, sizeof(alf)); 475 + memset(&alt, 0, sizeof(alt)); 476 + from = br->entries[i].from; 477 + to = br->entries[i].to; 478 + 479 + thread__find_addr_map(thread, cpumode, MAP__FUNCTION, from, &alf); 480 + if (alf.map) 481 + alf.sym = map__find_symbol(alf.map, alf.addr, NULL); 482 + 483 + thread__find_addr_map(thread, cpumode, MAP__FUNCTION, to, &alt); 484 + if (alt.map) 485 + alt.sym = map__find_symbol(alt.map, alt.addr, NULL); 486 + 487 + symbol__fprintf_symname_offs(alf.sym, &alf, stdout); 488 + putchar('/'); 489 + symbol__fprintf_symname_offs(alt.sym, &alt, stdout); 490 + printf("/%c/%c/%c/%d ", 491 + mispred_str( br->entries + i), 492 + br->entries[i].flags.in_tx? 'X' : '-', 493 + br->entries[i].flags.abort? 'A' : '-', 494 + br->entries[i].flags.cycles); 495 + } 496 + } 497 + 498 + 432 499 static void print_sample_addr(union perf_event *event, 433 500 struct perf_sample *sample, 434 501 struct thread *thread, ··· 634 559 635 560 if (PRINT_FIELD(IREGS)) 636 561 print_sample_iregs(event, sample, thread, attr); 562 + 563 + if (PRINT_FIELD(BRSTACK)) 564 + print_sample_brstack(event, sample, thread, attr); 565 + else if (PRINT_FIELD(BRSTACKSYM)) 566 + print_sample_brstacksym(event, sample, thread, attr); 637 567 638 568 printf("\n"); 639 569 } ··· 1761 1681 "comma separated output fields prepend with 'type:'. " 1762 1682 "Valid types: hw,sw,trace,raw. " 1763 1683 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 1764 - "addr,symoff,period,iregs,flags", parse_output_fields), 1684 + "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields), 1765 1685 OPT_BOOLEAN('a', "all-cpus", &system_wide, 1766 1686 "system-wide collection from all CPUs"), 1767 1687 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",