diff mbox series

[1/1] perf arm-spe: Inject SPE samples in perf-inject

Message ID 20211105104130.28186-2-german.gomez@arm.com (mailing list archive)
State New, archived
Headers show
Series perf arm-spe: Inject SPE samples in perf-inject | expand

Commit Message

German Gomez Nov. 5, 2021, 10:41 a.m. UTC
Inject synthesized SPE samples during perf-inject run.

Signed-off-by: German Gomez <german.gomez@arm.com>
---
 tools/perf/util/arm-spe.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

Comments

James Clark Nov. 8, 2021, 8:39 p.m. UTC | #1
On 05/11/2021 10:41, German Gomez wrote:
> Inject synthesized SPE samples during perf-inject run.
> 
> Signed-off-by: German Gomez <german.gomez@arm.com>

Reviewed-by: James Clark <james.clark@arm.com>
> ---
>  tools/perf/util/arm-spe.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
> index 58b7069c5..7054f2315 100644
> --- a/tools/perf/util/arm-spe.c
> +++ b/tools/perf/util/arm-spe.c
> @@ -51,6 +51,7 @@ struct arm_spe {
>  	u8				timeless_decoding;
>  	u8				data_queued;
>  
> +	u64				sample_type;
>  	u8				sample_flc;
>  	u8				sample_llc;
>  	u8				sample_tlb;
> @@ -248,6 +249,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
>  	event->sample.header.size = sizeof(struct perf_event_header);
>  }
>  
> +static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
> +{
> +	event->header.size = perf_event__sample_event_size(sample, type, 0);
> +	return perf_event__synthesize_sample(event, type, 0, sample);
> +}
> +
>  static inline int
>  arm_spe_deliver_synth_event(struct arm_spe *spe,
>  			    struct arm_spe_queue *speq __maybe_unused,
> @@ -256,6 +263,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe,
>  {
>  	int ret;
>  
> +	if (spe->synth_opts.inject) {
> +		ret = arm_spe__inject_event(event, sample, spe->sample_type);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	ret = perf_session__deliver_synth_event(spe->session, event, sample);
>  	if (ret)
>  		pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
> @@ -920,6 +933,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
>  	else
>  		attr.sample_type |= PERF_SAMPLE_TIME;
>  
> +	spe->sample_type = attr.sample_type;
> +
>  	attr.exclude_user = evsel->core.attr.exclude_user;
>  	attr.exclude_kernel = evsel->core.attr.exclude_kernel;
>  	attr.exclude_hv = evsel->core.attr.exclude_hv;
>
Arnaldo Carvalho de Melo Nov. 17, 2021, 3:27 p.m. UTC | #2
Em Mon, Nov 08, 2021 at 08:39:58PM +0000, James Clark escreveu:
> 
> 
> On 05/11/2021 10:41, German Gomez wrote:
> > Inject synthesized SPE samples during perf-inject run.
> > 
> > Signed-off-by: German Gomez <german.gomez@arm.com>
> 
> Reviewed-by: James Clark <james.clark@arm.com>


Thanks, applied.

- Arnaldo


> > ---
> >  tools/perf/util/arm-spe.c | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
> > index 58b7069c5..7054f2315 100644
> > --- a/tools/perf/util/arm-spe.c
> > +++ b/tools/perf/util/arm-spe.c
> > @@ -51,6 +51,7 @@ struct arm_spe {
> >  	u8				timeless_decoding;
> >  	u8				data_queued;
> >  
> > +	u64				sample_type;
> >  	u8				sample_flc;
> >  	u8				sample_llc;
> >  	u8				sample_tlb;
> > @@ -248,6 +249,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
> >  	event->sample.header.size = sizeof(struct perf_event_header);
> >  }
> >  
> > +static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
> > +{
> > +	event->header.size = perf_event__sample_event_size(sample, type, 0);
> > +	return perf_event__synthesize_sample(event, type, 0, sample);
> > +}
> > +
> >  static inline int
> >  arm_spe_deliver_synth_event(struct arm_spe *spe,
> >  			    struct arm_spe_queue *speq __maybe_unused,
> > @@ -256,6 +263,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe,
> >  {
> >  	int ret;
> >  
> > +	if (spe->synth_opts.inject) {
> > +		ret = arm_spe__inject_event(event, sample, spe->sample_type);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> >  	ret = perf_session__deliver_synth_event(spe->session, event, sample);
> >  	if (ret)
> >  		pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
> > @@ -920,6 +933,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
> >  	else
> >  		attr.sample_type |= PERF_SAMPLE_TIME;
> >  
> > +	spe->sample_type = attr.sample_type;
> > +
> >  	attr.exclude_user = evsel->core.attr.exclude_user;
> >  	attr.exclude_kernel = evsel->core.attr.exclude_kernel;
> >  	attr.exclude_hv = evsel->core.attr.exclude_hv;
> >
Arnaldo Carvalho de Melo Nov. 17, 2021, 3:29 p.m. UTC | #3
Em Mon, Nov 08, 2021 at 08:39:58PM +0000, James Clark escreveu:
> 
> 
> On 05/11/2021 10:41, German Gomez wrote:
> > Inject synthesized SPE samples during perf-inject run.
> > 
> > Signed-off-by: German Gomez <german.gomez@arm.com>
> 
> Reviewed-by: James Clark <james.clark@arm.com>

Next time please expand this explanations a bit more: why should we
inject such samples? Is this enabling some new mode of operation, fixing
something, what is an example of output before this patch and after it?

- Arnaldo

> > ---
> >  tools/perf/util/arm-spe.c | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
> > index 58b7069c5..7054f2315 100644
> > --- a/tools/perf/util/arm-spe.c
> > +++ b/tools/perf/util/arm-spe.c
> > @@ -51,6 +51,7 @@ struct arm_spe {
> >  	u8				timeless_decoding;
> >  	u8				data_queued;
> >  
> > +	u64				sample_type;
> >  	u8				sample_flc;
> >  	u8				sample_llc;
> >  	u8				sample_tlb;
> > @@ -248,6 +249,12 @@ static void arm_spe_prep_sample(struct arm_spe *spe,
> >  	event->sample.header.size = sizeof(struct perf_event_header);
> >  }
> >  
> > +static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
> > +{
> > +	event->header.size = perf_event__sample_event_size(sample, type, 0);
> > +	return perf_event__synthesize_sample(event, type, 0, sample);
> > +}
> > +
> >  static inline int
> >  arm_spe_deliver_synth_event(struct arm_spe *spe,
> >  			    struct arm_spe_queue *speq __maybe_unused,
> > @@ -256,6 +263,12 @@ arm_spe_deliver_synth_event(struct arm_spe *spe,
> >  {
> >  	int ret;
> >  
> > +	if (spe->synth_opts.inject) {
> > +		ret = arm_spe__inject_event(event, sample, spe->sample_type);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> >  	ret = perf_session__deliver_synth_event(spe->session, event, sample);
> >  	if (ret)
> >  		pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
> > @@ -920,6 +933,8 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
> >  	else
> >  		attr.sample_type |= PERF_SAMPLE_TIME;
> >  
> > +	spe->sample_type = attr.sample_type;
> > +
> >  	attr.exclude_user = evsel->core.attr.exclude_user;
> >  	attr.exclude_kernel = evsel->core.attr.exclude_kernel;
> >  	attr.exclude_hv = evsel->core.attr.exclude_hv;
> >
German Gomez Nov. 17, 2021, 4:27 p.m. UTC | #4
Hi Arnaldo,

On 17/11/2021 15:29, Arnaldo Carvalho de Melo wrote:
> [...]
> Next time please expand this explanations a bit more: why should we
> inject such samples? Is this enabling some new mode of operation, fixing
> something, what is an example of output before this patch and after it?
I will keep this in mind, thanks. In this case the support was missing
and I included the context in the cover letter but not the commit msg.

Thanks,
German
>
> - Arnaldo
>
> [...]
Arnaldo Carvalho de Melo Nov. 17, 2021, 5:24 p.m. UTC | #5
Em Wed, Nov 17, 2021 at 04:27:27PM +0000, German Gomez escreveu:
> Hi Arnaldo,
> 
> On 17/11/2021 15:29, Arnaldo Carvalho de Melo wrote:
> > [...]
> > Next time please expand this explanations a bit more: why should we
> > inject such samples? Is this enabling some new mode of operation, fixing
> > something, what is an example of output before this patch and after it?
> I will keep this in mind, thanks. In this case the support was missing
> and I included the context in the cover letter but not the commit msg.

Got it, I'm adding it to the cset comment:

-------------------------------------------------------------------------------

perf-inject is currently not working for Arm SPE. When you try to run
perf-inject and perf-report with a perf.data file that contains SPE
traces, the tool reports a "Bad address" error:

  # ./perf record -e arm_spe_0/ts_enable=1,store_filter=1,branch_filter=1,load_filter=1/ -a -- sleep 1
  # ./perf inject -i perf.data -o perf.inject.data --itrace
  # ./perf report -i perf.inject.data --stdio

  0x42c00 [0x8]: failed to process type: 9 [Bad address]
  Error:
  failed to process sample

As far as I know, the issue was first spotted in [1], but perf-inject
was not yet injecting the samples. This patch does something similar to
what cs_etm does for injecting the samples [2], but for SPE.

[1] https://patchwork.kernel.org/project/linux-arm-kernel/cover/20210412091006.468557-1-leo.yan@linaro.org/#24117339
[2] https://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git/tree/tools/perf/util/cs-etm.c?h=perf/core&id=133fe2e617e48ca0948983329f43877064ffda3e#n1196
-------------------------------------------------------------------------------
diff mbox series

Patch

diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index 58b7069c5..7054f2315 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -51,6 +51,7 @@  struct arm_spe {
 	u8				timeless_decoding;
 	u8				data_queued;
 
+	u64				sample_type;
 	u8				sample_flc;
 	u8				sample_llc;
 	u8				sample_tlb;
@@ -248,6 +249,12 @@  static void arm_spe_prep_sample(struct arm_spe *spe,
 	event->sample.header.size = sizeof(struct perf_event_header);
 }
 
+static int arm_spe__inject_event(union perf_event *event, struct perf_sample *sample, u64 type)
+{
+	event->header.size = perf_event__sample_event_size(sample, type, 0);
+	return perf_event__synthesize_sample(event, type, 0, sample);
+}
+
 static inline int
 arm_spe_deliver_synth_event(struct arm_spe *spe,
 			    struct arm_spe_queue *speq __maybe_unused,
@@ -256,6 +263,12 @@  arm_spe_deliver_synth_event(struct arm_spe *spe,
 {
 	int ret;
 
+	if (spe->synth_opts.inject) {
+		ret = arm_spe__inject_event(event, sample, spe->sample_type);
+		if (ret)
+			return ret;
+	}
+
 	ret = perf_session__deliver_synth_event(spe->session, event, sample);
 	if (ret)
 		pr_err("ARM SPE: failed to deliver event, error %d\n", ret);
@@ -920,6 +933,8 @@  arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session)
 	else
 		attr.sample_type |= PERF_SAMPLE_TIME;
 
+	spe->sample_type = attr.sample_type;
+
 	attr.exclude_user = evsel->core.attr.exclude_user;
 	attr.exclude_kernel = evsel->core.attr.exclude_kernel;
 	attr.exclude_hv = evsel->core.attr.exclude_hv;