If packet processing wants to check ETM version, it needs to access metadata to decide that; but we cannot simply to use CPU logic ID number as index to access metadata sequential array, especially when system have hotplugged out CPUs, the metadata array are only allocated for online CPUs but not offline CPUs, so the CPU logic number doesn't match with its index in the array.
For this reason, a more reliable way to access metadata array is to use traceID to find metadata; by accessing metadata content we can know not only the CPU number but also for ETM version, which can be used for sequential change for setting sample flags for exception packets.
This patch is to change tuple from traceID-CPU# to traceID-metadata, thus it can use the tuple to retrieve metadata pointer according to traceID.
Signed-off-by: Leo Yan leo.yan@linaro.org --- .../perf/util/cs-etm-decoder/cs-etm-decoder.c | 5 +++- tools/perf/util/cs-etm.c | 23 ++++++++++++++----- tools/perf/util/cs-etm.h | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c index 05830fe1fb70..a537e13c45a0 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c @@ -305,6 +305,7 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, { u32 et = 0; struct int_node *inode = NULL; + u64 *metadata;
if (decoder->packet_count >= MAX_BUFFER - 1) return OCSD_RESP_FATAL_SYS_ERR; @@ -314,6 +315,8 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder, if (!inode) return OCSD_RESP_FATAL_SYS_ERR;
+ metadata = inode->priv; + et = decoder->tail; et = (et + 1) & (MAX_BUFFER - 1); decoder->tail = et; @@ -321,7 +324,7 @@ cs_etm_decoder__buffer_packet(struct cs_etm_decoder *decoder,
decoder->packet_buffer[et].sample_type = sample_type; decoder->packet_buffer[et].isa = CS_ETM_ISA_UNKNOWN; - decoder->packet_buffer[et].cpu = *((int *)inode->priv); + decoder->packet_buffer[et].cpu = (int)metadata[CS_ETM_CPU]; decoder->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR; decoder->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR; decoder->packet_buffer[et].instr_count = 0; diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index f07ebc4f57bc..7c1399eda135 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -252,7 +252,7 @@ static void cs_etm__free(struct perf_session *session) cs_etm__free_events(session); session->auxtrace = NULL;
- /* First remove all traceID/CPU# nodes for the RB tree */ + /* First remove all traceID/metadata nodes for the RB tree */ intlist__for_each_entry_safe(inode, tmp, traceid_list) intlist__remove(traceid_list, inode); /* Then the RB tree itself */ @@ -1521,9 +1521,20 @@ int cs_etm__process_auxtrace_info(union perf_event *event, 0xffffffff);
/* - * Create an RB tree for traceID-CPU# tuple. Since the conversion has - * to be made for each packet that gets decoded, optimizing access in - * anything other than a sequential array is worth doing. + * Create an RB tree for traceID-metadata tuple. + * + * The conversion between traceID and CPU logic ID number has to + * be made for each packet that gets decoded: firstly retrive + * metadata pointer from trace ID by using traceID-metadata tuple, + * then read CPU logic ID number in metadata. + * + * It's not safe to directly use CPU logic ID number as index to + * access metadata sequential array, e.g. when system have + * hotplugged out CPUs, the metadata array are only allocated for + * online CPUs but not offline CPUs, thus the CPU logic number is + * not consistent with its index in the arrary. For this reason, + * we need to fallback to use TraceID-metadata tuple as a reliable + * method to access metadata. */ traceid_list = intlist__new(NULL); if (!traceid_list) { @@ -1589,8 +1600,8 @@ int cs_etm__process_auxtrace_info(union perf_event *event, err = -EINVAL; goto err_free_metadata; } - /* All good, associate the traceID with the CPU# */ - inode->priv = &metadata[j][CS_ETM_CPU]; + /* All good, associate the traceID with the metadata pointer */ + inode->priv = metadata[j]; }
/* diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index 37f8d48179ca..a145aafb020a 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -53,7 +53,7 @@ enum { CS_ETMV4_PRIV_MAX, };
-/* RB tree for quick conversion between traceID and CPUs */ +/* RB tree for quick conversion between traceID and metadata pointers */ struct intlist *traceid_list;
#define KiB(x) ((x) * 1024)