If working on a per-thread scenario, each etmq needs to have a decoder capable of handling packets from all CPUs in the session. But when working on CPU-wide scenario each etmq only needs to deal with packets generated by the CPU is has been associated with.
As such make the code aware of CPU specifics and allocate the minimum amount of decoder required for the trace session.
Signed-off-by: Mathieu Poirier mathieu.poirier@linaro.org --- tools/perf/util/cs-etm.c | 56 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 11 deletions(-)
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c index 91b77353429e..f7c78c39266c 100644 --- a/tools/perf/util/cs-etm.c +++ b/tools/perf/util/cs-etm.c @@ -119,7 +119,7 @@ static void cs_etm__set_trace_param(struct cs_etm_trace_params *t_params, }
static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params, - struct cs_etm_auxtrace *etm, + struct cs_etm_auxtrace *etm, int cpu, enum cs_etm_decoder_protocol protocol) { int i, ret = 0; @@ -129,8 +129,32 @@ static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params, goto out; }
- for (i = 0; i < etm->num_cpu; i++) - cs_etm__set_trace_param(&t_params[i], etm, i, protocol); + /* + * cpu == -1 is per-thread scenario: setup parameters for all the CPUs. + */ + if (cpu == -1) { + for (i = 0; i < etm->num_cpu; i++) + cs_etm__set_trace_param(&t_params[i], etm, i, protocol); + + goto out; + } + + /* + * CPU-wide scenario: setup the parameter for the CPU that was + * requested. + */ + for (i = 0; i < etm->num_cpu; i++) { + if (cpu == (int)etm->metadata[i][CS_ETM_CPU]) + break; + } + + /* We didn't find a match */ + if (i == etm->num_cpu) { + ret = -EINVAL; + goto out; + } + + cs_etm__set_trace_param(&t_params[0], etm, i, protocol);
out: return ret; @@ -178,7 +202,7 @@ static void cs_etm__dump_event(struct cs_etm_auxtrace *etm, if (!t_params) return;
- if (cs_etm__init_trace_params(t_params, etm, CS_ETM_PROTO_ETMV4i)) + if (cs_etm__init_trace_params(t_params, etm, -1, CS_ETM_PROTO_ETMV4i)) return;
/* Set decoder parameters to simply print the trace packets */ @@ -336,8 +360,10 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u64 address, return len; }
-static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm) +static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm, + int cpu) { + int num_cpu; struct cs_etm_decoder_params d_params; struct cs_etm_trace_params *t_params; struct cs_etm_queue *etmq; @@ -374,12 +400,20 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm) if (!etmq->event_buf) goto out_free;
+ /* + * If working on a per-thread scenario, each etmq needs to have + * a decoder capable of handling packets from all CPUs in the session. + * If working on CPU-wide scenario each etmq needs to deal with the + * CPU it has been assocated with. + */ + num_cpu = etm->timeless_decoding ? etm->num_cpu : 1; + /* Use metadata to fill in trace parameters for trace decoder */ - t_params = zalloc(sizeof(*t_params) * etm->num_cpu); + t_params = zalloc(sizeof(*t_params) * num_cpu); if (!t_params) goto out_free;
- if (cs_etm__init_trace_params(t_params, etm, CS_ETM_PROTO_ETMV4i)) + if (cs_etm__init_trace_params(t_params, etm, cpu, CS_ETM_PROTO_ETMV4i)) goto out_free;
/* Set decoder parameters to decode trace packets */ @@ -387,7 +421,7 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm) CS_ETM_OPERATION_DECODE)) goto out_free;
- etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params); + etmq->decoder = cs_etm_decoder__new(num_cpu, &d_params, t_params);
zfree(&t_params);
@@ -422,13 +456,13 @@ static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm, struct auxtrace_queue *queue, unsigned int queue_nr) { - int ret = 0; + int ret = 0, cpu = queue->cpu; struct cs_etm_queue *etmq = queue->priv;
if (list_empty(&queue->head) || etmq) goto out;
- etmq = cs_etm__alloc_queue(etm); + etmq = cs_etm__alloc_queue(etm, cpu);
if (!etmq) { ret = -ENOMEM; @@ -438,7 +472,7 @@ static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm, queue->priv = etmq; etmq->etm = etm; etmq->queue_nr = queue_nr; - etmq->cpu = queue->cpu; + etmq->cpu = cpu; etmq->tid = queue->tid; etmq->pid = -1; etmq->offset = 0;