perf cs-etm: Make PID format accessible from struct cs_etm_auxtrace
authorJames Clark <james.clark@arm.com>
Mon, 12 Jun 2023 11:14:00 +0000 (12:14 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 12 Jun 2023 21:18:13 +0000 (18:18 -0300)
To avoid every user of PID format having to use their own static
local variable, cache it on initialisation and change the accessor to
take struct cs_etm_auxtrace.

Reviewed-by: Leo Yan <leo.yan@linaro.org>
Signed-off-by: James Clark <james.clark@arm.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20230612111403.100613-4-james.clark@arm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
tools/perf/util/cs-etm.c
tools/perf/util/cs-etm.h

index 82a27ab..2af641d 100644 (file)
@@ -541,34 +541,22 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq,
                        const uint8_t trace_chan_id)
 {
        pid_t tid = -1;
-       static u64 pid_fmt;
-       int ret;
-
-       /*
-        * As all the ETMs run at the same exception level, the system should
-        * have the same PID format crossing CPUs.  So cache the PID format
-        * and reuse it for sequential decoding.
-        */
-       if (!pid_fmt) {
-               ret = cs_etm__get_pid_fmt(trace_chan_id, &pid_fmt);
-               if (ret)
-                       return OCSD_RESP_FATAL_SYS_ERR;
-       }
 
        /*
         * Process the PE_CONTEXT packets if we have a valid contextID or VMID.
         * If the kernel is running at EL2, the PID is traced in CONTEXTIDR_EL2
         * as VMID, Bit ETM_OPT_CTXTID2 is set in this case.
         */
-       switch (pid_fmt) {
-       case BIT(ETM_OPT_CTXTID):
+       switch (cs_etm__get_pid_fmt(etmq)) {
+       case CS_ETM_PIDFMT_CTXTID:
                if (elem->context.ctxt_id_valid)
                        tid = elem->context.context_id;
                break;
-       case BIT(ETM_OPT_CTXTID2):
+       case CS_ETM_PIDFMT_CTXTID2:
                if (elem->context.vmid_valid)
                        tid = elem->context.vmid;
                break;
+       case CS_ETM_PIDFMT_NONE:
        default:
                break;
        }
index da22732..8c4d55a 100644 (file)
@@ -78,6 +78,7 @@ struct cs_etm_auxtrace {
        u64 instructions_id;
        u64 **metadata;
        unsigned int pmu_type;
+       enum cs_etm_pid_fmt pid_fmt;
 };
 
 struct cs_etm_traceid_queue {
@@ -170,44 +171,46 @@ int cs_etm__get_cpu(u8 trace_chan_id, int *cpu)
 }
 
 /*
- * The returned PID format is presented by two bits:
+ * The returned PID format is presented as an enum:
  *
- *   Bit ETM_OPT_CTXTID: CONTEXTIDR or CONTEXTIDR_EL1 is traced;
- *   Bit ETM_OPT_CTXTID2: CONTEXTIDR_EL2 is traced.
+ *   CS_ETM_PIDFMT_CTXTID: CONTEXTIDR or CONTEXTIDR_EL1 is traced.
+ *   CS_ETM_PIDFMT_CTXTID2: CONTEXTIDR_EL2 is traced.
+ *   CS_ETM_PIDFMT_NONE: No context IDs
  *
  * It's possible that the two bits ETM_OPT_CTXTID and ETM_OPT_CTXTID2
  * are enabled at the same time when the session runs on an EL2 kernel.
  * This means the CONTEXTIDR_EL1 and CONTEXTIDR_EL2 both will be
  * recorded in the trace data, the tool will selectively use
  * CONTEXTIDR_EL2 as PID.
+ *
+ * The result is cached in etm->pid_fmt so this function only needs to be called
+ * when processing the aux info.
  */
-int cs_etm__get_pid_fmt(u8 trace_chan_id, u64 *pid_fmt)
+static enum cs_etm_pid_fmt cs_etm__init_pid_fmt(u64 *metadata)
 {
-       struct int_node *inode;
-       u64 *metadata, val;
-
-       inode = intlist__find(traceid_list, trace_chan_id);
-       if (!inode)
-               return -EINVAL;
-
-       metadata = inode->priv;
+       u64 val;
 
        if (metadata[CS_ETM_MAGIC] == __perf_cs_etmv3_magic) {
                val = metadata[CS_ETM_ETMCR];
                /* CONTEXTIDR is traced */
                if (val & BIT(ETM_OPT_CTXTID))
-                       *pid_fmt = BIT(ETM_OPT_CTXTID);
+                       return CS_ETM_PIDFMT_CTXTID;
        } else {
                val = metadata[CS_ETMV4_TRCCONFIGR];
                /* CONTEXTIDR_EL2 is traced */
                if (val & (BIT(ETM4_CFG_BIT_VMID) | BIT(ETM4_CFG_BIT_VMID_OPT)))
-                       *pid_fmt = BIT(ETM_OPT_CTXTID2);
+                       return CS_ETM_PIDFMT_CTXTID2;
                /* CONTEXTIDR_EL1 is traced */
                else if (val & BIT(ETM4_CFG_BIT_CTXTID))
-                       *pid_fmt = BIT(ETM_OPT_CTXTID);
+                       return CS_ETM_PIDFMT_CTXTID;
        }
 
-       return 0;
+       return CS_ETM_PIDFMT_NONE;
+}
+
+enum cs_etm_pid_fmt cs_etm__get_pid_fmt(struct cs_etm_queue *etmq)
+{
+       return etmq->etm->pid_fmt;
 }
 
 static int cs_etm__map_trace_id(u8 trace_chan_id, u64 *cpu_metadata)
@@ -3239,6 +3242,13 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
                goto err_free_metadata;
        }
 
+       /*
+        * As all the ETMs run at the same exception level, the system should
+        * have the same PID format crossing CPUs.  So cache the PID format
+        * and reuse it for sequential decoding.
+        */
+       etm->pid_fmt = cs_etm__init_pid_fmt(metadata[0]);
+
        err = auxtrace_queues__init(&etm->queues);
        if (err)
                goto err_free_etm;
index ecca407..2f47f4e 100644 (file)
@@ -244,9 +244,15 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
                                  struct perf_session *session);
 struct perf_event_attr *cs_etm_get_default_config(struct perf_pmu *pmu);
 
+enum cs_etm_pid_fmt {
+       CS_ETM_PIDFMT_NONE,
+       CS_ETM_PIDFMT_CTXTID,
+       CS_ETM_PIDFMT_CTXTID2
+};
+
 #ifdef HAVE_CSTRACE_SUPPORT
 int cs_etm__get_cpu(u8 trace_chan_id, int *cpu);
-int cs_etm__get_pid_fmt(u8 trace_chan_id, u64 *pid_fmt);
+enum pid_fmt cs_etm__get_pid_fmt(struct cs_etm_queue *etmq);
 int cs_etm__etmq_set_tid(struct cs_etm_queue *etmq,
                         pid_t tid, u8 trace_chan_id);
 bool cs_etm__etmq_is_timeless(struct cs_etm_queue *etmq);