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:
Родитель
84c3a2bb4c
Коммит
0927729555
|
@ -7,9 +7,14 @@
|
||||||
#ifndef _LINUX_CORESIGHT_PMU_H
|
#ifndef _LINUX_CORESIGHT_PMU_H
|
||||||
#define _LINUX_CORESIGHT_PMU_H
|
#define _LINUX_CORESIGHT_PMU_H
|
||||||
|
|
||||||
|
#include <linux/bits.h>
|
||||||
|
|
||||||
#define CORESIGHT_ETM_PMU_NAME "cs_etm"
|
#define CORESIGHT_ETM_PMU_NAME "cs_etm"
|
||||||
#define CORESIGHT_ETM_PMU_SEED 0x10
|
#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
|
* Below are the definition of bit offsets for perf option, and works as
|
||||||
* arbitrary values for all ETM versions.
|
* arbitrary values for all ETM versions.
|
||||||
|
|
|
@ -148,7 +148,8 @@ static void cs_etm__print_auxtrace_info(u64 *val, int num)
|
||||||
for (i = CS_HEADER_VERSION_MAX; cpu < num; cpu++) {
|
for (i = CS_HEADER_VERSION_MAX; cpu < num; cpu++) {
|
||||||
if (version == 0)
|
if (version == 0)
|
||||||
err = cs_etm__print_cpu_metadata_v0(val, &i);
|
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);
|
err = cs_etm__print_cpu_metadata_v1(val, &i);
|
||||||
if (err)
|
if (err)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -196,6 +196,30 @@ int cs_etm__get_pid_fmt(u8 trace_chan_id, u64 *pid_fmt)
|
||||||
return 0;
|
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,
|
void cs_etm__etmq_set_traceid_queue_timestamp(struct cs_etm_queue *etmq,
|
||||||
u8 trace_chan_id)
|
u8 trace_chan_id)
|
||||||
{
|
{
|
||||||
|
@ -2804,17 +2828,46 @@ static bool cs_etm__has_virtual_ts(u64 **metadata, int num_cpu)
|
||||||
return true;
|
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,
|
int cs_etm__process_auxtrace_info_full(union perf_event *event,
|
||||||
struct perf_session *session)
|
struct perf_session *session)
|
||||||
{
|
{
|
||||||
struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
|
struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
|
||||||
struct cs_etm_auxtrace *etm = NULL;
|
struct cs_etm_auxtrace *etm = NULL;
|
||||||
struct int_node *inode;
|
|
||||||
struct perf_record_time_conv *tc = &session->time_conv;
|
struct perf_record_time_conv *tc = &session->time_conv;
|
||||||
int event_header_size = sizeof(struct perf_event_header);
|
int event_header_size = sizeof(struct perf_event_header);
|
||||||
int total_size = auxtrace_info->header.size;
|
int total_size = auxtrace_info->header.size;
|
||||||
int priv_size = 0;
|
int priv_size = 0;
|
||||||
int num_cpu, trcidr_idx;
|
int num_cpu;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
int i, j;
|
int i, j;
|
||||||
u64 *ptr = NULL;
|
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__create_meta_blk(ptr, &i,
|
||||||
CS_ETM_PRIV_MAX,
|
CS_ETM_PRIV_MAX,
|
||||||
CS_ETM_NR_TRC_PARAMS_V0);
|
CS_ETM_NR_TRC_PARAMS_V0);
|
||||||
|
|
||||||
/* The traceID is our handle */
|
|
||||||
trcidr_idx = CS_ETM_ETMTRACEIDR;
|
|
||||||
|
|
||||||
} else if (ptr[i] == __perf_cs_etmv4_magic) {
|
} else if (ptr[i] == __perf_cs_etmv4_magic) {
|
||||||
metadata[j] =
|
metadata[j] =
|
||||||
cs_etm__create_meta_blk(ptr, &i,
|
cs_etm__create_meta_blk(ptr, &i,
|
||||||
CS_ETMV4_PRIV_MAX,
|
CS_ETMV4_PRIV_MAX,
|
||||||
CS_ETMV4_NR_TRC_PARAMS_V0);
|
CS_ETMV4_NR_TRC_PARAMS_V0);
|
||||||
|
|
||||||
/* The traceID is our handle */
|
|
||||||
trcidr_idx = CS_ETMV4_TRCTRACEIDR;
|
|
||||||
} else if (ptr[i] == __perf_cs_ete_magic) {
|
} else if (ptr[i] == __perf_cs_ete_magic) {
|
||||||
metadata[j] = cs_etm__create_meta_blk(ptr, &i, CS_ETE_PRIV_MAX, -1);
|
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 {
|
} else {
|
||||||
ui__error("CS ETM Trace: Unrecognised magic number %#"PRIx64". File could be from a newer version of perf.\n",
|
ui__error("CS ETM Trace: Unrecognised magic number %#"PRIx64". File could be from a newer version of perf.\n",
|
||||||
ptr[i]);
|
ptr[i]);
|
||||||
|
@ -2881,26 +2924,6 @@ int cs_etm__process_auxtrace_info_full(union perf_event *event,
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto err_free_metadata;
|
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)
|
if (err)
|
||||||
goto err_delete_thread;
|
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);
|
err = cs_etm__queue_aux_records(session);
|
||||||
if (err)
|
if (err)
|
||||||
goto err_delete_thread;
|
goto err_delete_thread;
|
||||||
|
|
|
@ -29,13 +29,17 @@ enum {
|
||||||
/*
|
/*
|
||||||
* Update the version for new format.
|
* 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.
|
* This allows easy adding of new metadata parameters.
|
||||||
* Requires that new params always added after current ones.
|
* Requires that new params always added after current ones.
|
||||||
* Also allows client reader to handle file versions that are different by
|
* Also allows client reader to handle file versions that are different by
|
||||||
* checking the number of params in the file vs the number expected.
|
* 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 */
|
/* Beginning of header common to both ETMv3 and V4 */
|
||||||
enum {
|
enum {
|
||||||
|
@ -97,6 +101,12 @@ enum {
|
||||||
CS_ETE_PRIV_MAX
|
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:
|
* ETMv3 exception encoding number:
|
||||||
* See Embedded Trace Macrocell specification (ARM IHI 0014Q)
|
* See Embedded Trace Macrocell specification (ARM IHI 0014Q)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче