Skip to content

Commit edf3ce0

Browse files
Kan Liangacmel
authored andcommitted
perf env: Find correct branch counter info on hybrid
No event is printed in the "Branch Counter" column on hybrid machines. For example, $ perf record -e "{cpu_core/branch-instructions/pp,cpu_core/branches/}:S" -j any,counter $ perf report --total-cycles # Branch counter abbr list: # cpu_core/branch-instructions/pp = A # cpu_core/branches/ = B # '-' No event occurs # '+' Event occurrences may be lost due to branch counter saturated # # Sampled Cycles% Sampled Cycles Avg Cycles% Avg Cycles Branch Counter # ............... .............. ........... .......... .............. 44.54% 727.1K 0.00% 1 |+ |+ | 36.31% 592.7K 0.00% 2 |+ |+ | 17.83% 291.1K 0.00% 1 |+ |+ | The branch counter information (br_cntr_width and br_cntr_nr) in the perf_env is retrieved from the CPU_PMU_CAPS. However, the CPU_PMU_CAPS is not available on hybrid machines. Without the width information, the number of occurrences of an event cannot be calculated. For a hybrid machine, the caps information should be retrieved from the PMU_CAPS, and stored in the perf_env->pmu_caps. Add a perf_env__find_br_cntr_info() to return the correct branch counter information from the corresponding fields. Committer notes: While testing I couldn't s ee those "Branch counter" columns enabled by pressing 'B' on the TUI, after reporting it to the list Kan explained the situation: <quote Kan Liang> For a hybrid client, the "Branch Counter" feature is only supported starting from the just released Lunar Lake. Perf falls back to only "ANY" on your Raptor Lake. The "The branch counter is not available" message is expected. Here is the 'perf evlist' result from my Lunar Lake machine, # perf evlist -v cpu_core/branch-instructions/pp: type: 4 (cpu_core), size: 136, config: 0xc4 (branch-instructions), { sample_period, sample_freq }: 4000, sample_type: IP|TID|TIME|READ|PERIOD|BRANCH_STACK|IDENTIFIER, read_format: ID|GROUP|LOST, disabled: 1, freq: 1, enable_on_exec: 1, precise_ip: 2, sample_id_all: 1, exclude_guest: 1, branch_sample_type: ANY|COUNTERS # </quote> Fixes: 6f9d8d1 ("perf script: Add branch counters") Reviewed-by: Ian Rogers <[email protected]> Signed-off-by: Kan Liang <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Kan Liang <[email protected]> Cc: Namhyung Kim <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 9953807 commit edf3ce0

File tree

5 files changed

+28
-6
lines changed

5 files changed

+28
-6
lines changed

tools/perf/builtin-script.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,10 +1241,11 @@ static int ip__fprintf_jump(uint64_t ip, struct branch_entry *en,
12411241
}
12421242

12431243
if (PRINT_FIELD(BRCNTR)) {
1244-
unsigned int width = evsel__env(evsel)->br_cntr_width;
1245-
unsigned int i = 0, j, num, mask = (1L << width) - 1;
12461244
struct evsel *pos = evsel__leader(evsel);
1245+
unsigned int i = 0, j, num, mask, width;
12471246

1247+
perf_env__find_br_cntr_info(evsel__env(evsel), NULL, &width);
1248+
mask = (1L << width) - 1;
12481249
printed += fprintf(fp, "br_cntr: ");
12491250
evlist__for_each_entry_from(evsel->evlist, pos) {
12501251
if (!(pos->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS))

tools/perf/util/annotate.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,14 +333,15 @@ static int symbol__account_br_cntr(struct annotated_branch *branch,
333333
{
334334
unsigned int br_cntr_nr = evsel__leader(evsel)->br_cntr_nr;
335335
unsigned int base = evsel__leader(evsel)->br_cntr_idx;
336-
unsigned int width = evsel__env(evsel)->br_cntr_width;
337336
unsigned int off = offset * evsel->evlist->nr_br_cntr;
338-
unsigned int i, mask = (1L << width) - 1;
339337
u64 *branch_br_cntr = branch->br_cntr;
338+
unsigned int i, mask, width;
340339

341340
if (!br_cntr || !branch_br_cntr)
342341
return 0;
343342

343+
perf_env__find_br_cntr_info(evsel__env(evsel), NULL, &width);
344+
mask = (1L << width) - 1;
344345
for (i = 0; i < br_cntr_nr; i++) {
345346
u64 cntr = (br_cntr >> i * width) & mask;
346347

tools/perf/util/env.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,3 +624,18 @@ char *perf_env__find_pmu_cap(struct perf_env *env, const char *pmu_name,
624624
free(cap_eq);
625625
return NULL;
626626
}
627+
628+
void perf_env__find_br_cntr_info(struct perf_env *env,
629+
unsigned int *nr,
630+
unsigned int *width)
631+
{
632+
if (nr) {
633+
*nr = env->cpu_pmu_caps ? env->br_cntr_nr :
634+
env->pmu_caps->br_cntr_nr;
635+
}
636+
637+
if (width) {
638+
*width = env->cpu_pmu_caps ? env->br_cntr_width :
639+
env->pmu_caps->br_cntr_width;
640+
}
641+
}

tools/perf/util/env.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,4 +192,7 @@ char *perf_env__find_pmu_cap(struct perf_env *env, const char *pmu_name,
192192
const char *cap);
193193

194194
bool perf_env__has_pmu_mapping(struct perf_env *env, const char *pmu_name);
195+
void perf_env__find_br_cntr_info(struct perf_env *env,
196+
unsigned int *nr,
197+
unsigned int *width);
195198
#endif /* __PERF_ENV_H */

tools/perf/util/session.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,6 @@ static void branch_stack__printf(struct perf_sample *sample,
856856
struct branch_entry *entries = perf_sample__branch_entries(sample);
857857
bool callstack = evsel__has_branch_callstack(evsel);
858858
u64 *branch_stack_cntr = sample->branch_stack_cntr;
859-
struct perf_env *env = evsel__env(evsel);
860859
uint64_t i;
861860

862861
if (!callstack) {
@@ -900,8 +899,11 @@ static void branch_stack__printf(struct perf_sample *sample,
900899
}
901900

902901
if (branch_stack_cntr) {
902+
unsigned int br_cntr_width, br_cntr_nr;
903+
904+
perf_env__find_br_cntr_info(evsel__env(evsel), &br_cntr_nr, &br_cntr_width);
903905
printf("... branch stack counters: nr:%" PRIu64 " (counter width: %u max counter nr:%u)\n",
904-
sample->branch_stack->nr, env->br_cntr_width, env->br_cntr_nr);
906+
sample->branch_stack->nr, br_cntr_width, br_cntr_nr);
905907
for (i = 0; i < sample->branch_stack->nr; i++)
906908
printf("..... %2"PRIu64": %016" PRIx64 "\n", i, branch_stack_cntr[i]);
907909
}

0 commit comments

Comments
 (0)