]> www.infradead.org Git - users/willy/xarray.git/commitdiff
perf tools: Add missing_features for aux_start_paused, aux_pause, aux_resume
authorAdrian Hunter <adrian.hunter@intel.com>
Mon, 16 Dec 2024 07:02:40 +0000 (09:02 +0200)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Wed, 18 Dec 2024 19:24:32 +0000 (16:24 -0300)
Display "feature is not supported" error message if aux_start_paused,
aux_pause or aux_resume result in a perf_event_open() error.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Leo Yan <leo.yan@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20241216070244.14450-5-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/evsel.c
tools/perf/util/evsel.h

index 0a1b797d1f00ca84e87d086aecc3fbc88c736a63..f6bf845808d6ec80d5bd411e2eb7d13ccd906b58 100644 (file)
@@ -2145,16 +2145,17 @@ int evsel__prepare_open(struct evsel *evsel, struct perf_cpu_map *cpus,
        return err;
 }
 
-static bool has_attr_feature(struct perf_event_attr *attr, unsigned long flags)
+static bool __has_attr_feature(struct perf_event_attr *attr,
+                              struct perf_cpu cpu, unsigned long flags)
 {
-       int fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, /*cpu=*/-1,
+       int fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, cpu.cpu,
                         /*group_fd=*/-1, flags);
        close(fd);
 
        if (fd < 0) {
                attr->exclude_kernel = 1;
 
-               fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, /*cpu=*/-1,
+               fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, cpu.cpu,
                             /*group_fd=*/-1, flags);
                close(fd);
        }
@@ -2162,7 +2163,7 @@ static bool has_attr_feature(struct perf_event_attr *attr, unsigned long flags)
        if (fd < 0) {
                attr->exclude_hv = 1;
 
-               fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, /*cpu=*/-1,
+               fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, cpu.cpu,
                             /*group_fd=*/-1, flags);
                close(fd);
        }
@@ -2170,7 +2171,7 @@ static bool has_attr_feature(struct perf_event_attr *attr, unsigned long flags)
        if (fd < 0) {
                attr->exclude_guest = 1;
 
-               fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, /*cpu=*/-1,
+               fd = syscall(SYS_perf_event_open, attr, /*pid=*/0, cpu.cpu,
                             /*group_fd=*/-1, flags);
                close(fd);
        }
@@ -2182,6 +2183,13 @@ static bool has_attr_feature(struct perf_event_attr *attr, unsigned long flags)
        return fd >= 0;
 }
 
+static bool has_attr_feature(struct perf_event_attr *attr, unsigned long flags)
+{
+       struct perf_cpu cpu = {.cpu = -1};
+
+       return __has_attr_feature(attr, cpu, flags);
+}
+
 static void evsel__detect_missing_pmu_features(struct evsel *evsel)
 {
        struct perf_event_attr attr = {
@@ -2270,7 +2278,65 @@ found:
        errno = old_errno;
 }
 
-static bool evsel__detect_missing_features(struct evsel *evsel)
+static bool evsel__probe_aux_action(struct evsel *evsel, struct perf_cpu cpu)
+{
+       struct perf_event_attr attr = evsel->core.attr;
+       int old_errno = errno;
+
+       attr.disabled = 1;
+       attr.aux_start_paused = 1;
+
+       if (__has_attr_feature(&attr, cpu, /*flags=*/0)) {
+               errno = old_errno;
+               return true;
+       }
+
+       /*
+        * EOPNOTSUPP means the kernel supports the feature but the PMU does
+        * not, so keep that distinction if possible.
+        */
+       if (errno != EOPNOTSUPP)
+               errno = old_errno;
+
+       return false;
+}
+
+static void evsel__detect_missing_aux_action_feature(struct evsel *evsel, struct perf_cpu cpu)
+{
+       static bool detection_done;
+       struct evsel *leader;
+
+       /*
+        * Don't bother probing aux_action if it is not being used or has been
+        * probed before.
+        */
+       if (!evsel->core.attr.aux_action || detection_done)
+               return;
+
+       detection_done = true;
+
+       /*
+        * The leader is an AUX area event. If it has failed, assume the feature
+        * is not supported.
+        */
+       leader = evsel__leader(evsel);
+       if (evsel == leader) {
+               perf_missing_features.aux_action = true;
+               return;
+       }
+
+       /*
+        * AUX area event with aux_action must have been opened successfully
+        * already, so feature is supported.
+        */
+       if (leader->core.attr.aux_action)
+               return;
+
+       if (!evsel__probe_aux_action(leader, cpu))
+               perf_missing_features.aux_action = true;
+}
+
+static bool evsel__detect_missing_features(struct evsel *evsel, struct perf_cpu cpu)
 {
        static bool detection_done = false;
        struct perf_event_attr attr = {
@@ -2280,6 +2346,8 @@ static bool evsel__detect_missing_features(struct evsel *evsel)
        };
        int old_errno;
 
+       evsel__detect_missing_aux_action_feature(evsel, cpu);
+
        evsel__detect_missing_pmu_features(evsel);
 
        if (evsel__has_br_stack(evsel))
@@ -2494,6 +2562,7 @@ static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
        int idx, thread, nthreads;
        int pid = -1, err, old_errno;
        enum rlimit_action set_rlimit = NO_CHANGE;
+       struct perf_cpu cpu;
 
        if (evsel__is_retire_lat(evsel))
                return tpebs_start(evsel->evlist);
@@ -2531,6 +2600,7 @@ fallback_missing_features:
        }
 
        for (idx = start_cpu_map_idx; idx < end_cpu_map_idx; idx++) {
+               cpu = perf_cpu_map__cpu(cpus, idx);
 
                for (thread = 0; thread < nthreads; thread++) {
                        int fd, group_fd;
@@ -2551,10 +2621,9 @@ retry_open:
 
                        /* Debug message used by test scripts */
                        pr_debug2_peo("sys_perf_event_open: pid %d  cpu %d  group_fd %d  flags %#lx",
-                               pid, perf_cpu_map__cpu(cpus, idx).cpu, group_fd, evsel->open_flags);
+                               pid, cpu.cpu, group_fd, evsel->open_flags);
 
-                       fd = sys_perf_event_open(&evsel->core.attr, pid,
-                                               perf_cpu_map__cpu(cpus, idx).cpu,
+                       fd = sys_perf_event_open(&evsel->core.attr, pid, cpu.cpu,
                                                group_fd, evsel->open_flags);
 
                        FD(evsel, idx, thread) = fd;
@@ -2570,8 +2639,7 @@ retry_open:
                        bpf_counter__install_pe(evsel, idx, fd);
 
                        if (unlikely(test_attr__enabled())) {
-                               test_attr__open(&evsel->core.attr, pid,
-                                               perf_cpu_map__cpu(cpus, idx),
+                               test_attr__open(&evsel->core.attr, pid, cpu,
                                                fd, group_fd, evsel->open_flags);
                        }
 
@@ -2626,7 +2694,7 @@ try_fallback:
        if (err == -EMFILE && rlimit__increase_nofile(&set_rlimit))
                goto retry_open;
 
-       if (err == -EINVAL && evsel__detect_missing_features(evsel))
+       if (err == -EINVAL && evsel__detect_missing_features(evsel, cpu))
                goto fallback_missing_features;
 
        if (evsel__precise_ip_fallback(evsel))
@@ -3585,6 +3653,10 @@ int evsel__open_strerror(struct evsel *evsel, struct target *target,
                        return scnprintf(msg, size,
        "%s: PMU Hardware doesn't support 'aux_output' feature",
                                         evsel__name(evsel));
+               if (evsel->core.attr.aux_action)
+                       return scnprintf(msg, size,
+       "%s: PMU Hardware doesn't support 'aux_action' feature",
+                                       evsel__name(evsel));
                if (evsel->core.attr.sample_period != 0)
                        return scnprintf(msg, size,
        "%s: PMU Hardware doesn't support sampling/overflow-interrupts. Try 'perf stat'",
@@ -3615,6 +3687,8 @@ int evsel__open_strerror(struct evsel *evsel, struct target *target,
                        return scnprintf(msg, size, "clockid feature not supported.");
                if (perf_missing_features.clockid_wrong)
                        return scnprintf(msg, size, "wrong clockid (%d).", clockid);
+               if (perf_missing_features.aux_action)
+                       return scnprintf(msg, size, "The 'aux_action' feature is not supported, update the kernel.");
                if (perf_missing_features.aux_output)
                        return scnprintf(msg, size, "The 'aux_output' feature is not supported, update the kernel.");
                if (!target__has_cpu(target))
index 93b6244ec302c2b29b4ee3789345e30f0156084f..76749bb0e1a54209a98911143e06c29be61e7a09 100644 (file)
@@ -207,6 +207,7 @@ struct perf_missing_features {
        bool weight_struct;
        bool read_lost;
        bool branch_counters;
+       bool aux_action;
        bool inherit_sample_read;
 };