perf cs-etm: Move mapping of Trace ID and cpu into helper function
authorMike Leach <mike.leach@linaro.org>
Fri, 31 Mar 2023 05:56:43 +0000 (06:56 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Tue, 4 Apr 2023 12:39:56 +0000 (09:39 -0300)
The information to associate Trace ID and CPU will be changing.

Drivers will start outputting this as a hardware ID packet in the data
file which if present will be used in preference to the AUXINFO values.

To prepare for this we provide a helper functions to do the individual ID
mapping, and one to extract the IDs from the completed metadata blocks.

Reviewed-by: James Clark <james.clark@arm.com>
Signed-off-by: Mike Leach <mike.leach@linaro.org>
Acked-by: Suzuki Poulouse <suzuki.poulose@arm.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Darren Hart <darren@os.amperecomputing.com>
Cc: Ganapatrao Kulkarni <gankulkarni@os.amperecomputing.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Leo Yan <leo.yan@linaro.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Cc: coresight@lists.linaro.org
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20230331055645.26918-2-mike.leach@linaro.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/include/linux/coresight-pmu.h
tools/perf/util/cs-etm-base.c
tools/perf/util/cs-etm.c
tools/perf/util/cs-etm.h

index 6c2fd6c..db9c7c0 100644 (file)
@@ -7,9 +7,14 @@
 #ifndef _LINUX_CORESIGHT_PMU_H
 #define _LINUX_CORESIGHT_PMU_H
 
+#include <linux/bits.h>
+
 #define CORESIGHT_ETM_PMU_NAME "cs_etm"
 #define CORESIGHT_ETM_PMU_SEED  0x10
 
+/* CoreSight trace ID is currently the bottom 7 bits of the value */
+#define CORESIGHT_TRACE_ID_VAL_MASK    GENMASK(6, 0)
+
 /*
  * Below are the definition of bit offsets for perf option, and works as
  * arbitrary values for all ETM versions.
index 5f48b75..4abe416 100644 (file)
@@ -148,7 +148,8 @@ static void cs_etm__print_auxtrace_info(u64 *val, int num)
        for (i = CS_HEADER_VERSION_MAX; cpu < num; cpu++) {
                if (version == 0)
                        err = cs_etm__print_cpu_metadata_v0(val, &i);
-               else if (version == 1)
+               /* printing same for both, but value bit flags added on v2 */
+               else if ((version == 1) || (version == 2))
                        err = cs_etm__print_cpu_metadata_v1(val, &i);
                if (err)
                        return;
index f65bac5..5fc9c28 100644 (file)
@@ -196,6 +196,30 @@ int cs_etm__get_pid_fmt(u8 trace_chan_id, u64 *pid_fmt)
        return 0;
 }
 
+static int cs_etm__map_trace_id(u8 trace_chan_id, u64 *cpu_metadata)
+{
+       struct int_node *inode;
+
+       /* Get an RB node for this CPU */
+       inode = intlist__findnew(traceid_list, trace_chan_id);
+
+       /* Something went wrong, no need to continue */
+       if (!inode)
+               return -ENOMEM;
+
+       /*
+        * The node for that CPU should not be taken.
+        * Back out if that's the case.
+        */
+       if (inode->priv)
+               return -EINVAL;
+
+       /* All good, associate the traceID with the metadata pointer */
+       inode->priv = cpu_metadata;
+
+       return 0;
+}
+
 void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq,
                                              u8 trace_chan_id)
 {
@@ -2804,17 +2828,46 @@ static bool cs_etm__has_virtual_ts(u64 **metadata, int num_cpu)
        return true;
 }
 
+/* map trace ids to correct metadata block, from information in metadata */
+static int cs_etm__map_trace_ids_metadata(int num_cpu, u64 **metadata)
+{
+       u64 cs_etm_magic;
+       u8 trace_chan_id;
+       int i, err;
+
+       for (i = 0; i < num_cpu; i++) {
+               cs_etm_magic = metadata[i][CS_ETM_MAGIC];
+               switch (cs_etm_magic) {
+               case __perf_cs_etmv3_magic:
+                       trace_chan_id = (u8)((metadata[i][CS_ETM_ETMTRACEIDR]) &
+                                            CORESIGHT_TRACE_ID_VAL_MASK);
+                       break;
+               case __perf_cs_etmv4_magic:
+               case __perf_cs_ete_magic:
+                       trace_chan_id = (u8)((metadata[i][CS_ETMV4_TRCTRACEIDR]) &
+                                             CORESIGHT_TRACE_ID_VAL_MASK);
+                       break;
+               default:
+                       /* unknown magic number */
+                       return -EINVAL;
+               }
+               err = cs_etm__map_trace_id(trace_chan_id, metadata[i]);
+               if (err)
+                       return err;
+       }
+       return 0;
+}
+
 int cs_etm__process_auxtrace_info_full(union perf_event *event,
                                       struct perf_session *session)
 {
        struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
        struct cs_etm_auxtrace *etm = NULL;
-       struct int_node *inode;
        struct perf_record_time_conv *tc = &session->time_conv;
        int event_header_size = sizeof(struct perf_event_header);
        int total_size = auxtrace_info->header.size;
        int priv_size = 0;
-       int num_cpu, trcidr_idx;
+       int num_cpu;
        int err = 0;
        int i, j;
        u64 *ptr = NULL;
@@ -2853,23 +2906,13 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
                                cs_etm__create_meta_blk(ptr, &i,
                                                        CS_ETM_PRIV_MAX,
                                                        CS_ETM_NR_TRC_PARAMS_V0);
-
-                       /* The traceID is our handle */
-                       trcidr_idx = CS_ETM_ETMTRACEIDR;
-
                } else if (ptr[i] == __perf_cs_etmv4_magic) {
                        metadata[j] =
                                cs_etm__create_meta_blk(ptr, &i,
                                                        CS_ETMV4_PRIV_MAX,
                                                        CS_ETMV4_NR_TRC_PARAMS_V0);
-
-                       /* The traceID is our handle */
-                       trcidr_idx = CS_ETMV4_TRCTRACEIDR;
                } else if (ptr[i] == __perf_cs_ete_magic) {
                        metadata[j] = cs_etm__create_meta_blk(ptr, &i, CS_ETE_PRIV_MAX, -1);
-
-                       /* ETE shares first part of metadata with ETMv4 */
-                       trcidr_idx = CS_ETMV4_TRCTRACEIDR;
                } else {
                        ui__error("CS ETM Trace: Unrecognised magic number %#"PRIx64". File could be from a newer version of perf.\n",
                                  ptr[i]);
@@ -2881,26 +2924,6 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
                        err = -ENOMEM;
                        goto err_free_metadata;
                }
-
-               /* Get an RB node for this CPU */
-               inode = intlist__findnew(traceid_list, metadata[j][trcidr_idx]);
-
-               /* Something went wrong, no need to continue */
-               if (!inode) {
-                       err = -ENOMEM;
-                       goto err_free_metadata;
-               }
-
-               /*
-                * The node for that CPU should not be taken.
-                * Back out if that's the case.
-                */
-               if (inode->priv) {
-                       err = -EINVAL;
-                       goto err_free_metadata;
-               }
-               /* All good, associate the traceID with the metadata pointer */
-               inode->priv = metadata[j];
        }
 
        /*
@@ -2994,6 +3017,11 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
        if (err)
                goto err_delete_thread;
 
+       /* before aux records are queued, need to map metadata to trace IDs */
+       err = cs_etm__map_trace_ids_metadata(num_cpu, metadata);
+       if (err)
+               goto err_delete_thread;
+
        err = cs_etm__queue_aux_records(session);
        if (err)
                goto err_delete_thread;
index 98a4f71..661f029 100644 (file)
@@ -29,13 +29,17 @@ enum {
 /*
  * Update the version for new format.
  *
- * New version 1 format adds a param count to the per cpu metadata.
+ * Version 1: format adds a param count to the per cpu metadata.
  * This allows easy adding of new metadata parameters.
  * Requires that new params always added after current ones.
  * Also allows client reader to handle file versions that are different by
  * checking the number of params in the file vs the number expected.
+ *
+ * Version 2: Drivers will use PERF_RECORD_AUX_OUTPUT_HW_ID to output
+ * CoreSight Trace ID. ...TRACEIDR metadata will be set to legacy values
+ * but with addition flags.
  */
-#define CS_HEADER_CURRENT_VERSION 1
+#define CS_HEADER_CURRENT_VERSION      2
 
 /* Beginning of header common to both ETMv3 and V4 */
 enum {
@@ -98,6 +102,12 @@ enum {
 };
 
 /*
+ * Check for valid CoreSight trace ID. If an invalid value is present in the metadata,
+ * then IDs are present in the hardware ID packet in the data file.
+ */
+#define CS_IS_VALID_TRACE_ID(id) ((id > 0) && (id < 0x70))
+
+/*
  * ETMv3 exception encoding number:
  * See Embedded Trace Macrocell specification (ARM IHI 0014Q)
  * table 7-12 Encoding of Exception[3:0] for non-ARMv7-M processors.