]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blobdiff - tools/perf/util/evsel.c
perf evsel: Provide meaningful warning when trying to use 'aux_output' on older kernels
[mirror_ubuntu-focal-kernel.git] / tools / perf / util / evsel.c
index 089582e644d783bc4539c7a31f7ff722ac313eda..0a33f7322eccbd338ac129b59a185ff0baf4b920 100644 (file)
@@ -90,7 +90,7 @@ set_methods:
        return 0;
 }
 
-#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
+#define FD(e, x, y) (*(int *)xyarray__entry(e->core.fd, x, y))
 
 int __perf_evsel__sample_size(u64 sample_type)
 {
@@ -833,6 +833,9 @@ static void apply_config_terms(struct evsel *evsel,
                        break;
                case PERF_EVSEL__CONFIG_TERM_PERCORE:
                        break;
+               case PERF_EVSEL__CONFIG_TERM_AUX_OUTPUT:
+                       attr->aux_output = term->val.aux_output ? 1 : 0;
+                       break;
                default:
                        break;
                }
@@ -948,7 +951,7 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts,
                 * Apply group format only if we belong to group
                 * with more than one members.
                 */
-               if (leader->nr_members > 1) {
+               if (leader->core.nr_members > 1) {
                        attr->read_format |= PERF_FORMAT_GROUP;
                        attr->inherit = 0;
                }
@@ -1125,7 +1128,7 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts,
                attr->exclude_user   = 1;
        }
 
-       if (evsel->own_cpus || evsel->unit)
+       if (evsel->core.own_cpus || evsel->unit)
                evsel->core.attr.read_format |= PERF_FORMAT_ID;
 
        /*
@@ -1153,47 +1156,6 @@ void perf_evsel__config(struct evsel *evsel, struct record_opts *opts,
                perf_evsel__reset_sample_bit(evsel, BRANCH_STACK);
 }
 
-static int perf_evsel__alloc_fd(struct evsel *evsel, int ncpus, int nthreads)
-{
-       evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
-
-       if (evsel->fd) {
-               int cpu, thread;
-               for (cpu = 0; cpu < ncpus; cpu++) {
-                       for (thread = 0; thread < nthreads; thread++) {
-                               FD(evsel, cpu, thread) = -1;
-                       }
-               }
-       }
-
-       return evsel->fd != NULL ? 0 : -ENOMEM;
-}
-
-static int perf_evsel__run_ioctl(struct evsel *evsel,
-                         int ioc,  void *arg)
-{
-       int cpu, thread;
-
-       for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
-               for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
-                       int fd = FD(evsel, cpu, thread),
-                           err = ioctl(fd, ioc, arg);
-
-                       if (err)
-                               return err;
-               }
-       }
-
-       return 0;
-}
-
-int evsel__apply_filter(struct evsel *evsel, const char *filter)
-{
-       return perf_evsel__run_ioctl(evsel,
-                                    PERF_EVENT_IOC_SET_FILTER,
-                                    (void *)filter);
-}
-
 int perf_evsel__set_filter(struct evsel *evsel, const char *filter)
 {
        char *new_filter = strdup(filter);
@@ -1236,7 +1198,7 @@ int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter)
 
 int evsel__enable(struct evsel *evsel)
 {
-       int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
+       int err = perf_evsel__enable(&evsel->core);
 
        if (!err)
                evsel->disabled = false;
@@ -1246,7 +1208,7 @@ int evsel__enable(struct evsel *evsel)
 
 int evsel__disable(struct evsel *evsel)
 {
-       int err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
+       int err = perf_evsel__disable(&evsel->core);
        /*
         * We mark it disabled here so that tools that disable a event can
         * ignore events after they disable it. I.e. the ring buffer may have
@@ -1281,12 +1243,6 @@ int perf_evsel__alloc_id(struct evsel *evsel, int ncpus, int nthreads)
        return 0;
 }
 
-static void perf_evsel__free_fd(struct evsel *evsel)
-{
-       xyarray__delete(evsel->fd);
-       evsel->fd = NULL;
-}
-
 static void perf_evsel__free_id(struct evsel *evsel)
 {
        xyarray__delete(evsel->sample_id);
@@ -1305,29 +1261,18 @@ static void perf_evsel__free_config_terms(struct evsel *evsel)
        }
 }
 
-void perf_evsel__close_fd(struct evsel *evsel)
-{
-       int cpu, thread;
-
-       for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
-               for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
-                       close(FD(evsel, cpu, thread));
-                       FD(evsel, cpu, thread) = -1;
-               }
-}
-
 void perf_evsel__exit(struct evsel *evsel)
 {
        assert(list_empty(&evsel->core.node));
        assert(evsel->evlist == NULL);
        perf_evsel__free_counts(evsel);
-       perf_evsel__free_fd(evsel);
+       perf_evsel__free_fd(&evsel->core);
        perf_evsel__free_id(evsel);
        perf_evsel__free_config_terms(evsel);
        cgroup__put(evsel->cgrp);
-       perf_cpu_map__put(evsel->cpus);
-       perf_cpu_map__put(evsel->own_cpus);
-       perf_thread_map__put(evsel->threads);
+       perf_cpu_map__put(evsel->core.cpus);
+       perf_cpu_map__put(evsel->core.own_cpus);
+       perf_thread_map__put(evsel->core.threads);
        zfree(&evsel->group_name);
        zfree(&evsel->name);
        perf_evsel__object.fini(evsel);
@@ -1379,53 +1324,12 @@ void perf_counts_values__scale(struct perf_counts_values *count,
                *pscaled = scaled;
 }
 
-static int perf_evsel__read_size(struct evsel *evsel)
-{
-       u64 read_format = evsel->core.attr.read_format;
-       int entry = sizeof(u64); /* value */
-       int size = 0;
-       int nr = 1;
-
-       if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
-               size += sizeof(u64);
-
-       if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
-               size += sizeof(u64);
-
-       if (read_format & PERF_FORMAT_ID)
-               entry += sizeof(u64);
-
-       if (read_format & PERF_FORMAT_GROUP) {
-               nr = evsel->nr_members;
-               size += sizeof(u64);
-       }
-
-       size += entry * nr;
-       return size;
-}
-
-int perf_evsel__read(struct evsel *evsel, int cpu, int thread,
-                    struct perf_counts_values *count)
-{
-       size_t size = perf_evsel__read_size(evsel);
-
-       memset(count, 0, sizeof(*count));
-
-       if (FD(evsel, cpu, thread) < 0)
-               return -EINVAL;
-
-       if (readn(FD(evsel, cpu, thread), count->values, size) <= 0)
-               return -errno;
-
-       return 0;
-}
-
 static int
 perf_evsel__read_one(struct evsel *evsel, int cpu, int thread)
 {
        struct perf_counts_values *count = perf_counts(evsel->counts, cpu, thread);
 
-       return perf_evsel__read(evsel, cpu, thread, count);
+       return perf_evsel__read(&evsel->core, cpu, thread, count);
 }
 
 static void
@@ -1453,7 +1357,7 @@ perf_evsel__process_group_data(struct evsel *leader,
 
        nr = *data++;
 
-       if (nr != (u64) leader->nr_members)
+       if (nr != (u64) leader->core.nr_members)
                return -EINVAL;
 
        if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
@@ -1486,7 +1390,7 @@ perf_evsel__read_group(struct evsel *leader, int cpu, int thread)
 {
        struct perf_stat_evsel *ps = leader->stats;
        u64 read_format = leader->core.attr.read_format;
-       int size = perf_evsel__read_size(leader);
+       int size = perf_evsel__read_size(&leader->core);
        u64 *data = ps->group_data;
 
        if (!(read_format & PERF_FORMAT_ID))
@@ -1555,7 +1459,7 @@ static int get_group_fd(struct evsel *evsel, int cpu, int thread)
         * Leader must be already processed/open,
         * if not it's a bug.
         */
-       BUG_ON(!leader->fd);
+       BUG_ON(!leader->core.fd);
 
        fd = FD(leader, cpu, thread);
        BUG_ON(fd == -1);
@@ -1686,6 +1590,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
        PRINT_ATTRf(namespaces, p_unsigned);
        PRINT_ATTRf(ksymbol, p_unsigned);
        PRINT_ATTRf(bpf_event, p_unsigned);
+       PRINT_ATTRf(aux_output, p_unsigned);
 
        PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
        PRINT_ATTRf(bp_type, p_unsigned);
@@ -1833,7 +1738,8 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
        int pid = -1, err;
        enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
 
-       if (perf_missing_features.write_backward && evsel->core.attr.write_backward)
+       if ((perf_missing_features.write_backward && evsel->core.attr.write_backward) ||
+           (perf_missing_features.aux_output     && evsel->core.attr.aux_output))
                return -EINVAL;
 
        if (cpus == NULL) {
@@ -1865,8 +1771,8 @@ int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
        else
                nthreads = threads->nr;
 
-       if (evsel->fd == NULL &&
-           perf_evsel__alloc_fd(evsel, cpus->nr, nthreads) < 0)
+       if (evsel->core.fd == NULL &&
+           perf_evsel__alloc_fd(&evsel->core, cpus->nr, nthreads) < 0)
                return -ENOMEM;
 
        if (evsel->cgrp) {
@@ -2007,7 +1913,11 @@ try_fallback:
         * Must probe features in the order they were added to the
         * perf_event_attr interface.
         */
-       if (!perf_missing_features.bpf_event && evsel->core.attr.bpf_event) {
+       if (!perf_missing_features.aux_output && evsel->core.attr.aux_output) {
+               perf_missing_features.aux_output = true;
+               pr_debug2("Kernel has no attr.aux_output support, bailing out\n");
+               goto out_close;
+       } else if (!perf_missing_features.bpf_event && evsel->core.attr.bpf_event) {
                perf_missing_features.bpf_event = true;
                pr_debug2("switching off bpf_event\n");
                goto fallback_missing_features;
@@ -2073,13 +1983,9 @@ out_close:
        return err;
 }
 
-void perf_evsel__close(struct evsel *evsel)
+void evsel__close(struct evsel *evsel)
 {
-       if (evsel->fd == NULL)
-               return;
-
-       perf_evsel__close_fd(evsel);
-       perf_evsel__free_fd(evsel);
+       perf_evsel__close(&evsel->core);
        perf_evsel__free_id(evsel);
 }
 
@@ -3025,6 +2931,8 @@ int perf_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_output)
+                       return scnprintf(msg, size, "The 'aux_output' feature is not supported, update the kernel.");
                break;
        default:
                break;
@@ -3048,8 +2956,8 @@ static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist)
 {
        int cpu, thread;
 
-       for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
-               for (thread = 0; thread < xyarray__max_y(evsel->fd);
+       for (cpu = 0; cpu < xyarray__max_x(evsel->core.fd); cpu++) {
+               for (thread = 0; thread < xyarray__max_y(evsel->core.fd);
                     thread++) {
                        int fd = FD(evsel, cpu, thread);
 
@@ -3064,8 +2972,8 @@ static int store_evsel_ids(struct evsel *evsel, struct evlist *evlist)
 
 int perf_evsel__store_ids(struct evsel *evsel, struct evlist *evlist)
 {
-       struct perf_cpu_map *cpus = evsel->cpus;
-       struct perf_thread_map *threads = evsel->threads;
+       struct perf_cpu_map *cpus = evsel->core.cpus;
+       struct perf_thread_map *threads = evsel->core.threads;
 
        if (perf_evsel__alloc_id(evsel, cpus->nr, threads->nr))
                return -ENOMEM;