perf cs-etm: Move mapping of Trace ID and cpu into helper function

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>
This commit is contained in:
Mike Leach 2023-03-31 06:56:43 +01:00 committed by Arnaldo Carvalho de Melo
parent 84c3a2bb4c
commit 0927729555
4 changed files with 79 additions and 35 deletions

View 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.

View 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;

View 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;

View 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 {
@ -97,6 +101,12 @@ enum {
CS_ETE_PRIV_MAX
};
/*
* 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)