Auxtrace events are associated with auxtrace_queues. The auxtrace queues are extended using the "priv" field to point to a cs-etm specific structure associated with each queue.
This patch adds functions to allocate and free these structures, including instantiating the trace decoder library interface, and providing the function used to register a memory access function with the decoder library.
Signed-off-by: Tor Jeremiassen tor@ti.com --- tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 32 ++++++++++ tools/perf/util/cs-etm-decoder/cs-etm-decoder.h | 4 ++ tools/perf/util/cs-etm.c | 80 +++++++++++++++++++++++++ tools/perf/util/cs-etm.h | 4 ++ 4 files changed, 120 insertions(+)
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 1345eda..cfd18ec 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c @@ -54,6 +54,38 @@ struct cs_etm_decoder { struct list_head channel_list; };
+static uint32_t cs_etm_decoder__mem_access(const void *context, + const ocsd_vaddr_t address, + const ocsd_mem_space_acc_t mem_space, + const uint32_t req_size, + uint8_t *buffer) +{ + struct cs_etm_decoder *decoder = (struct cs_etm_decoder *) context; + (void) mem_space; + + return decoder->mem_access(decoder->state.data, + address, + req_size, + buffer); +} + +int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder, + uint64_t start, uint64_t end, + cs_etm_mem_cb_type cb_func) +{ + int err; + + decoder->mem_access = cb_func; + err = ocsd_dt_add_callback_mem_acc(decoder->dcd_tree, start, end, + OCSD_MEM_SPACE_ANY, + cs_etm_decoder__mem_access, + decoder); + if (err) + return -CS_ETM_ERR_DECODER; + + return 0; +} + const struct cs_etm_state * cs_etm_decoder__process_data_block(struct cs_etm_decoder *decoder, uint64_t indx, const uint8_t *buf, diff --git a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h index daaa217..b53dbed 100644 --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.h @@ -122,6 +122,10 @@ cs_etm_decoder__new(uint32_t num_cpu,
void cs_etm_decoder__free(struct cs_etm_decoder *decoder);
+int cs_etm_decoder__add_mem_access_cb(struct cs_etm_decoder *decoder, + uint64_t start, uint64_t end, + cs_etm_mem_cb_type cb_func); + int cs_etm_decoder__create_etmv4i_decoder(struct cs_etm_decoder_params *d_params, struct cs_etm_trace_params *t_params, diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 527733a..62556a7 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -165,6 +165,8 @@ static void cs_etm__free_queue(void *priv) return;
thread__zput(etmq->thread); + cs_etm_decoder__free(etmq->decoder); + zfree(&etmq->event_buf); free(etmq); }
@@ -208,6 +210,84 @@ static void cs_etm__free(struct perf_session *session) zfree(&aux); }
+struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, + unsigned int queue_nr) +{ + struct cs_etm_decoder_params d_params; + struct cs_etm_trace_params *t_params; + struct cs_etm_queue *etmq; + size_t i; + + etmq = zalloc(sizeof(*etmq)); + if (!etmq) + return NULL; + + etmq->event_buf = malloc(PERF_SAMPLE_MAX_SIZE); + if (!etmq->event_buf) + goto out_free; + + etmq->etm = etm; + etmq->queue_nr = queue_nr; + etmq->pid = -1; + etmq->tid = -1; + etmq->cpu = -1; + etmq->stop = false; + + /* Use metadata to fill in trace parameters for trace decoder */ + t_params = zalloc(sizeof(*t_params) * etm->num_cpu); + + if (!t_params) + goto out_free; + + for (i = 0; i < etm->num_cpu; i++) { + t_params[i].reg_idr0 = etm->metadata[i][CS_ETMV4_TRCIDR0]; + t_params[i].reg_idr1 = etm->metadata[i][CS_ETMV4_TRCIDR1]; + t_params[i].reg_idr2 = etm->metadata[i][CS_ETMV4_TRCIDR2]; + t_params[i].reg_idr8 = etm->metadata[i][CS_ETMV4_TRCIDR8]; + t_params[i].reg_configr = etm->metadata[i][CS_ETMV4_TRCCONFIGR]; + t_params[i].reg_traceidr = + etm->metadata[i][CS_ETMV4_TRCTRACEIDR]; + t_params[i].protocol = CS_ETM_PROTO_ETMV4i; + } + + /* Set decoder parameters to simply print the trace packets */ + d_params.packet_printer = cs_etm__packet_dump; + d_params.operation = CS_ETM_OPERATION_DECODE; + d_params.formatted = true; + d_params.fsyncs = false; + d_params.hsyncs = false; + d_params.frame_aligned = true; + d_params.data = etmq; + + etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params); + + zfree(&t_params); + + if (!etmq->decoder) + goto out_free; + + /* + * Register a function to handle all memory accesses required by + * the trace decoder library. + */ + if (cs_etm_decoder__add_mem_access_cb(etmq->decoder, + 0x0L, ((u64) -1L), + cs_etm__mem_access)) + goto out_free_decoder; + + etmq->offset = 0; + etmq->eot = false; + + return etmq; + +out_free_decoder: + cs_etm_decoder__free(etmq->decoder); +out_free: + zfree(&etmq->event_buf); + free(etmq); + return NULL; +} + struct cs_etm_queue *cs_etm__cpu_to_etmq(struct cs_etm_auxtrace *etm, int cpu) { int q, j; diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h index 846cd48..0bb35d6 100644 --- a/tools/perf/util/cs-etm.h +++ b/tools/perf/util/cs-etm.h @@ -102,4 +102,8 @@ uint32_t cs_etm__mem_access(struct cs_etm_queue *etmq, uint64_t address, size_t size, uint8_t *buffer);
struct cs_etm_queue *cs_etm__cpu_to_etmq(struct cs_etm_auxtrace *etm, int cpu); + +struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, + unsigned int queue_nr); + #endif