perf branch: Extend branch type classification

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.

Committer note:

Add an extra entry to the branch_type_name array to cope with
PERF_BR_EXTEND_ABI, to address build warnings on some compiler/systems,
like:

  75     8.89 ubuntu:20.04-x-powerpc64el    : FAIL gcc version 10.3.0 (Ubuntu 10.3.0-1ubuntu1~20.04)
        inlined from 'branch_type_stat_display' at util/branch.c:152:4:
    /usr/powerpc64le-linux-gnu/include/bits/stdio2.h:100:10: error: '%8s' directive argument is null [-Werror=format-overflow=]
      100 |   return __fprintf_chk (__stream, __USE_FORTIFY_LEVEL - 1, __fmt,
          |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      101 |    __va_arg_pack ());
          |    ~~~~~~~~~~~~~~~~~

Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20220824044822.70230-7-anshuman.khandual@arm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Anshuman Khandual
2022-08-24 10:18:20 +05:30
committed by Arnaldo Carvalho de Melo
parent 1c96b6e45f
commit 0ddea8e2a0
5 changed files with 75 additions and 6 deletions

View File

@@ -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] = {
@@ -53,7 +75,8 @@ const char *branch_type_name(int type)
"ERET",
"IRQ",
"SERROR",
"NO_TX"
"NO_TX",
"", // Needed for PERF_BR_EXTEND_ABI that ends up triggering some compiler warnings about NULL deref
};
if (type >= 0 && type < PERF_BR_MAX)
@@ -62,6 +85,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 "";
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 +142,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 +166,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 +186,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);