This patchset consists of refactoring to allow the decoder to be
created in advance when the AUX records are iterated over. The
AUX record flags are used to communicate whether the data is
formatted or not which is the reason this refactoring is required.
These changes result in some simplifications, removal of early exit
conditions etc.
A change was also made to --dump-raw-trace code to allow the
formatted/unformatted status to persist and for the decoder to
not be continually deleted and recreated.
The changes apply on top of the previous patchset "[PATCH v7 0/2] perf
cs-etm: Split Coresight decode by aux records".
Changes since v1:
* Change 'decoders_per_cpu' variable name to 'decoders' and add a comment
* Add a warning that piped mode is best effort, suggested by Suzuki
James Clark (6):
perf cs-etm: Refactor initialisation of kernel start address
perf cs-etm: Split setup and timestamp search functions
perf cs-etm: Only setup queues when they are modified
perf cs-etm: Suppress printing when resetting decoder
perf cs-etm: Use existing decoder instead of resetting it
perf cs-etm: Pass unformatted flag to decoder
.../perf/util/cs-etm-decoder/cs-etm-decoder.c | 14 +-
tools/perf/util/cs-etm.c | 185 +++++++++---------
2 files changed, 97 insertions(+), 102 deletions(-)
--
2.28.0
The TRBE (Trace Buffer Extension) feature allows a separate trace buffer
for each trace source, therefore the trace wouldn't need to be
formatted. The driver was introduced in commit 3fbf7f011f24
("coresight: sink: Add TRBE driver").
The formatted/unformatted mode is encoded in one of the flags of the
AUX record. The first AUX record encountered for each event is used to
determine the mode, and this will persist for the remaining trace that
is either decoded or dumped.
Signed-off-by: James Clark <[email protected]>
---
.../perf/util/cs-etm-decoder/cs-etm-decoder.c | 4 +-
tools/perf/util/cs-etm.c | 53 ++++++++++++++-----
2 files changed, 42 insertions(+), 15 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 ed1f0326f859..9c9039ae6989 100644
--- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
+++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
@@ -687,7 +687,7 @@ cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
}
struct cs_etm_decoder *
-cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
+cs_etm_decoder__new(int decoders, struct cs_etm_decoder_params *d_params,
struct cs_etm_trace_params t_params[])
{
struct cs_etm_decoder *decoder;
@@ -732,7 +732,7 @@ cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
/* init raw frame logging if required */
cs_etm_decoder__init_raw_frame_logging(d_params, decoder);
- for (i = 0; i < num_cpu; i++) {
+ for (i = 0; i < decoders; i++) {
ret = cs_etm_decoder__create_etm_decoder(d_params,
&t_params[i],
decoder);
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 760050ea936d..f4b2bff533f3 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -461,13 +461,14 @@ static void cs_etm__set_trace_param_etmv4(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 decoders)
{
int i;
u32 etmidr;
u64 architecture;
- for (i = 0; i < etm->num_cpu; i++) {
+ for (i = 0; i < decoders; i++) {
architecture = etm->metadata[i][CS_ETM_MAGIC];
switch (architecture) {
@@ -488,7 +489,8 @@ static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params,
static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
struct cs_etm_queue *etmq,
- enum cs_etm_decoder_operation mode)
+ enum cs_etm_decoder_operation mode,
+ bool formatted)
{
int ret = -EINVAL;
@@ -498,7 +500,7 @@ static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
d_params->packet_printer = cs_etm__packet_dump;
d_params->operation = mode;
d_params->data = etmq;
- d_params->formatted = true;
+ d_params->formatted = formatted;
d_params->fsyncs = false;
d_params->hsyncs = false;
d_params->frame_aligned = true;
@@ -720,11 +722,17 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
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,
+ bool formatted)
{
struct cs_etm_decoder_params d_params;
struct cs_etm_trace_params *t_params = NULL;
struct cs_etm_queue *etmq;
+ /*
+ * Each queue can only contain data from one CPU when unformatted, so only one decoder is
+ * needed.
+ */
+ int decoders = formatted ? etm->num_cpu : 1;
etmq = zalloc(sizeof(*etmq));
if (!etmq)
@@ -735,21 +743,23 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
goto out_free;
/* 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) * decoders);
if (!t_params)
goto out_free;
- if (cs_etm__init_trace_params(t_params, etm))
+ if (cs_etm__init_trace_params(t_params, etm, decoders))
goto out_free;
/* Set decoder parameters to decode trace packets */
if (cs_etm__init_decoder_params(&d_params, etmq,
dump_trace ? CS_ETM_OPERATION_PRINT :
- CS_ETM_OPERATION_DECODE))
+ CS_ETM_OPERATION_DECODE,
+ formatted))
goto out_free;
- etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
+ etmq->decoder = cs_etm_decoder__new(decoders, &d_params,
+ t_params);
if (!etmq->decoder)
goto out_free;
@@ -777,14 +787,15 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
struct auxtrace_queue *queue,
- unsigned int queue_nr)
+ unsigned int queue_nr,
+ bool formatted)
{
struct cs_etm_queue *etmq = queue->priv;
if (list_empty(&queue->head) || etmq)
return 0;
- etmq = cs_etm__alloc_queue(etm);
+ etmq = cs_etm__alloc_queue(etm, formatted);
if (!etmq)
return -ENOMEM;
@@ -2430,8 +2441,14 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session,
if (err)
return err;
+ /*
+ * Knowing if the trace is formatted or not requires a lookup of
+ * the aux record so only works in non-piped mode where data is
+ * queued in cs_etm__queue_aux_records(). Always assume
+ * formatted in piped mode (true).
+ */
err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
- idx);
+ idx, true);
if (err)
return err;
@@ -2678,6 +2695,7 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
union perf_event auxtrace_fragment;
__u64 aux_offset, aux_size;
__u32 idx;
+ bool formatted;
struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
struct cs_etm_auxtrace,
@@ -2745,7 +2763,9 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
return err;
idx = auxtrace_event->idx;
- return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], idx);
+ formatted = !(aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW);
+ return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
+ idx, formatted);
}
/* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */
@@ -3034,6 +3054,13 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
goto err_delete_thread;
etm->data_queued = etm->queues.populated;
+ /*
+ * Print warning in pipe mode, see cs_etm__process_auxtrace_event() and
+ * cs_etm__queue_aux_fragment() for details relating to limitations.
+ */
+ if (!etm->data_queued)
+ pr_warning("CS ETM warning: Coresight decode and TRBE support requires random file access.\n"
+ "Continuing with best effort decoding in piped mode.\n\n");
return 0;
--
2.28.0
The kernel start address is already cached in the machine struct once it
is initialised, so storing it in the cs_etm struct is unnecessary.
It also depends on kernel maps being available to be initialised.
Therefore cs_etm__setup_queues() isn't an appropriate place to call it
because it could be called before processing starts. It would be better
to initialise it at the point when it is needed, then we can be sure
that all the necessary maps are available. Also by calling
machine__kernel_start() multiple times it can be initialised at some
point, even if it failed to initialise previously due to missing maps.
In a later commit cs_etm__setup_queues() will be moved which is the
motivation for this change.
Reviewed-by: Mathieu Poirier <[email protected]>
Signed-off-by: James Clark <[email protected]>
---
tools/perf/util/cs-etm.c | 6 +-----
1 file changed, 1 insertion(+), 5 deletions(-)
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index bc1f64873c8f..4c69ef391f60 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -62,7 +62,6 @@ struct cs_etm_auxtrace {
u64 instructions_sample_period;
u64 instructions_id;
u64 **metadata;
- u64 kernel_start;
unsigned int pmu_type;
};
@@ -691,7 +690,7 @@ static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
machine = etmq->etm->machine;
- if (address >= etmq->etm->kernel_start) {
+ if (address >= machine__kernel_start(machine)) {
if (machine__is_host(machine))
return PERF_RECORD_MISC_KERNEL;
else
@@ -901,9 +900,6 @@ static int cs_etm__setup_queues(struct cs_etm_auxtrace *etm)
unsigned int i;
int ret;
- if (!etm->kernel_start)
- etm->kernel_start = machine__kernel_start(etm->machine);
-
for (i = 0; i < etm->queues.nr_queues; i++) {
ret = cs_etm__setup_queue(etm, &etm->queues.queue_array[i], i);
if (ret)
--
2.28.0
On Wed, Jul 21, 2021 at 04:02:02PM +0100, James Clark wrote:
> The TRBE (Trace Buffer Extension) feature allows a separate trace buffer
> for each trace source, therefore the trace wouldn't need to be
> formatted. The driver was introduced in commit 3fbf7f011f24
> ("coresight: sink: Add TRBE driver").
>
> The formatted/unformatted mode is encoded in one of the flags of the
> AUX record. The first AUX record encountered for each event is used to
> determine the mode, and this will persist for the remaining trace that
> is either decoded or dumped.
>
> Signed-off-by: James Clark <[email protected]>
> ---
> .../perf/util/cs-etm-decoder/cs-etm-decoder.c | 4 +-
> tools/perf/util/cs-etm.c | 53 ++++++++++++++-----
> 2 files changed, 42 insertions(+), 15 deletions(-)
>
Reviewed-by: Mathieu Poirier <[email protected]>
Arnaldo, please consider adding this set to your tree.
Thanks,
Mathieu
> 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 ed1f0326f859..9c9039ae6989 100644
> --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> @@ -687,7 +687,7 @@ cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
> }
>
> struct cs_etm_decoder *
> -cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
> +cs_etm_decoder__new(int decoders, struct cs_etm_decoder_params *d_params,
> struct cs_etm_trace_params t_params[])
> {
> struct cs_etm_decoder *decoder;
> @@ -732,7 +732,7 @@ cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
> /* init raw frame logging if required */
> cs_etm_decoder__init_raw_frame_logging(d_params, decoder);
>
> - for (i = 0; i < num_cpu; i++) {
> + for (i = 0; i < decoders; i++) {
> ret = cs_etm_decoder__create_etm_decoder(d_params,
> &t_params[i],
> decoder);
> diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> index 760050ea936d..f4b2bff533f3 100644
> --- a/tools/perf/util/cs-etm.c
> +++ b/tools/perf/util/cs-etm.c
> @@ -461,13 +461,14 @@ static void cs_etm__set_trace_param_etmv4(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 decoders)
> {
> int i;
> u32 etmidr;
> u64 architecture;
>
> - for (i = 0; i < etm->num_cpu; i++) {
> + for (i = 0; i < decoders; i++) {
> architecture = etm->metadata[i][CS_ETM_MAGIC];
>
> switch (architecture) {
> @@ -488,7 +489,8 @@ static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params,
>
> static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
> struct cs_etm_queue *etmq,
> - enum cs_etm_decoder_operation mode)
> + enum cs_etm_decoder_operation mode,
> + bool formatted)
> {
> int ret = -EINVAL;
>
> @@ -498,7 +500,7 @@ static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
> d_params->packet_printer = cs_etm__packet_dump;
> d_params->operation = mode;
> d_params->data = etmq;
> - d_params->formatted = true;
> + d_params->formatted = formatted;
> d_params->fsyncs = false;
> d_params->hsyncs = false;
> d_params->frame_aligned = true;
> @@ -720,11 +722,17 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
> 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,
> + bool formatted)
> {
> struct cs_etm_decoder_params d_params;
> struct cs_etm_trace_params *t_params = NULL;
> struct cs_etm_queue *etmq;
> + /*
> + * Each queue can only contain data from one CPU when unformatted, so only one decoder is
> + * needed.
> + */
> + int decoders = formatted ? etm->num_cpu : 1;
>
> etmq = zalloc(sizeof(*etmq));
> if (!etmq)
> @@ -735,21 +743,23 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
> goto out_free;
>
> /* 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) * decoders);
>
> if (!t_params)
> goto out_free;
>
> - if (cs_etm__init_trace_params(t_params, etm))
> + if (cs_etm__init_trace_params(t_params, etm, decoders))
> goto out_free;
>
> /* Set decoder parameters to decode trace packets */
> if (cs_etm__init_decoder_params(&d_params, etmq,
> dump_trace ? CS_ETM_OPERATION_PRINT :
> - CS_ETM_OPERATION_DECODE))
> + CS_ETM_OPERATION_DECODE,
> + formatted))
> goto out_free;
>
> - etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
> + etmq->decoder = cs_etm_decoder__new(decoders, &d_params,
> + t_params);
>
> if (!etmq->decoder)
> goto out_free;
> @@ -777,14 +787,15 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
>
> static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
> struct auxtrace_queue *queue,
> - unsigned int queue_nr)
> + unsigned int queue_nr,
> + bool formatted)
> {
> struct cs_etm_queue *etmq = queue->priv;
>
> if (list_empty(&queue->head) || etmq)
> return 0;
>
> - etmq = cs_etm__alloc_queue(etm);
> + etmq = cs_etm__alloc_queue(etm, formatted);
>
> if (!etmq)
> return -ENOMEM;
> @@ -2430,8 +2441,14 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session,
> if (err)
> return err;
>
> + /*
> + * Knowing if the trace is formatted or not requires a lookup of
> + * the aux record so only works in non-piped mode where data is
> + * queued in cs_etm__queue_aux_records(). Always assume
> + * formatted in piped mode (true).
> + */
> err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
> - idx);
> + idx, true);
> if (err)
> return err;
>
> @@ -2678,6 +2695,7 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
> union perf_event auxtrace_fragment;
> __u64 aux_offset, aux_size;
> __u32 idx;
> + bool formatted;
>
> struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
> struct cs_etm_auxtrace,
> @@ -2745,7 +2763,9 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
> return err;
>
> idx = auxtrace_event->idx;
> - return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], idx);
> + formatted = !(aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW);
> + return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
> + idx, formatted);
> }
>
> /* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */
> @@ -3034,6 +3054,13 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
> goto err_delete_thread;
>
> etm->data_queued = etm->queues.populated;
> + /*
> + * Print warning in pipe mode, see cs_etm__process_auxtrace_event() and
> + * cs_etm__queue_aux_fragment() for details relating to limitations.
> + */
> + if (!etm->data_queued)
> + pr_warning("CS ETM warning: Coresight decode and TRBE support requires random file access.\n"
> + "Continuing with best effort decoding in piped mode.\n\n");
>
> return 0;
>
> --
> 2.28.0
>
Em Wed, Jul 21, 2021 at 10:05:23AM -0600, Mathieu Poirier escreveu:
> On Wed, Jul 21, 2021 at 04:02:02PM +0100, James Clark wrote:
> > The TRBE (Trace Buffer Extension) feature allows a separate trace buffer
> > for each trace source, therefore the trace wouldn't need to be
> > formatted. The driver was introduced in commit 3fbf7f011f24
> > ("coresight: sink: Add TRBE driver").
> >
> > The formatted/unformatted mode is encoded in one of the flags of the
> > AUX record. The first AUX record encountered for each event is used to
> > determine the mode, and this will persist for the remaining trace that
> > is either decoded or dumped.
> >
> > Signed-off-by: James Clark <[email protected]>
> > ---
> > .../perf/util/cs-etm-decoder/cs-etm-decoder.c | 4 +-
> > tools/perf/util/cs-etm.c | 53 ++++++++++++++-----
> > 2 files changed, 42 insertions(+), 15 deletions(-)
> >
>
> Reviewed-by: Mathieu Poirier <[email protected]>
>
> Arnaldo, please consider adding this set to your tree.
Thanks, applied to perf/core.
- Arnaldo
> Thanks,
> Mathieu
>
> > 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 ed1f0326f859..9c9039ae6989 100644
> > --- a/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> > +++ b/tools/perf/util/cs-etm-decoder/cs-etm-decoder.c
> > @@ -687,7 +687,7 @@ cs_etm_decoder__create_etm_decoder(struct cs_etm_decoder_params *d_params,
> > }
> >
> > struct cs_etm_decoder *
> > -cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
> > +cs_etm_decoder__new(int decoders, struct cs_etm_decoder_params *d_params,
> > struct cs_etm_trace_params t_params[])
> > {
> > struct cs_etm_decoder *decoder;
> > @@ -732,7 +732,7 @@ cs_etm_decoder__new(int num_cpu, struct cs_etm_decoder_params *d_params,
> > /* init raw frame logging if required */
> > cs_etm_decoder__init_raw_frame_logging(d_params, decoder);
> >
> > - for (i = 0; i < num_cpu; i++) {
> > + for (i = 0; i < decoders; i++) {
> > ret = cs_etm_decoder__create_etm_decoder(d_params,
> > &t_params[i],
> > decoder);
> > diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
> > index 760050ea936d..f4b2bff533f3 100644
> > --- a/tools/perf/util/cs-etm.c
> > +++ b/tools/perf/util/cs-etm.c
> > @@ -461,13 +461,14 @@ static void cs_etm__set_trace_param_etmv4(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 decoders)
> > {
> > int i;
> > u32 etmidr;
> > u64 architecture;
> >
> > - for (i = 0; i < etm->num_cpu; i++) {
> > + for (i = 0; i < decoders; i++) {
> > architecture = etm->metadata[i][CS_ETM_MAGIC];
> >
> > switch (architecture) {
> > @@ -488,7 +489,8 @@ static int cs_etm__init_trace_params(struct cs_etm_trace_params *t_params,
> >
> > static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
> > struct cs_etm_queue *etmq,
> > - enum cs_etm_decoder_operation mode)
> > + enum cs_etm_decoder_operation mode,
> > + bool formatted)
> > {
> > int ret = -EINVAL;
> >
> > @@ -498,7 +500,7 @@ static int cs_etm__init_decoder_params(struct cs_etm_decoder_params *d_params,
> > d_params->packet_printer = cs_etm__packet_dump;
> > d_params->operation = mode;
> > d_params->data = etmq;
> > - d_params->formatted = true;
> > + d_params->formatted = formatted;
> > d_params->fsyncs = false;
> > d_params->hsyncs = false;
> > d_params->frame_aligned = true;
> > @@ -720,11 +722,17 @@ static u32 cs_etm__mem_access(struct cs_etm_queue *etmq, u8 trace_chan_id,
> > 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,
> > + bool formatted)
> > {
> > struct cs_etm_decoder_params d_params;
> > struct cs_etm_trace_params *t_params = NULL;
> > struct cs_etm_queue *etmq;
> > + /*
> > + * Each queue can only contain data from one CPU when unformatted, so only one decoder is
> > + * needed.
> > + */
> > + int decoders = formatted ? etm->num_cpu : 1;
> >
> > etmq = zalloc(sizeof(*etmq));
> > if (!etmq)
> > @@ -735,21 +743,23 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
> > goto out_free;
> >
> > /* 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) * decoders);
> >
> > if (!t_params)
> > goto out_free;
> >
> > - if (cs_etm__init_trace_params(t_params, etm))
> > + if (cs_etm__init_trace_params(t_params, etm, decoders))
> > goto out_free;
> >
> > /* Set decoder parameters to decode trace packets */
> > if (cs_etm__init_decoder_params(&d_params, etmq,
> > dump_trace ? CS_ETM_OPERATION_PRINT :
> > - CS_ETM_OPERATION_DECODE))
> > + CS_ETM_OPERATION_DECODE,
> > + formatted))
> > goto out_free;
> >
> > - etmq->decoder = cs_etm_decoder__new(etm->num_cpu, &d_params, t_params);
> > + etmq->decoder = cs_etm_decoder__new(decoders, &d_params,
> > + t_params);
> >
> > if (!etmq->decoder)
> > goto out_free;
> > @@ -777,14 +787,15 @@ static struct cs_etm_queue *cs_etm__alloc_queue(struct cs_etm_auxtrace *etm)
> >
> > static int cs_etm__setup_queue(struct cs_etm_auxtrace *etm,
> > struct auxtrace_queue *queue,
> > - unsigned int queue_nr)
> > + unsigned int queue_nr,
> > + bool formatted)
> > {
> > struct cs_etm_queue *etmq = queue->priv;
> >
> > if (list_empty(&queue->head) || etmq)
> > return 0;
> >
> > - etmq = cs_etm__alloc_queue(etm);
> > + etmq = cs_etm__alloc_queue(etm, formatted);
> >
> > if (!etmq)
> > return -ENOMEM;
> > @@ -2430,8 +2441,14 @@ static int cs_etm__process_auxtrace_event(struct perf_session *session,
> > if (err)
> > return err;
> >
> > + /*
> > + * Knowing if the trace is formatted or not requires a lookup of
> > + * the aux record so only works in non-piped mode where data is
> > + * queued in cs_etm__queue_aux_records(). Always assume
> > + * formatted in piped mode (true).
> > + */
> > err = cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
> > - idx);
> > + idx, true);
> > if (err)
> > return err;
> >
> > @@ -2678,6 +2695,7 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
> > union perf_event auxtrace_fragment;
> > __u64 aux_offset, aux_size;
> > __u32 idx;
> > + bool formatted;
> >
> > struct cs_etm_auxtrace *etm = container_of(session->auxtrace,
> > struct cs_etm_auxtrace,
> > @@ -2745,7 +2763,9 @@ static int cs_etm__queue_aux_fragment(struct perf_session *session, off_t file_o
> > return err;
> >
> > idx = auxtrace_event->idx;
> > - return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx], idx);
> > + formatted = !(aux_event->flags & PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW);
> > + return cs_etm__setup_queue(etm, &etm->queues.queue_array[idx],
> > + idx, formatted);
> > }
> >
> > /* Wasn't inside this buffer, but there were no parse errors. 1 == 'not found' */
> > @@ -3034,6 +3054,13 @@ int cs_etm__process_auxtrace_info(union perf_event *event,
> > goto err_delete_thread;
> >
> > etm->data_queued = etm->queues.populated;
> > + /*
> > + * Print warning in pipe mode, see cs_etm__process_auxtrace_event() and
> > + * cs_etm__queue_aux_fragment() for details relating to limitations.
> > + */
> > + if (!etm->data_queued)
> > + pr_warning("CS ETM warning: Coresight decode and TRBE support requires random file access.\n"
> > + "Continuing with best effort decoding in piped mode.\n\n");
> >
> > return 0;
> >
> > --
> > 2.28.0
> >
--
- Arnaldo