]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
perf evlist: Save branch counters information
authorKan Liang <kan.liang@linux.intel.com>
Tue, 13 Aug 2024 16:02:02 +0000 (09:02 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 14 Aug 2024 13:20:40 +0000 (10:20 -0300)
The branch counters logging (A.K.A LBR event logging) introduces a
per-counter indication of precise event occurrences in LBRs. The kernel
only dumps the number of occurrences into a record. The perf tool has
to map the number to the corresponding event.

Add evlist__update_br_cntr() to go through the evlist to pick the
events that are configured to be logged. Assign a logical idx to track
them, and add the total number of the events in the leader event.

The total number will be used to allocate the space to save the branch
counters for a block. The logical idx will be used to locate the
corresponding event quickly in the following patches.

It only needs to iterate the evlist once. The
evsel__has_branch_counters() is also optimized.

Reviewed-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: https://lore.kernel.org/r/20240813160208.2493643-4-kan.liang@linux.intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h

index 4b2538e4f679fb5561186ce607f7a66fa487c082..68bbd3ea771b482e3e87b4be6d13dc5e9316cf3a 100644 (file)
@@ -79,6 +79,7 @@ void evlist__init(struct evlist *evlist, struct perf_cpu_map *cpus,
        evlist->ctl_fd.fd = -1;
        evlist->ctl_fd.ack = -1;
        evlist->ctl_fd.pos = -1;
+       evlist->nr_br_cntr = -1;
 }
 
 struct evlist *evlist__new(void)
@@ -1264,6 +1265,20 @@ u64 evlist__combined_branch_type(struct evlist *evlist)
        return branch_type;
 }
 
+void evlist__update_br_cntr(struct evlist *evlist)
+{
+       struct evsel *evsel;
+       int i = 0;
+
+       evlist__for_each_entry(evlist, evsel) {
+               if (evsel->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS) {
+                       evsel->br_cntr_idx = i++;
+                       evsel__leader(evsel)->br_cntr_nr++;
+               }
+       }
+       evlist->nr_br_cntr = i;
+}
+
 bool evlist__valid_read_format(struct evlist *evlist)
 {
        struct evsel *first = evlist__first(evlist), *pos = first;
index cccc34da5a02a3d6f340054a0e3bec6232f0bba6..b46f1a320783aea11e31660642996afc7e56861f 100644 (file)
@@ -57,6 +57,7 @@ struct evlist {
        bool             enabled;
        int              id_pos;
        int              is_pos;
+       int              nr_br_cntr;
        u64              combined_sample_type;
        enum bkw_mmap_state bkw_mmap_state;
        struct {
@@ -219,6 +220,7 @@ int evlist__apply_filters(struct evlist *evlist, struct evsel **err_evsel,
 u64 __evlist__combined_sample_type(struct evlist *evlist);
 u64 evlist__combined_sample_type(struct evlist *evlist);
 u64 evlist__combined_branch_type(struct evlist *evlist);
+void evlist__update_br_cntr(struct evlist *evlist);
 bool evlist__sample_id_all(struct evlist *evlist);
 u16 evlist__id_hdr_size(struct evlist *evlist);
 
index f22f402d54cc4c185bc7102798032ed029007c01..38a74d6dde4943895a7a06d8fb334d799e228175 100644 (file)
@@ -2636,17 +2636,18 @@ u64 evsel__bitfield_swap_branch_flags(u64 value)
 
 static inline bool evsel__has_branch_counters(const struct evsel *evsel)
 {
-       struct evsel *cur, *leader = evsel__leader(evsel);
+       struct evsel *leader = evsel__leader(evsel);
 
        /* The branch counters feature only supports group */
        if (!leader || !evsel->evlist)
                return false;
 
-       evlist__for_each_entry(evsel->evlist, cur) {
-               if ((leader == evsel__leader(cur)) &&
-                   (cur->core.attr.branch_sample_type & PERF_SAMPLE_BRANCH_COUNTERS))
-                       return true;
-       }
+       if (evsel->evlist->nr_br_cntr < 0)
+               evlist__update_br_cntr(evsel->evlist);
+
+       if (leader->br_cntr_nr > 0)
+               return true;
+
        return false;
 }
 
index a5da4b03bb1c95a40c92b1b899ace43aa3779d93..a393dae1dc967718243c6f8417da310e784f2d62 100644 (file)
@@ -148,6 +148,14 @@ struct evsel {
         */
        __u64                   synth_sample_type;
 
+       /*
+        * Store the branch counter related information.
+        * br_cntr_idx: The idx of the branch counter event in the evlist
+        * br_cntr_nr:  The number of the branch counter event in the group
+        *              (Only available for the leader event)
+        */
+       int                     br_cntr_idx;
+       int                     br_cntr_nr;
        /*
         * bpf_counter_ops serves two use cases:
         *   1. perf-stat -b          counting events used byBPF programs