From: Ravi Bangoria <ravi.bangoria@linux.ibm.com> To: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org Cc: eranian@google.com, peterz@infradead.org, mpe@ellerman.id.au, paulus@samba.org, mingo@redhat.com, acme@kernel.org, mark.rutland@arm.com, alexander.shishkin@linux.intel.com, jolsa@redhat.com, namhyung@kernel.org, adrian.hunter@intel.com, ak@linux.intel.com, kan.liang@linux.intel.com, alexey.budankov@linux.intel.com, yao.jin@linux.intel.com, robert.richter@amd.com, kim.phillips@amd.com, maddy@linux.ibm.com, ravi.bangoria@linux.ibm.com Subject: [RFC 11/11] perf annotate: Show hazard data in tui mode Date: Mon, 2 Mar 2020 10:53:55 +0530 [thread overview] Message-ID: <20200302052355.36365-12-ravi.bangoria@linux.ibm.com> (raw) In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com> Enable perf report->annotate tui mode to show hazard information. By default they are hidden, but user can unhide them by pressing hot key 'S'. Sample o/p: │ Disassembly of section .text: │ │ 0000000010001cf8 <compare>: │ compare(): │ return NULL; │ } │ │ static int │ compare(const void *p1, const void *p2) │ { 33.23 │ std r31,-8(r1) │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: Load Hit Store, stall_stage: LSU, stall_reason: -, icache: L3 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: -, stall_reason: -, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} 0.84 │ stdu r1,-64(r1) │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: -, stall_reason: -, icache: L1 hit} 0.24 │ mr r31,r1 │ {haz_stage: -, haz_reason: -, stall_stage: -, stall_reason: -, icache: L1 hit} 21.18 │ std r3,32(r31) │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> --- tools/perf/builtin-annotate.c | 5 ++ tools/perf/ui/browsers/annotate.c | 124 ++++++++++++++++++++++++++---- tools/perf/util/annotate.c | 51 +++++++++++- tools/perf/util/annotate.h | 18 ++++- 4 files changed, 178 insertions(+), 20 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 78552a9428a6..a51313a6b019 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -472,6 +472,7 @@ static const char * const annotate_usage[] = { int cmd_annotate(int argc, const char **argv) { + bool annotate_haz = false; struct perf_annotate annotate = { .tool = { .sample = process_sample_event, @@ -531,6 +532,8 @@ int cmd_annotate(int argc, const char **argv) symbol__config_symfs), OPT_BOOLEAN(0, "source", &annotate.opts.annotate_src, "Interleave source code with assembly code (default)"), + OPT_BOOLEAN(0, "hazard", &annotate_haz, + "Interleave CPU pileline hazard/stall data with assembly code"), OPT_BOOLEAN(0, "asm-raw", &annotate.opts.show_asm_raw, "Display raw encoding of assembly instructions (default)"), OPT_STRING('M', "disassembler-style", &annotate.opts.disassembler_style, "disassembler style", @@ -583,6 +586,8 @@ int cmd_annotate(int argc, const char **argv) if (annotate_check_args(&annotate.opts) < 0) return -EINVAL; + annotate.opts.hide_haz_data = !annotate_haz; + if (symbol_conf.show_nr_samples && annotate.use_gtk) { pr_err("--show-nr-samples is not available in --gtk mode at this time\n"); return ret; diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 2e4db8216b3b..b04d825cee50 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -190,9 +190,15 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) return; } - if (notes->options->hide_src_code) { + if (notes->options->hide_src_code && notes->options->hide_haz_data) { from = cursor->al.idx_asm; to = target->idx_asm; + } else if (!notes->options->hide_src_code && notes->options->hide_haz_data) { + from = cursor->al.idx_asm + cursor->al.idx_src + 1; + to = target->idx_asm + target->idx_src + 1; + } else if (notes->options->hide_src_code && !notes->options->hide_haz_data) { + from = cursor->al.idx_asm + cursor->al.idx_haz + 1; + to = target->idx_asm + target->idx_haz + 1; } else { from = (u64)cursor->al.idx; to = (u64)target->idx; @@ -293,8 +299,13 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser, struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node); u32 idx = pos->idx; - if (notes->options->hide_src_code) + if (notes->options->hide_src_code && notes->options->hide_haz_data) idx = pos->idx_asm; + else if (!notes->options->hide_src_code && notes->options->hide_haz_data) + idx = pos->idx_asm + pos->idx_src + 1; + else if (notes->options->hide_src_code && !notes->options->hide_haz_data) + idx = pos->idx_asm + pos->idx_haz + 1; + annotate_browser__set_top(browser, pos, idx); browser->curr_hot = nd; } @@ -348,44 +359,117 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser) struct annotation *notes = browser__annotation(&browser->b); struct annotation_line *al; off_t offset = browser->b.index - browser->b.top_idx; + u32 curr_idx; browser->b.seek(&browser->b, offset, SEEK_CUR); al = list_entry(browser->b.top, struct annotation_line, node); if (notes->options->hide_src_code) { - if (al->idx_asm < offset) - offset = al->idx; + if (notes->options->hide_haz_data) { + curr_idx = al->idx_asm + al->idx_src + 1; + browser->b.nr_entries = notes->nr_asm_entries + + notes->nr_src_entries; + } else { + curr_idx = al->idx; + browser->b.nr_entries = notes->nr_entries; + } - browser->b.nr_entries = notes->nr_entries; notes->options->hide_src_code = false; browser->b.seek(&browser->b, -offset, SEEK_CUR); - browser->b.top_idx = al->idx - offset; - browser->b.index = al->idx; + browser->b.top_idx = curr_idx - offset; + browser->b.index = curr_idx; } else { - if (al->idx_asm < 0) { + if (al->type != AL_TYPE_ASM) { ui_helpline__puts("Only available for assembly lines."); browser->b.seek(&browser->b, -offset, SEEK_CUR); return false; } - if (al->idx_asm < offset) - offset = al->idx_asm; + if (notes->options->hide_haz_data) { + curr_idx = al->idx_asm; + browser->b.nr_entries = notes->nr_asm_entries; + } else { + curr_idx = al->idx_asm + al->idx_haz + 1; + browser->b.nr_entries = notes->nr_asm_entries + + notes->nr_haz_entries; + } + + if (curr_idx < offset) + offset = curr_idx; - browser->b.nr_entries = notes->nr_asm_entries; notes->options->hide_src_code = true; browser->b.seek(&browser->b, -offset, SEEK_CUR); - browser->b.top_idx = al->idx_asm - offset; - browser->b.index = al->idx_asm; + browser->b.top_idx = curr_idx - offset; + browser->b.index = curr_idx; + } + + return true; +} + +static bool annotate_browser__toggle_hazard(struct annotate_browser *browser) +{ + struct annotation *notes = browser__annotation(&browser->b); + struct annotation_line *al; + off_t offset = browser->b.index - browser->b.top_idx; + u32 curr_idx; + + browser->b.seek(&browser->b, offset, SEEK_CUR); + al = list_entry(browser->b.top, struct annotation_line, node); + + if (notes->options->hide_haz_data) { + if (notes->options->hide_src_code) { + curr_idx = al->idx_asm + al->idx_haz + 1; + browser->b.nr_entries = notes->nr_asm_entries + + notes->nr_haz_entries; + } else { + curr_idx = al->idx; + browser->b.nr_entries = notes->nr_entries; + } + + notes->options->hide_haz_data = false; + browser->b.seek(&browser->b, -offset, SEEK_CUR); + browser->b.top_idx = curr_idx - offset; + browser->b.index = curr_idx; + } else { + if (al->type != AL_TYPE_ASM) { + ui_helpline__puts("Only available for assembly lines."); + browser->b.seek(&browser->b, -offset, SEEK_CUR); + return false; + } + + if (notes->options->hide_src_code) { + curr_idx = al->idx_asm; + browser->b.nr_entries = notes->nr_asm_entries; + } else { + curr_idx = al->idx_asm + al->idx_src + 1; + browser->b.nr_entries = notes->nr_asm_entries + + notes->nr_src_entries; + } + + if (curr_idx < offset) + offset = curr_idx; + + notes->options->hide_haz_data = true; + browser->b.seek(&browser->b, -offset, SEEK_CUR); + browser->b.top_idx = curr_idx - offset; + browser->b.index = curr_idx; } return true; } -static void ui_browser__init_asm_mode(struct ui_browser *browser) +static void ui_browser__hide_src_code(struct ui_browser *browser) +{ + struct annotation *notes = browser__annotation(browser); + ui_browser__reset_index(browser); + browser->nr_entries -= notes->nr_src_entries; +} + +static void ui_browser__hide_haz_data(struct ui_browser *browser) { struct annotation *notes = browser__annotation(browser); ui_browser__reset_index(browser); - browser->nr_entries = notes->nr_asm_entries; + browser->nr_entries -= notes->nr_haz_entries; } #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) @@ -743,6 +827,7 @@ static int annotate_browser__run(struct annotate_browser *browser, "o Toggle disassembler output/simplified view\n" "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n" "s Toggle source code view\n" + "S Toggle pipeline hazard/stall view\n" "t Circulate percent, total period, samples view\n" "c Show min/max cycle\n" "/ Search string\n" @@ -767,6 +852,10 @@ static int annotate_browser__run(struct annotate_browser *browser, if (annotate_browser__toggle_source(browser)) ui_helpline__puts(help); continue; + case 'S': + if (annotate_browser__toggle_hazard(browser)) + ui_helpline__puts(help); + continue; case 'o': notes->options->use_offset = !notes->options->use_offset; annotation__update_column_widths(notes); @@ -932,7 +1021,10 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, browser.b.width += 18; /* Percentage */ if (notes->options->hide_src_code) - ui_browser__init_asm_mode(&browser.b); + ui_browser__hide_src_code(&browser.b); + + if (notes->options->hide_haz_data) + ui_browser__hide_haz_data(&browser.b); ret = annotate_browser__run(&browser, evsel, hbt); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 766934b0f36d..d782ee193345 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -66,6 +66,7 @@ struct annotation_options annotation__default_options = { .annotate_src = true, .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS, .percent_type = PERCENT_PERIOD_LOCAL, + .hide_haz_data = true, }; static regex_t file_lineno; @@ -1268,7 +1269,7 @@ static struct disasm_line *disasm_line__new(struct annotate_args *args) struct disasm_line *dl = NULL; int nr = 1; - if (perf_evsel__is_group_event(args->evsel)) + if (args->type != AL_TYPE_HAZ && perf_evsel__is_group_event(args->evsel)) nr = args->evsel->core.nr_members; dl = zalloc(disasm_line_size(nr)); @@ -1509,6 +1510,7 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start } else if (max_lines && printed >= max_lines) return 1; else { + /* TODO: Hazard specific changes */ int width = symbol_conf.show_total_period ? 12 : 8; if (queue) @@ -1526,6 +1528,34 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start return 0; } +static int annotation_add_hazard_detail(struct annotation *notes, s64 offset) +{ + int ret; + struct hazard_hist *hh; + struct disasm_line *dl; + struct annotate_args args = { + .type = AL_TYPE_HAZ, + .offset = -1, + }; + + list_for_each_entry(hh, ¬es->src->haz_hist[offset].list, list) { + ret = asprintf(&(args.line), " {haz_stage: %s, " + "haz_reason: %s, stall_stage: %s, stall_reason: %s, " + "icache: %s}", hh->haz_stage, hh->haz_reason, + hh->stall_stage, hh->stall_reason, hh->icache); + if (ret == -1) + return -ENOMEM; + + dl = disasm_line__new(&args); + free(args.line); + if (!dl) + return -ENOMEM; + + annotation_line__add(&dl->al, ¬es->src->source); + } + return 0; +} + /* * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw) * which looks like following @@ -1608,6 +1638,10 @@ static int symbol__parse_objdump_line(struct symbol *sym, annotation_line__add(&dl->al, ¬es->src->source); + if (offset != -1 && notes->src->haz_hist && + !list_empty(¬es->src->haz_hist[offset].list)) + return annotation_add_hazard_detail(notes, offset); + return 0; } @@ -2701,6 +2735,8 @@ static void annotation__set_offsets(struct annotation *notes, s64 size) notes->max_line_len = 0; notes->nr_entries = 0; notes->nr_asm_entries = 0; + notes->nr_src_entries = 0; + notes->nr_haz_entries = 0; list_for_each_entry(al, ¬es->src->source, node) { size_t line_len = strlen(al->line); @@ -2710,6 +2746,8 @@ static void annotation__set_offsets(struct annotation *notes, s64 size) al->idx = notes->nr_entries++; if (al->type == AL_TYPE_ASM) { al->idx_asm = notes->nr_asm_entries++; + al->idx_src = notes->nr_src_entries - 1; + al->idx_haz = notes->nr_haz_entries - 1; /* * FIXME: short term bandaid to cope with assembly * routines that comes with labels in the same column @@ -2719,8 +2757,15 @@ static void annotation__set_offsets(struct annotation *notes, s64 size) */ if (al->offset < size) notes->offsets[al->offset] = al; - } else + } else if (al->type == AL_TYPE_SRC) { al->idx_asm = -1; + al->idx_src = notes->nr_src_entries++; + al->idx_haz = notes->nr_haz_entries - 1; + } else if (al->type == AL_TYPE_HAZ) { + al->idx_asm = -1; + al->idx_haz = notes->nr_haz_entries++; + al->idx_src = notes->nr_src_entries - 1; + } } } @@ -3051,6 +3096,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati printed = scnprintf(bf, sizeof(bf), "%-*s ", notes->widths.addr, " "); obj__printf(obj, bf); obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line); + } else if (al->type == AL_TYPE_HAZ) { + obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, al->line); } else { u64 addr = al->offset; int color = -1; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index a3803f89b8fc..3a082c13bdad 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -85,7 +85,8 @@ struct annotation_options { show_nr_jumps, show_minmax_cycle, show_asm_raw, - annotate_src; + annotate_src, + hide_haz_data; u8 offset_level; int min_pcnt; int max_lines; @@ -131,8 +132,16 @@ struct annotation_data { enum annotation_line_type { AL_TYPE_ASM = 0, AL_TYPE_SRC, + AL_TYPE_HAZ, }; +/* + * @idx_asm, @idx_src and @idx_haz starts from -1 and increments in + * chronological order. For _all_ non-assembly lines, @idx_asm is -1. + * OTOH, for non-source line, @idx_src contains prev value. Similarly + * for non-hazard lines @idx_haz also contains prev value. + * And @idx = @idx_asm + (@idx_src + 1) + (@idx_haz + 1); + */ struct annotation_line { struct list_head node; struct rb_node rb_node; @@ -148,6 +157,8 @@ struct annotation_line { char *path; u32 idx; int idx_asm; + int idx_src; + int idx_haz; int data_nr; struct annotation_data data[0]; }; @@ -298,6 +309,8 @@ struct annotation { int max_jump_sources; int nr_entries; int nr_asm_entries; + int nr_src_entries; + int nr_haz_entries; u16 max_line_len; struct { u8 addr; @@ -326,7 +339,8 @@ static inline int annotation__pcnt_width(struct annotation *notes) static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes) { - return notes->options->hide_src_code && al->type == AL_TYPE_SRC; + return ((notes->options->hide_src_code && al->type == AL_TYPE_SRC) || + (notes->options->hide_haz_data && al->type == AL_TYPE_HAZ)); } void annotation__update_column_widths(struct annotation *notes); -- 2.21.1
WARNING: multiple messages have this Message-ID (diff)
From: Ravi Bangoria <ravi.bangoria@linux.ibm.com> To: linuxppc-dev@lists.ozlabs.org, linux-kernel@vger.kernel.org Cc: mark.rutland@arm.com, ravi.bangoria@linux.ibm.com, ak@linux.intel.com, maddy@linux.ibm.com, peterz@infradead.org, alexey.budankov@linux.intel.com, adrian.hunter@intel.com, acme@kernel.org, alexander.shishkin@linux.intel.com, yao.jin@linux.intel.com, mingo@redhat.com, paulus@samba.org, eranian@google.com, robert.richter@amd.com, namhyung@kernel.org, kim.phillips@amd.com, jolsa@redhat.com, kan.liang@linux.intel.com Subject: [RFC 11/11] perf annotate: Show hazard data in tui mode Date: Mon, 2 Mar 2020 10:53:55 +0530 [thread overview] Message-ID: <20200302052355.36365-12-ravi.bangoria@linux.ibm.com> (raw) In-Reply-To: <20200302052355.36365-1-ravi.bangoria@linux.ibm.com> Enable perf report->annotate tui mode to show hazard information. By default they are hidden, but user can unhide them by pressing hot key 'S'. Sample o/p: │ Disassembly of section .text: │ │ 0000000010001cf8 <compare>: │ compare(): │ return NULL; │ } │ │ static int │ compare(const void *p1, const void *p2) │ { 33.23 │ std r31,-8(r1) │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: Load Hit Store, stall_stage: LSU, stall_reason: -, icache: L3 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: -, stall_reason: -, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} 0.84 │ stdu r1,-64(r1) │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: -, stall_reason: -, icache: L1 hit} 0.24 │ mr r31,r1 │ {haz_stage: -, haz_reason: -, stall_stage: -, stall_reason: -, icache: L1 hit} 21.18 │ std r3,32(r31) │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} │ {haz_stage: LSU, haz_reason: ERAT Miss, stall_stage: LSU, stall_reason: Store, icache: L1 hit} Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.ibm.com> --- tools/perf/builtin-annotate.c | 5 ++ tools/perf/ui/browsers/annotate.c | 124 ++++++++++++++++++++++++++---- tools/perf/util/annotate.c | 51 +++++++++++- tools/perf/util/annotate.h | 18 ++++- 4 files changed, 178 insertions(+), 20 deletions(-) diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 78552a9428a6..a51313a6b019 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c @@ -472,6 +472,7 @@ static const char * const annotate_usage[] = { int cmd_annotate(int argc, const char **argv) { + bool annotate_haz = false; struct perf_annotate annotate = { .tool = { .sample = process_sample_event, @@ -531,6 +532,8 @@ int cmd_annotate(int argc, const char **argv) symbol__config_symfs), OPT_BOOLEAN(0, "source", &annotate.opts.annotate_src, "Interleave source code with assembly code (default)"), + OPT_BOOLEAN(0, "hazard", &annotate_haz, + "Interleave CPU pileline hazard/stall data with assembly code"), OPT_BOOLEAN(0, "asm-raw", &annotate.opts.show_asm_raw, "Display raw encoding of assembly instructions (default)"), OPT_STRING('M', "disassembler-style", &annotate.opts.disassembler_style, "disassembler style", @@ -583,6 +586,8 @@ int cmd_annotate(int argc, const char **argv) if (annotate_check_args(&annotate.opts) < 0) return -EINVAL; + annotate.opts.hide_haz_data = !annotate_haz; + if (symbol_conf.show_nr_samples && annotate.use_gtk) { pr_err("--show-nr-samples is not available in --gtk mode at this time\n"); return ret; diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c index 2e4db8216b3b..b04d825cee50 100644 --- a/tools/perf/ui/browsers/annotate.c +++ b/tools/perf/ui/browsers/annotate.c @@ -190,9 +190,15 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser) return; } - if (notes->options->hide_src_code) { + if (notes->options->hide_src_code && notes->options->hide_haz_data) { from = cursor->al.idx_asm; to = target->idx_asm; + } else if (!notes->options->hide_src_code && notes->options->hide_haz_data) { + from = cursor->al.idx_asm + cursor->al.idx_src + 1; + to = target->idx_asm + target->idx_src + 1; + } else if (notes->options->hide_src_code && !notes->options->hide_haz_data) { + from = cursor->al.idx_asm + cursor->al.idx_haz + 1; + to = target->idx_asm + target->idx_haz + 1; } else { from = (u64)cursor->al.idx; to = (u64)target->idx; @@ -293,8 +299,13 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser, struct annotation_line * pos = rb_entry(nd, struct annotation_line, rb_node); u32 idx = pos->idx; - if (notes->options->hide_src_code) + if (notes->options->hide_src_code && notes->options->hide_haz_data) idx = pos->idx_asm; + else if (!notes->options->hide_src_code && notes->options->hide_haz_data) + idx = pos->idx_asm + pos->idx_src + 1; + else if (notes->options->hide_src_code && !notes->options->hide_haz_data) + idx = pos->idx_asm + pos->idx_haz + 1; + annotate_browser__set_top(browser, pos, idx); browser->curr_hot = nd; } @@ -348,44 +359,117 @@ static bool annotate_browser__toggle_source(struct annotate_browser *browser) struct annotation *notes = browser__annotation(&browser->b); struct annotation_line *al; off_t offset = browser->b.index - browser->b.top_idx; + u32 curr_idx; browser->b.seek(&browser->b, offset, SEEK_CUR); al = list_entry(browser->b.top, struct annotation_line, node); if (notes->options->hide_src_code) { - if (al->idx_asm < offset) - offset = al->idx; + if (notes->options->hide_haz_data) { + curr_idx = al->idx_asm + al->idx_src + 1; + browser->b.nr_entries = notes->nr_asm_entries + + notes->nr_src_entries; + } else { + curr_idx = al->idx; + browser->b.nr_entries = notes->nr_entries; + } - browser->b.nr_entries = notes->nr_entries; notes->options->hide_src_code = false; browser->b.seek(&browser->b, -offset, SEEK_CUR); - browser->b.top_idx = al->idx - offset; - browser->b.index = al->idx; + browser->b.top_idx = curr_idx - offset; + browser->b.index = curr_idx; } else { - if (al->idx_asm < 0) { + if (al->type != AL_TYPE_ASM) { ui_helpline__puts("Only available for assembly lines."); browser->b.seek(&browser->b, -offset, SEEK_CUR); return false; } - if (al->idx_asm < offset) - offset = al->idx_asm; + if (notes->options->hide_haz_data) { + curr_idx = al->idx_asm; + browser->b.nr_entries = notes->nr_asm_entries; + } else { + curr_idx = al->idx_asm + al->idx_haz + 1; + browser->b.nr_entries = notes->nr_asm_entries + + notes->nr_haz_entries; + } + + if (curr_idx < offset) + offset = curr_idx; - browser->b.nr_entries = notes->nr_asm_entries; notes->options->hide_src_code = true; browser->b.seek(&browser->b, -offset, SEEK_CUR); - browser->b.top_idx = al->idx_asm - offset; - browser->b.index = al->idx_asm; + browser->b.top_idx = curr_idx - offset; + browser->b.index = curr_idx; + } + + return true; +} + +static bool annotate_browser__toggle_hazard(struct annotate_browser *browser) +{ + struct annotation *notes = browser__annotation(&browser->b); + struct annotation_line *al; + off_t offset = browser->b.index - browser->b.top_idx; + u32 curr_idx; + + browser->b.seek(&browser->b, offset, SEEK_CUR); + al = list_entry(browser->b.top, struct annotation_line, node); + + if (notes->options->hide_haz_data) { + if (notes->options->hide_src_code) { + curr_idx = al->idx_asm + al->idx_haz + 1; + browser->b.nr_entries = notes->nr_asm_entries + + notes->nr_haz_entries; + } else { + curr_idx = al->idx; + browser->b.nr_entries = notes->nr_entries; + } + + notes->options->hide_haz_data = false; + browser->b.seek(&browser->b, -offset, SEEK_CUR); + browser->b.top_idx = curr_idx - offset; + browser->b.index = curr_idx; + } else { + if (al->type != AL_TYPE_ASM) { + ui_helpline__puts("Only available for assembly lines."); + browser->b.seek(&browser->b, -offset, SEEK_CUR); + return false; + } + + if (notes->options->hide_src_code) { + curr_idx = al->idx_asm; + browser->b.nr_entries = notes->nr_asm_entries; + } else { + curr_idx = al->idx_asm + al->idx_src + 1; + browser->b.nr_entries = notes->nr_asm_entries + + notes->nr_src_entries; + } + + if (curr_idx < offset) + offset = curr_idx; + + notes->options->hide_haz_data = true; + browser->b.seek(&browser->b, -offset, SEEK_CUR); + browser->b.top_idx = curr_idx - offset; + browser->b.index = curr_idx; } return true; } -static void ui_browser__init_asm_mode(struct ui_browser *browser) +static void ui_browser__hide_src_code(struct ui_browser *browser) +{ + struct annotation *notes = browser__annotation(browser); + ui_browser__reset_index(browser); + browser->nr_entries -= notes->nr_src_entries; +} + +static void ui_browser__hide_haz_data(struct ui_browser *browser) { struct annotation *notes = browser__annotation(browser); ui_browser__reset_index(browser); - browser->nr_entries = notes->nr_asm_entries; + browser->nr_entries -= notes->nr_haz_entries; } #define SYM_TITLE_MAX_SIZE (PATH_MAX + 64) @@ -743,6 +827,7 @@ static int annotate_browser__run(struct annotate_browser *browser, "o Toggle disassembler output/simplified view\n" "O Bump offset level (jump targets -> +call -> all -> cycle thru)\n" "s Toggle source code view\n" + "S Toggle pipeline hazard/stall view\n" "t Circulate percent, total period, samples view\n" "c Show min/max cycle\n" "/ Search string\n" @@ -767,6 +852,10 @@ static int annotate_browser__run(struct annotate_browser *browser, if (annotate_browser__toggle_source(browser)) ui_helpline__puts(help); continue; + case 'S': + if (annotate_browser__toggle_hazard(browser)) + ui_helpline__puts(help); + continue; case 'o': notes->options->use_offset = !notes->options->use_offset; annotation__update_column_widths(notes); @@ -932,7 +1021,10 @@ int symbol__tui_annotate(struct map_symbol *ms, struct evsel *evsel, browser.b.width += 18; /* Percentage */ if (notes->options->hide_src_code) - ui_browser__init_asm_mode(&browser.b); + ui_browser__hide_src_code(&browser.b); + + if (notes->options->hide_haz_data) + ui_browser__hide_haz_data(&browser.b); ret = annotate_browser__run(&browser, evsel, hbt); diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c index 766934b0f36d..d782ee193345 100644 --- a/tools/perf/util/annotate.c +++ b/tools/perf/util/annotate.c @@ -66,6 +66,7 @@ struct annotation_options annotation__default_options = { .annotate_src = true, .offset_level = ANNOTATION__OFFSET_JUMP_TARGETS, .percent_type = PERCENT_PERIOD_LOCAL, + .hide_haz_data = true, }; static regex_t file_lineno; @@ -1268,7 +1269,7 @@ static struct disasm_line *disasm_line__new(struct annotate_args *args) struct disasm_line *dl = NULL; int nr = 1; - if (perf_evsel__is_group_event(args->evsel)) + if (args->type != AL_TYPE_HAZ && perf_evsel__is_group_event(args->evsel)) nr = args->evsel->core.nr_members; dl = zalloc(disasm_line_size(nr)); @@ -1509,6 +1510,7 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start } else if (max_lines && printed >= max_lines) return 1; else { + /* TODO: Hazard specific changes */ int width = symbol_conf.show_total_period ? 12 : 8; if (queue) @@ -1526,6 +1528,34 @@ annotation_line__print(struct annotation_line *al, struct symbol *sym, u64 start return 0; } +static int annotation_add_hazard_detail(struct annotation *notes, s64 offset) +{ + int ret; + struct hazard_hist *hh; + struct disasm_line *dl; + struct annotate_args args = { + .type = AL_TYPE_HAZ, + .offset = -1, + }; + + list_for_each_entry(hh, ¬es->src->haz_hist[offset].list, list) { + ret = asprintf(&(args.line), " {haz_stage: %s, " + "haz_reason: %s, stall_stage: %s, stall_reason: %s, " + "icache: %s}", hh->haz_stage, hh->haz_reason, + hh->stall_stage, hh->stall_reason, hh->icache); + if (ret == -1) + return -ENOMEM; + + dl = disasm_line__new(&args); + free(args.line); + if (!dl) + return -ENOMEM; + + annotation_line__add(&dl->al, ¬es->src->source); + } + return 0; +} + /* * symbol__parse_objdump_line() parses objdump output (with -d --no-show-raw) * which looks like following @@ -1608,6 +1638,10 @@ static int symbol__parse_objdump_line(struct symbol *sym, annotation_line__add(&dl->al, ¬es->src->source); + if (offset != -1 && notes->src->haz_hist && + !list_empty(¬es->src->haz_hist[offset].list)) + return annotation_add_hazard_detail(notes, offset); + return 0; } @@ -2701,6 +2735,8 @@ static void annotation__set_offsets(struct annotation *notes, s64 size) notes->max_line_len = 0; notes->nr_entries = 0; notes->nr_asm_entries = 0; + notes->nr_src_entries = 0; + notes->nr_haz_entries = 0; list_for_each_entry(al, ¬es->src->source, node) { size_t line_len = strlen(al->line); @@ -2710,6 +2746,8 @@ static void annotation__set_offsets(struct annotation *notes, s64 size) al->idx = notes->nr_entries++; if (al->type == AL_TYPE_ASM) { al->idx_asm = notes->nr_asm_entries++; + al->idx_src = notes->nr_src_entries - 1; + al->idx_haz = notes->nr_haz_entries - 1; /* * FIXME: short term bandaid to cope with assembly * routines that comes with labels in the same column @@ -2719,8 +2757,15 @@ static void annotation__set_offsets(struct annotation *notes, s64 size) */ if (al->offset < size) notes->offsets[al->offset] = al; - } else + } else if (al->type == AL_TYPE_SRC) { al->idx_asm = -1; + al->idx_src = notes->nr_src_entries++; + al->idx_haz = notes->nr_haz_entries - 1; + } else if (al->type == AL_TYPE_HAZ) { + al->idx_asm = -1; + al->idx_haz = notes->nr_haz_entries++; + al->idx_src = notes->nr_src_entries - 1; + } } } @@ -3051,6 +3096,8 @@ static void __annotation_line__write(struct annotation_line *al, struct annotati printed = scnprintf(bf, sizeof(bf), "%-*s ", notes->widths.addr, " "); obj__printf(obj, bf); obj__printf(obj, "%-*s", width - printed - pcnt_width - cycles_width + 1, al->line); + } else if (al->type == AL_TYPE_HAZ) { + obj__printf(obj, "%-*s", width - pcnt_width - cycles_width, al->line); } else { u64 addr = al->offset; int color = -1; diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h index a3803f89b8fc..3a082c13bdad 100644 --- a/tools/perf/util/annotate.h +++ b/tools/perf/util/annotate.h @@ -85,7 +85,8 @@ struct annotation_options { show_nr_jumps, show_minmax_cycle, show_asm_raw, - annotate_src; + annotate_src, + hide_haz_data; u8 offset_level; int min_pcnt; int max_lines; @@ -131,8 +132,16 @@ struct annotation_data { enum annotation_line_type { AL_TYPE_ASM = 0, AL_TYPE_SRC, + AL_TYPE_HAZ, }; +/* + * @idx_asm, @idx_src and @idx_haz starts from -1 and increments in + * chronological order. For _all_ non-assembly lines, @idx_asm is -1. + * OTOH, for non-source line, @idx_src contains prev value. Similarly + * for non-hazard lines @idx_haz also contains prev value. + * And @idx = @idx_asm + (@idx_src + 1) + (@idx_haz + 1); + */ struct annotation_line { struct list_head node; struct rb_node rb_node; @@ -148,6 +157,8 @@ struct annotation_line { char *path; u32 idx; int idx_asm; + int idx_src; + int idx_haz; int data_nr; struct annotation_data data[0]; }; @@ -298,6 +309,8 @@ struct annotation { int max_jump_sources; int nr_entries; int nr_asm_entries; + int nr_src_entries; + int nr_haz_entries; u16 max_line_len; struct { u8 addr; @@ -326,7 +339,8 @@ static inline int annotation__pcnt_width(struct annotation *notes) static inline bool annotation_line__filter(struct annotation_line *al, struct annotation *notes) { - return notes->options->hide_src_code && al->type == AL_TYPE_SRC; + return ((notes->options->hide_src_code && al->type == AL_TYPE_SRC) || + (notes->options->hide_haz_data && al->type == AL_TYPE_HAZ)); } void annotation__update_column_widths(struct annotation *notes); -- 2.21.1
next prev parent reply other threads:[~2020-03-02 5:25 UTC|newest] Thread overview: 73+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-03-02 5:23 [RFC 00/11] perf: Enhancing perf to export processor hazard information Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 01/11] powerpc/perf: Simplify ISA207_SIER macros Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 02/11] perf/core: Data structure to present hazard data Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 9:55 ` Peter Zijlstra 2020-03-02 9:55 ` Peter Zijlstra 2020-03-02 14:23 ` maddy 2020-03-02 14:23 ` maddy 2020-03-02 14:48 ` Mark Rutland 2020-03-02 14:48 ` Mark Rutland 2020-03-03 14:32 ` Ravi Bangoria 2020-03-03 14:32 ` Ravi Bangoria 2020-03-02 14:54 ` Mark Rutland 2020-03-02 14:54 ` Mark Rutland 2020-03-03 14:31 ` Ravi Bangoria 2020-03-03 14:31 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 03/11] powerpc/perf: Arch specific definitions for pipeline Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 04/11] powerpc/perf: Arch support to expose Hazard data Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 05/11] perf tools: Enable record and script to record and show hazard data Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 06/11] perf hists: Make a room for hazard info in struct hist_entry Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 07/11] perf hazard: Functions to convert generic hazard data to arch specific string Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 08/11] perf report: Enable hazard mode Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 09/11] perf annotate: Introduce type for annotation_line Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` [RFC 10/11] perf annotate: Preparation for hazard Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria 2020-03-02 5:23 ` Ravi Bangoria [this message] 2020-03-02 5:23 ` [RFC 11/11] perf annotate: Show hazard data in tui mode Ravi Bangoria 2020-03-02 10:13 ` [RFC 00/11] perf: Enhancing perf to export processor hazard information Peter Zijlstra 2020-03-02 10:13 ` Peter Zijlstra 2020-03-02 20:21 ` Stephane Eranian 2020-03-02 20:21 ` Stephane Eranian 2020-03-02 22:25 ` Kim Phillips 2020-03-02 22:25 ` Kim Phillips 2020-03-05 4:46 ` Ravi Bangoria 2020-03-05 4:46 ` Ravi Bangoria 2020-03-05 22:06 ` Kim Phillips 2020-03-05 22:06 ` Kim Phillips 2020-03-11 16:00 ` Ravi Bangoria 2020-03-12 22:38 ` Kim Phillips 2020-03-12 22:38 ` Kim Phillips 2020-03-17 6:50 ` maddy 2020-03-17 6:50 ` maddy 2020-03-18 17:35 ` Kim Phillips 2020-03-18 17:35 ` Kim Phillips 2020-03-19 11:22 ` Michael Ellerman 2020-03-19 11:22 ` Michael Ellerman 2020-03-26 10:19 ` maddy 2020-03-26 10:19 ` maddy 2020-03-26 19:48 ` Kim Phillips 2020-03-26 19:48 ` Kim Phillips 2020-04-20 7:09 ` Madhavan Srinivasan 2020-04-20 7:09 ` Madhavan Srinivasan 2020-04-27 7:18 ` Madhavan Srinivasan 2020-04-27 7:18 ` Madhavan Srinivasan 2020-03-05 4:28 ` maddy 2020-03-05 4:28 ` maddy 2020-03-03 1:33 ` Andi Kleen 2020-03-03 1:33 ` Andi Kleen 2020-03-05 5:06 ` Ravi Bangoria 2020-03-05 5:06 ` Ravi Bangoria 2020-03-02 21:08 ` Paul Clarke 2020-03-02 21:08 ` Paul Clarke 2020-03-05 5:06 ` Ravi Bangoria 2020-03-05 5:06 ` Ravi Bangoria
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200302052355.36365-12-ravi.bangoria@linux.ibm.com \ --to=ravi.bangoria@linux.ibm.com \ --cc=acme@kernel.org \ --cc=adrian.hunter@intel.com \ --cc=ak@linux.intel.com \ --cc=alexander.shishkin@linux.intel.com \ --cc=alexey.budankov@linux.intel.com \ --cc=eranian@google.com \ --cc=jolsa@redhat.com \ --cc=kan.liang@linux.intel.com \ --cc=kim.phillips@amd.com \ --cc=linux-kernel@vger.kernel.org \ --cc=linuxppc-dev@lists.ozlabs.org \ --cc=maddy@linux.ibm.com \ --cc=mark.rutland@arm.com \ --cc=mingo@redhat.com \ --cc=mpe@ellerman.id.au \ --cc=namhyung@kernel.org \ --cc=paulus@samba.org \ --cc=peterz@infradead.org \ --cc=robert.richter@amd.com \ --cc=yao.jin@linux.intel.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.