Exception packets need their own ISA so the frontend can generate samples directly from them. Currently, ISA initialization is limited to instruction range packets.
Move ISA initialization into cs_etm_decoder__buffer_packet() and use a common helper to obtain it from the OpenCSD element. Populate the ISA for instruction ranges, context updates and exceptions, leaving it unknown for other element types.
Assisted-by: Codex:gpt-6 Signed-off-by: Leo Yan leo.yan@arm.com --- tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 69 +++++++++++++++---------- 1 file changed, 41 insertions(+), 28 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 35ca1a23e12735416d0d412a949595efc5bfe50a..469aba5e596a791289c5bcece132aba7b0baf6c3 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c @@ -368,9 +368,38 @@ cs_etm_decoder__reset_timestamp(struct cs_etm_packet_queue *packet_queue) packet_queue->instr_count = 0; }
+static enum cs_etm_isa +cs_etm_decoder__get_isa(const ocsd_generic_trace_elem *elem) +{ + /* + * OpenCSD preserves ISA and context between output elements, including + * exceptions after a context change with no intervening range. + */ + if (elem->elem_type != OCSD_GEN_TRC_ELEM_PE_CONTEXT && + elem->elem_type != OCSD_GEN_TRC_ELEM_INSTR_RANGE && + elem->elem_type != OCSD_GEN_TRC_ELEM_EXCEPTION) + return CS_ETM_ISA_UNKNOWN; + + switch (elem->isa) { + case ocsd_isa_aarch64: + return CS_ETM_ISA_A64; + case ocsd_isa_arm: + return CS_ETM_ISA_A32; + case ocsd_isa_thumb2: + return CS_ETM_ISA_T32; + case ocsd_isa_tee: + case ocsd_isa_jazelle: + case ocsd_isa_custom: + case ocsd_isa_unknown: + default: + return CS_ETM_ISA_UNKNOWN; + } +} + static ocsd_datapath_resp_t cs_etm_decoder__buffer_packet(struct cs_etm_queue *etmq, struct cs_etm_packet_queue *packet_queue, + const ocsd_generic_trace_elem *elem, const u8 trace_chan_id, enum cs_etm_sample_type sample_type) { @@ -389,7 +418,7 @@ cs_etm_decoder__buffer_packet(struct cs_etm_queue *etmq, packet_queue->packet_count++;
packet_queue->packet_buffer[et].sample_type = sample_type; - packet_queue->packet_buffer[et].isa = CS_ETM_ISA_UNKNOWN; + packet_queue->packet_buffer[et].isa = cs_etm_decoder__get_isa(elem); packet_queue->packet_buffer[et].cpu = cpu; packet_queue->packet_buffer[et].start_addr = CS_ETM_INVAL_ADDR; packet_queue->packet_buffer[et].end_addr = CS_ETM_INVAL_ADDR; @@ -420,31 +449,13 @@ cs_etm_decoder__buffer_range(struct cs_etm_queue *etmq, int ret = 0; struct cs_etm_packet *packet;
- ret = cs_etm_decoder__buffer_packet(etmq, packet_queue, trace_chan_id, - CS_ETM_RANGE); + ret = cs_etm_decoder__buffer_packet(etmq, packet_queue, elem, + trace_chan_id, CS_ETM_RANGE); if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT) return ret;
packet = &packet_queue->packet_buffer[packet_queue->tail];
- switch (elem->isa) { - case ocsd_isa_aarch64: - packet->isa = CS_ETM_ISA_A64; - break; - case ocsd_isa_arm: - packet->isa = CS_ETM_ISA_A32; - break; - case ocsd_isa_thumb2: - packet->isa = CS_ETM_ISA_T32; - break; - case ocsd_isa_tee: - case ocsd_isa_jazelle: - case ocsd_isa_custom: - case ocsd_isa_unknown: - default: - packet->isa = CS_ETM_ISA_UNKNOWN; - } - packet->start_addr = elem->st_addr; packet->end_addr = elem->en_addr; packet->instr_count = elem->num_instr_range; @@ -483,6 +494,7 @@ cs_etm_decoder__buffer_range(struct cs_etm_queue *etmq, static ocsd_datapath_resp_t cs_etm_decoder__buffer_discontinuity(struct cs_etm_queue *etmq, struct cs_etm_packet_queue *queue, + const ocsd_generic_trace_elem *elem, const uint8_t trace_chan_id) { /* @@ -490,7 +502,7 @@ cs_etm_decoder__buffer_discontinuity(struct cs_etm_queue *etmq, * reset time statistics. */ cs_etm_decoder__reset_timestamp(queue); - return cs_etm_decoder__buffer_packet(etmq, queue, trace_chan_id, + return cs_etm_decoder__buffer_packet(etmq, queue, elem, trace_chan_id, CS_ETM_DISCONTINUITY); }
@@ -502,7 +514,7 @@ cs_etm_decoder__buffer_exception(struct cs_etm_queue *etmq, { int ret = 0; struct cs_etm_packet *packet;
- ret = cs_etm_decoder__buffer_packet(etmq, queue, trace_chan_id, + ret = cs_etm_decoder__buffer_packet(etmq, queue, elem, trace_chan_id, CS_ETM_EXCEPTION); if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT) return ret; @@ -516,9 +528,10 @@ cs_etm_decoder__buffer_exception(struct cs_etm_queue *etmq, static ocsd_datapath_resp_t cs_etm_decoder__buffer_exception_ret(struct cs_etm_queue *etmq, struct cs_etm_packet_queue *queue, + const ocsd_generic_trace_elem *elem, const uint8_t trace_chan_id) { - return cs_etm_decoder__buffer_packet(etmq, queue, trace_chan_id, + return cs_etm_decoder__buffer_packet(etmq, queue, elem, trace_chan_id, CS_ETM_EXCEPTION_RET); }
@@ -555,8 +568,8 @@ cs_etm_decoder__set_tid(struct cs_etm_queue *etmq, elem->context.exception_level, tid)) return OCSD_RESP_FATAL_SYS_ERR;
- ret = cs_etm_decoder__buffer_packet(etmq, packet_queue, trace_chan_id, - CS_ETM_CONTEXT); + ret = cs_etm_decoder__buffer_packet(etmq, packet_queue, elem, + trace_chan_id, CS_ETM_CONTEXT); if (ret != OCSD_RESP_CONT && ret != OCSD_RESP_WAIT) return ret;
@@ -597,7 +610,7 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( type == OCSD_GEN_TRC_ELEM_TRACE_ON || type == OCSD_GEN_TRC_ELEM_ADDR_NACC) resp = cs_etm_decoder__buffer_discontinuity(etmq, packet_queue, - trace_chan_id); + elem, trace_chan_id); else if (type == OCSD_GEN_TRC_ELEM_INSTR_RANGE) resp = cs_etm_decoder__buffer_range(etmq, packet_queue, elem, trace_chan_id); @@ -606,7 +619,7 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer( trace_chan_id); else if (type == OCSD_GEN_TRC_ELEM_EXCEPTION_RET) resp = cs_etm_decoder__buffer_exception_ret(etmq, packet_queue, - trace_chan_id); + elem, trace_chan_id); else if (type == OCSD_GEN_TRC_ELEM_TIMESTAMP) resp = cs_etm_decoder__do_hard_timestamp(etmq, elem, trace_chan_id,