perf arm-spe: Refactor arm-spe to support operation packet type
authorGerman Gomez <german.gomez@arm.com>
Mon, 20 Mar 2023 15:15:06 +0000 (15:15 +0000)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 20 Mar 2023 22:27:52 +0000 (19:27 -0300)
Extend the decoder of Arm SPE records to support more fields from the
operation packet type.

Not all fields are being decoded by this commit. Only those needed to
support the use-case SVE load/store/other operations.

Suggested-by: Leo Yan <leo.yan@linaro.org>
Signed-off-by: German Gomez <german.gomez@arm.com>
Acked-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Anshuman.Khandual@arm.com
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mike Leach <mike.leach@linaro.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Link: https://lore.kernel.org/r/20230320151509.1137462-2-james.clark@arm.com
Signed-off-by: James Clark <james.clark@arm.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
tools/perf/util/arm-spe.c

index 40dcedfd75cda2dfa4ec2a505ac40d9a7b5638b4..f3918f290df50d1c26561ad41b9a2cb98deebb5e 100644 (file)
@@ -190,11 +190,27 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder)
                        decoder->record.context_id = payload;
                        break;
                case ARM_SPE_OP_TYPE:
-                       if (idx == SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC) {
-                               if (payload & 0x1)
-                                       decoder->record.op = ARM_SPE_ST;
+                       switch (idx) {
+                       case SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC:
+                               decoder->record.op |= ARM_SPE_OP_LDST;
+                               if (payload & SPE_OP_PKT_ST)
+                                       decoder->record.op |= ARM_SPE_OP_ST;
                                else
-                                       decoder->record.op = ARM_SPE_LD;
+                                       decoder->record.op |= ARM_SPE_OP_LD;
+                               if (SPE_OP_PKT_IS_LDST_SVE(payload))
+                                       decoder->record.op |= ARM_SPE_OP_SVE_LDST;
+                               break;
+                       case SPE_OP_PKT_HDR_CLASS_OTHER:
+                               decoder->record.op |= ARM_SPE_OP_OTHER;
+                               if (SPE_OP_PKT_IS_OTHER_SVE_OP(payload))
+                                       decoder->record.op |= ARM_SPE_OP_SVE_OTHER;
+                               break;
+                       case SPE_OP_PKT_HDR_CLASS_BR_ERET:
+                               decoder->record.op |= ARM_SPE_OP_BRANCH_ERET;
+                               break;
+                       default:
+                               pr_err("Get packet error!\n");
+                               return -1;
                        }
                        break;
                case ARM_SPE_EVENTS:
@@ -222,6 +238,12 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder)
                        if (payload & BIT(EV_MISPRED))
                                decoder->record.type |= ARM_SPE_BRANCH_MISS;
 
+                       if (payload & BIT(EV_PARTIAL_PREDICATE))
+                               decoder->record.type |= ARM_SPE_SVE_PARTIAL_PRED;
+
+                       if (payload & BIT(EV_EMPTY_PREDICATE))
+                               decoder->record.type |= ARM_SPE_SVE_EMPTY_PRED;
+
                        break;
                case ARM_SPE_DATA_SOURCE:
                        decoder->record.source = payload;
index 46a61df1145b664465044124f04613382440a5b6..1443c28545a946f8d184892c68b9379ea224f750 100644 (file)
 #include "arm-spe-pkt-decoder.h"
 
 enum arm_spe_sample_type {
-       ARM_SPE_L1D_ACCESS      = 1 << 0,
-       ARM_SPE_L1D_MISS        = 1 << 1,
-       ARM_SPE_LLC_ACCESS      = 1 << 2,
-       ARM_SPE_LLC_MISS        = 1 << 3,
-       ARM_SPE_TLB_ACCESS      = 1 << 4,
-       ARM_SPE_TLB_MISS        = 1 << 5,
-       ARM_SPE_BRANCH_MISS     = 1 << 6,
-       ARM_SPE_REMOTE_ACCESS   = 1 << 7,
+       ARM_SPE_L1D_ACCESS              = 1 << 0,
+       ARM_SPE_L1D_MISS                = 1 << 1,
+       ARM_SPE_LLC_ACCESS              = 1 << 2,
+       ARM_SPE_LLC_MISS                = 1 << 3,
+       ARM_SPE_TLB_ACCESS              = 1 << 4,
+       ARM_SPE_TLB_MISS                = 1 << 5,
+       ARM_SPE_BRANCH_MISS             = 1 << 6,
+       ARM_SPE_REMOTE_ACCESS           = 1 << 7,
+       ARM_SPE_SVE_PARTIAL_PRED        = 1 << 8,
+       ARM_SPE_SVE_EMPTY_PRED          = 1 << 9,
 };
 
 enum arm_spe_op_type {
-       ARM_SPE_LD              = 1 << 0,
-       ARM_SPE_ST              = 1 << 1,
+       /* First level operation type */
+       ARM_SPE_OP_OTHER        = 1 << 0,
+       ARM_SPE_OP_LDST         = 1 << 1,
+       ARM_SPE_OP_BRANCH_ERET  = 1 << 2,
+
+       /* Second level operation type for OTHER */
+       ARM_SPE_OP_SVE_OTHER            = 1 << 16,
+       ARM_SPE_OP_SVE_FP               = 1 << 17,
+       ARM_SPE_OP_SVE_PRED_OTHER       = 1 << 18,
+
+       /* Second level operation type for LDST */
+       ARM_SPE_OP_LD                   = 1 << 16,
+       ARM_SPE_OP_ST                   = 1 << 17,
+       ARM_SPE_OP_ATOMIC               = 1 << 18,
+       ARM_SPE_OP_EXCL                 = 1 << 19,
+       ARM_SPE_OP_AR                   = 1 << 20,
+       ARM_SPE_OP_SIMD_FP              = 1 << 21,
+       ARM_SPE_OP_GP_REG               = 1 << 22,
+       ARM_SPE_OP_UNSPEC_REG           = 1 << 23,
+       ARM_SPE_OP_NV_SYSREG            = 1 << 24,
+       ARM_SPE_OP_SVE_LDST             = 1 << 25,
+       ARM_SPE_OP_SVE_PRED_LDST        = 1 << 26,
+       ARM_SPE_OP_SVE_SG               = 1 << 27,
+
+       /* Second level operation type for BRANCH_ERET */
+       ARM_SPE_OP_BR_COND      = 1 << 16,
+       ARM_SPE_OP_BR_INDIRECT  = 1 << 17,
 };
 
 enum arm_spe_neoverse_data_source {
index 906476a839e1f589bd414be19328e5b4d07dccda..bfae4731a47af6cc1e58f37806202d6599caac99 100644 (file)
@@ -411,7 +411,7 @@ static void arm_spe__synth_data_source_neoverse(const struct arm_spe_record *rec
         * We have no data on the hit level or data source for stores in the
         * Neoverse SPE records.
         */
-       if (record->op & ARM_SPE_ST) {
+       if (record->op & ARM_SPE_OP_ST) {
                data_src->mem_lvl = PERF_MEM_LVL_NA;
                data_src->mem_lvl_num = PERF_MEM_LVLNUM_NA;
                data_src->mem_snoop = PERF_MEM_SNOOP_NA;
@@ -497,12 +497,12 @@ static void arm_spe__synth_data_source_generic(const struct arm_spe_record *reco
 
 static u64 arm_spe__synth_data_source(const struct arm_spe_record *record, u64 midr)
 {
-       union perf_mem_data_src data_src = { 0 };
+       union perf_mem_data_src data_src = { .mem_op = PERF_MEM_OP_NA };
        bool is_neoverse = is_midr_in_range_list(midr, neoverse_spe);
 
-       if (record->op == ARM_SPE_LD)
+       if (record->op & ARM_SPE_OP_LD)
                data_src.mem_op = PERF_MEM_OP_LOAD;
-       else if (record->op == ARM_SPE_ST)
+       else if (record->op & ARM_SPE_OP_ST)
                data_src.mem_op = PERF_MEM_OP_STORE;
        else
                return 0;