Synthesize unaligned address access events and partial/empty predicated SVE operation introduced by ARMv8.3-SPE.
They can be filtered by itrace options when reporting. Signed-off-by: Wei Li <[email protected]> --- .../util/arm-spe-decoder/arm-spe-decoder.c | 11 ++++ .../util/arm-spe-decoder/arm-spe-decoder.h | 3 + tools/perf/util/arm-spe.c | 61 +++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c index 93e063f22be5..fac8102c0149 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c @@ -197,6 +197,17 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder) if (payload & BIT(EV_MISPRED)) decoder->record.type |= ARM_SPE_BRANCH_MISS; + if ((idx == 4 || idx == 8) && + (payload & BIT(EV_ALIGNMENT))) + decoder->record.type |= ARM_SPE_ALIGNMENT; + + if ((idx == 4 || idx == 8) && + (payload & BIT(EV_PARTIAL_PREDICATE))) + decoder->record.type |= ARM_SPE_PARTIAL_PREDICATE; + + if ((idx == 4 || idx == 8) && + (payload & BIT(EV_EMPTY_PREDICATE))) + decoder->record.type |= ARM_SPE_EMPTY_PREDICATE; break; case ARM_SPE_DATA_SOURCE: break; diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h index a5111a8d4360..d165418fcc13 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h +++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h @@ -39,6 +39,9 @@ enum arm_spe_sample_type { ARM_SPE_TLB_MISS = 1 << 5, ARM_SPE_BRANCH_MISS = 1 << 6, ARM_SPE_REMOTE_ACCESS = 1 << 7, + ARM_SPE_ALIGNMENT = 1 << 8, + ARM_SPE_PARTIAL_PREDICATE = 1 << 9, + ARM_SPE_EMPTY_PREDICATE = 1 << 10, }; struct arm_spe_record { diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c index 3882a5360ada..e36d6eea269b 100644 --- a/tools/perf/util/arm-spe.c +++ b/tools/perf/util/arm-spe.c @@ -53,6 +53,8 @@ struct arm_spe { u8 sample_tlb; u8 sample_branch; u8 sample_remote_access; + u8 sample_alignment; + u8 sample_sve; u64 l1d_miss_id; u64 l1d_access_id; @@ -62,6 +64,9 @@ struct arm_spe { u64 tlb_access_id; u64 branch_miss_id; u64 remote_access_id; + u64 alignment_id; + u64 epred_sve_id; + u64 ppred_sve_id; u64 kernel_start; @@ -344,6 +349,30 @@ static int arm_spe_sample(struct arm_spe_queue *speq) return err; } + if (spe->sample_alignment && + (record->type & ARM_SPE_ALIGNMENT)) { + err = arm_spe_synth_spe_events_sample(speq, + spe->alignment_id); + if (err) + return err; + } + + if (spe->sample_sve) { + if (record->type & ARM_SPE_EMPTY_PREDICATE) { + err = arm_spe_synth_spe_events_sample( + speq, spe->epred_sve_id); + if (err) + return err; + } + + if (record->type & ARM_SPE_PARTIAL_PREDICATE) { + err = arm_spe_synth_spe_events_sample( + speq, spe->ppred_sve_id); + if (err) + return err; + } + } + return 0; } @@ -907,6 +936,38 @@ arm_spe_synth_events(struct arm_spe *spe, struct perf_session *session) id += 1; } + if (spe->synth_opts.alignment) { + spe->sample_alignment = true; + + /* Alignment */ + err = arm_spe_synth_event(session, &attr, id); + if (err) + return err; + spe->alignment_id = id; + arm_spe_set_event_name(evlist, id, "alignment"); + id += 1; + } + + if (spe->synth_opts.sve) { + spe->sample_sve = true; + + /* Empty predicated SVE */ + err = arm_spe_synth_event(session, &attr, id); + if (err) + return err; + spe->epred_sve_id = id; + arm_spe_set_event_name(evlist, id, "sve-pred-empty"); + id += 1; + + /* Partial predicated SVE */ + err = arm_spe_synth_event(session, &attr, id); + if (err) + return err; + spe->ppred_sve_id = id; + arm_spe_set_event_name(evlist, id, "sve-pred-partial"); + id += 1; + } + return 0; } -- 2.17.1

