Messages in this thread | | | Subject | Re: [PATCH V6 6/8] perf/tools: Extend branch type classification | From | German Gomez <> | Date | Tue, 14 Jun 2022 17:53:59 +0100 |
| |
Hi Anshuman,
On 10/06/2022 04:50, Anshuman Khandual wrote: > This updates the perf tool with generic branch type classification with new > ABI extender place holder i.e PERF_BR_EXTEND_ABI, the new 4 bit branch type > field i.e perf_branch_entry.new_type, new generic page fault related branch > types and some arch specific branch types as added earlier in the kernel. > > Cc: Peter Zijlstra <peterz@infradead.org> > Cc: Ingo Molnar <mingo@redhat.com> > Cc: Arnaldo Carvalho de Melo <acme@kernel.org> > Cc: Mark Rutland <mark.rutland@arm.com> > Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> > Cc: Jiri Olsa <jolsa@redhat.com> > Cc: Namhyung Kim <namhyung@kernel.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Cc: Will Deacon <will@kernel.org> > Cc: linux-arm-kernel@lists.infradead.org > Cc: linux-perf-users@vger.kernel.org > Cc: linux-kernel@vger.kernel.org > Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com> > --- > tools/include/uapi/linux/perf_event.h | 16 ++++++++- > tools/perf/builtin-script.c | 2 +- > tools/perf/util/branch.c | 52 ++++++++++++++++++++++++++- > tools/perf/util/branch.h | 6 +++- > tools/perf/util/session.c | 2 +- > 5 files changed, 73 insertions(+), 5 deletions(-) > > diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h > index 26d8f0b5ac0d..d29280adc3c4 100644 > --- a/tools/include/uapi/linux/perf_event.h > +++ b/tools/include/uapi/linux/perf_event.h > @@ -255,9 +255,22 @@ enum { > PERF_BR_IRQ = 12, /* irq */ > PERF_BR_SERROR = 13, /* system error */ > PERF_BR_NO_TX = 14, /* not in transaction */ > + PERF_BR_EXTEND_ABI = 15, /* extend ABI */ > PERF_BR_MAX, > }; > > +enum { > + PERF_BR_NEW_FAULT_ALGN = 0, /* Alignment fault */ > + PERF_BR_NEW_FAULT_DATA = 1, /* Data fault */ > + PERF_BR_NEW_FAULT_INST = 2, /* Inst fault */ > + PERF_BR_NEW_ARCH_1 = 3, /* Architecture specific */ > + PERF_BR_NEW_ARCH_2 = 4, /* Architecture specific */ > + PERF_BR_NEW_ARCH_3 = 5, /* Architecture specific */ > + PERF_BR_NEW_ARCH_4 = 6, /* Architecture specific */ > + PERF_BR_NEW_ARCH_5 = 7, /* Architecture specific */ > + PERF_BR_NEW_MAX, > +}; > + > #define PERF_SAMPLE_BRANCH_PLM_ALL \ > (PERF_SAMPLE_BRANCH_USER|\ > PERF_SAMPLE_BRANCH_KERNEL|\ > @@ -1372,7 +1385,8 @@ struct perf_branch_entry { > abort:1, /* transaction abort */ > cycles:16, /* cycle count to last branch */ > type:4, /* branch type */ > - reserved:40; > + new_type:4, /* additional branch type */ > + reserved:36; > }; > > union perf_sample_weight { > diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c > index c689054002cc..d4d581230f23 100644 > --- a/tools/perf/builtin-script.c > +++ b/tools/perf/builtin-script.c > @@ -866,7 +866,7 @@ static int print_bstack_flags(FILE *fp, struct branch_entry *br) > br->flags.in_tx ? 'X' : '-', > br->flags.abort ? 'A' : '-', > br->flags.cycles, > - br->flags.type ? branch_type_name(br->flags.type) : "-"); > + get_branch_type(br));
(Small comment below regarding this line)
> } > > static int perf_sample__fprintf_brstack(struct perf_sample *sample, > diff --git a/tools/perf/util/branch.c b/tools/perf/util/branch.c > index abc673347bee..6d962b0a4532 100644 > --- a/tools/perf/util/branch.c > +++ b/tools/perf/util/branch.c > @@ -21,7 +21,10 @@ void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags, > if (flags->type == PERF_BR_UNKNOWN || from == 0) > return; > > - st->counts[flags->type]++; > + if (flags->type == PERF_BR_EXTEND_ABI) > + st->new_counts[flags->new_type]++; > + else > + st->counts[flags->type]++; > > if (flags->type == PERF_BR_COND) { > if (to > from) > @@ -36,6 +39,25 @@ void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags, > st->cross_4k++; > } > > +const char *branch_new_type_name(int new_type) > +{ > + const char *branch_new_names[PERF_BR_NEW_MAX] = { > + "FAULT_ALGN", > + "FAULT_DATA", > + "FAULT_INST", > + "ARCH_1", > + "ARCH_2", > + "ARCH_3", > + "ARCH_4", > + "ARCH_5" > + }; > + > + if (new_type >= 0 && new_type < PERF_BR_NEW_MAX) > + return branch_new_names[new_type]; > + > + return NULL; > +} > + > const char *branch_type_name(int type) > { > const char *branch_names[PERF_BR_MAX] = { > @@ -62,6 +84,17 @@ const char *branch_type_name(int type) > return NULL; > } > > +const char *get_branch_type(struct branch_entry *e) > +{ > + if (e->flags.type == PERF_BR_UNKNOWN) > + return "";
There is a small change of behavior in "perf script --field brstack". Unknown branches were printed as "-" before but now it's an empty string.
> + > + if (e->flags.type == PERF_BR_EXTEND_ABI) > + return branch_new_type_name(e->flags.new_type); > + > + return branch_type_name(e->flags.type); > +} > + > void branch_type_stat_display(FILE *fp, struct branch_type_stat *st) > { > u64 total = 0; > @@ -108,6 +141,15 @@ void branch_type_stat_display(FILE *fp, struct branch_type_stat *st) > 100.0 * > (double)st->counts[i] / (double)total); > } > + > + for (i = 0; i < PERF_BR_NEW_MAX; i++) { > + if (st->new_counts[i] > 0) > + fprintf(fp, "\n%8s: %5.1f%%", > + branch_new_type_name(i), > + 100.0 * > + (double)st->new_counts[i] / (double)total); > + } > + > } > > static int count_str_scnprintf(int idx, const char *str, char *bf, int size) > @@ -123,6 +165,9 @@ int branch_type_str(struct branch_type_stat *st, char *bf, int size) > for (i = 0; i < PERF_BR_MAX; i++) > total += st->counts[i]; > > + for (i = 0; i < PERF_BR_NEW_MAX; i++) > + total += st->new_counts[i]; > + > if (total == 0) > return 0; > > @@ -140,6 +185,11 @@ int branch_type_str(struct branch_type_stat *st, char *bf, int size) > printed += count_str_scnprintf(j++, branch_type_name(i), bf + printed, size - printed); > } > > + for (i = 0; i < PERF_BR_NEW_MAX; i++) { > + if (st->new_counts[i] > 0) > + printed += count_str_scnprintf(j++, branch_new_type_name(i), bf + printed, size - printed); > + } > + > if (st->cross_4k > 0) > printed += count_str_scnprintf(j++, "CROSS_4K", bf + printed, size - printed); > > diff --git a/tools/perf/util/branch.h b/tools/perf/util/branch.h > index 17b2ccc61094..8d251b35428a 100644 > --- a/tools/perf/util/branch.h > +++ b/tools/perf/util/branch.h > @@ -24,7 +24,8 @@ struct branch_flags { > u64 abort:1; > u64 cycles:16; > u64 type:4; > - u64 reserved:40; > + u64 new_type:4; > + u64 reserved:36; > }; > }; > }; > @@ -72,6 +73,7 @@ static inline struct branch_entry *perf_sample__branch_entries(struct perf_sampl > struct branch_type_stat { > bool branch_to; > u64 counts[PERF_BR_MAX]; > + u64 new_counts[PERF_BR_NEW_MAX]; > u64 cond_fwd; > u64 cond_bwd; > u64 cross_4k; > @@ -82,6 +84,8 @@ void branch_type_count(struct branch_type_stat *st, struct branch_flags *flags, > u64 from, u64 to); > > const char *branch_type_name(int type); > +const char *branch_new_type_name(int new_type); > +const char *get_branch_type(struct branch_entry *e); > void branch_type_stat_display(FILE *fp, struct branch_type_stat *st); > int branch_type_str(struct branch_type_stat *st, char *bf, int bfsize); > > diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c > index 0aa818977d2b..136fa03364ab 100644 > --- a/tools/perf/util/session.c > +++ b/tools/perf/util/session.c > @@ -1178,7 +1178,7 @@ static void branch_stack__printf(struct perf_sample *sample, bool callstack) > e->flags.abort ? "A" : " ", > e->flags.in_tx ? "T" : " ", > (unsigned)e->flags.reserved, > - e->flags.type ? branch_type_name(e->flags.type) : ""); > + get_branch_type(e)); > } else { > if (i == 0) { > printf("..... %2"PRIu64": %016" PRIx64 "\n"
| |