]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
perf header: Add e_machine/e_flags to the header
authorIan Rogers <irogers@google.com>
Tue, 3 Feb 2026 18:26:39 +0000 (10:26 -0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 3 Feb 2026 21:01:27 +0000 (18:01 -0300)
Add 64-bits of feature data to record the ELF machine and flags.

This allows readers to initialize based on the data.

For example, `perf kvm stat` wants to initialize based on the kind of
data to be read, but at initialization time there are no threads to base
this data upon and using the host means cross platform support won't
work.

The values in the perf_env also act as a cache for these within the
session.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Aditya Bodkhe <aditya.b1@linux.ibm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexandre Ghiti <alex@ghiti.fr>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Andrew Jones <ajones@ventanamicro.com>
Cc: Anubhav Shelat <ashelat@redhat.com>
Cc: Anup Patel <anup@brainfault.org>
Cc: Athira Rajeev <atrajeev@linux.ibm.com>
Cc: Blake Jones <blakejones@google.com>
Cc: Chun-Tse Shao <ctshao@google.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <pjw@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Quan Zhou <zhouquan@iscas.ac.cn>
Cc: Shimin Guo <shimin.guo@skydio.com>
Cc: Swapnil Sapkal <swapnil.sapkal@amd.com>
Cc: Thomas Falcon <thomas.falcon@intel.com>
Cc: Will Deacon <will@kernel.org>
Cc: Yunseong Kim <ysk@kzalloc.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/env.h
tools/perf/util/header.c
tools/perf/util/header.h
tools/perf/util/session.c

index 76ba1a36e9ff62432a458d1de95d55fb8b785d27..a4501cbca375fd642e8732166add7a516ed371ee 100644 (file)
@@ -74,6 +74,9 @@ struct perf_env {
        char                    *os_release;
        char                    *version;
        char                    *arch;
+       /* e_machine expanded from 16 to 32-bits for alignment. */
+       u32                     e_machine;
+       u32                     e_flags;
        int                     nr_cpus_online;
        int                     nr_cpus_avail;
        char                    *cpu_desc;
index 31c3bab1b10af3ebeecf619b7f026cb1a2eb3908..9142a8ba401957c618ca15cf88c235dd10ac4971 100644 (file)
@@ -379,6 +379,21 @@ static int write_arch(struct feat_fd *ff,
        return do_write_string(ff, uts.machine);
 }
 
+static int write_e_machine(struct feat_fd *ff,
+                          struct evlist *evlist __maybe_unused)
+{
+       /* e_machine expanded from 16 to 32-bits for alignment. */
+       uint32_t e_flags;
+       uint32_t e_machine = perf_session__e_machine(evlist->session, &e_flags);
+       int ret;
+
+       ret = do_write(ff, &e_machine, sizeof(e_machine));
+       if (ret)
+               return ret;
+
+       return do_write(ff, &e_flags, sizeof(e_flags));
+}
+
 static int write_version(struct feat_fd *ff,
                         struct evlist *evlist __maybe_unused)
 {
@@ -1785,6 +1800,12 @@ static void print_arch(struct feat_fd *ff, FILE *fp)
        fprintf(fp, "# arch : %s\n", ff->ph->env.arch);
 }
 
+static void print_e_machine(struct feat_fd *ff, FILE *fp)
+{
+       fprintf(fp, "# e_machine : %u\n", ff->ph->env.e_machine);
+       fprintf(fp, "#   e_flags : %u\n", ff->ph->env.e_flags);
+}
+
 static void print_cpudesc(struct feat_fd *ff, FILE *fp)
 {
        fprintf(fp, "# cpudesc : %s\n", ff->ph->env.cpu_desc);
@@ -2612,6 +2633,17 @@ FEAT_PROCESS_STR_FUN(arch, arch);
 FEAT_PROCESS_STR_FUN(cpudesc, cpu_desc);
 FEAT_PROCESS_STR_FUN(cpuid, cpuid);
 
+static int process_e_machine(struct feat_fd *ff, void *data __maybe_unused)
+{
+       int ret;
+
+       ret = do_read_u32(ff, &ff->ph->env.e_machine);
+       if (ret)
+               return ret;
+
+       return do_read_u32(ff, &ff->ph->env.e_flags);
+}
+
 #ifdef HAVE_LIBTRACEEVENT
 static int process_tracing_data(struct feat_fd *ff, void *data)
 {
@@ -3730,6 +3762,7 @@ const struct perf_header_feature_ops feat_ops[HEADER_LAST_FEATURE] = {
        FEAT_OPN(HYBRID_TOPOLOGY,       hybrid_topology,        true),
        FEAT_OPR(PMU_CAPS,      pmu_caps,       false),
        FEAT_OPR(CPU_DOMAIN_INFO,       cpu_domain_info,        true),
+       FEAT_OPR(E_MACHINE,     e_machine,      false),
 };
 
 struct header_print_data {
index 36cc74e2d14d259871ceb20d0fe4c6dc9513c808..cc40ac796f52644b09c4771c0fd34f6c3c2c46d2 100644 (file)
@@ -54,6 +54,7 @@ enum {
        HEADER_HYBRID_TOPOLOGY,
        HEADER_PMU_CAPS,
        HEADER_CPU_DOMAIN_INFO,
+       HEADER_E_MACHINE,
        HEADER_LAST_FEATURE,
        HEADER_FEAT_BITS        = 256,
 };
index 72e8bb67d7407d9c8af00cf5b66fc540f167e26a..53f51c3f96034d1a2a768927f684e8450f20d5eb 100644 (file)
@@ -2967,7 +2967,6 @@ struct perf_env *perf_session__env(struct perf_session *session)
 struct perf_session__e_machine_cb_args {
        uint32_t e_flags;
        uint16_t e_machine;
-       bool need_e_flags;
 };
 
 static int perf_session__e_machine_cb(struct thread *thread, void *_args)
@@ -2975,8 +2974,7 @@ static int perf_session__e_machine_cb(struct thread *thread, void *_args)
        struct perf_session__e_machine_cb_args *args = _args;
        struct machine *machine = maps__machine(thread__maps(thread));
 
-       args->e_machine = thread__e_machine(thread, machine,
-                                           args->need_e_flags ? &args->e_flags : NULL);
+       args->e_machine = thread__e_machine(thread, machine, &args->e_flags);
        return args->e_machine != EM_NONE ? 1 : 0;
 }
 
@@ -2988,8 +2986,8 @@ uint16_t perf_session__e_machine(struct perf_session *session, uint32_t *e_flags
 {
        struct perf_session__e_machine_cb_args args = {
                .e_machine = EM_NONE,
-               .need_e_flags = e_flags != NULL,
        };
+       struct perf_env *env;
 
        if (!session) {
                /* Default to assuming a host machine. */
@@ -2999,12 +2997,35 @@ uint16_t perf_session__e_machine(struct perf_session *session, uint32_t *e_flags
                return EM_HOST;
        }
 
+       env = perf_session__env(session);
+       if (env && env->e_machine != EM_NONE) {
+               if (e_flags)
+                       *e_flags = env->e_flags;
+
+               return env->e_machine;
+       }
+
        machines__for_each_thread(&session->machines,
                                  perf_session__e_machine_cb,
                                  &args);
 
+       if (args.e_machine != EM_NONE) {
+               if (env) {
+                       env->e_machine = args.e_machine;
+                       env->e_flags = args.e_flags;
+               }
+               if (e_flags)
+                       *e_flags = args.e_flags;
+
+               return args.e_machine;
+       }
+
+       /*
+        * Couldn't determine from the perf_env or current set of
+        * threads. Default to the host.
+        */
        if (e_flags)
-               *e_flags = args.e_flags;
+               *e_flags = EF_HOST;
 
-       return args.e_machine == EM_NONE ? EM_HOST : args.e_machine;
+       return EM_HOST;
 }