[PATCH v3 3/6] perf arm_spe: Store MIDR in arm_spe_pkt

From: James Clark

Date: Tue Apr 14 2026 - 07:06:31 EST


The MIDR will affect printing of arm_spe_pkts, so store a copy of it
there. Technically it's constant for each decoder, but there is no
decoder when doing a raw dump, so it has to be stored in every packet.
It will only be used in raw dump mode and not in normal decoding for
now, but to avoid any surprises, set MIDR properly on the decoder too.

Having both the MIDR and the arm_spe_pkt (which has a copy of it) in the
decoder seemed a bit weird, so remove arm_spe_pkt from the decoder. The
packet is only short lived anyway so probably shouldn't have been there
in the first place.

Reviewed-by: Leo Yan <leo.yan@xxxxxxx>
Signed-off-by: James Clark <james.clark@xxxxxxxxxx>
---
tools/perf/util/arm-spe-decoder/arm-spe-decoder.c | 17 ++++++++++-------
tools/perf/util/arm-spe-decoder/arm-spe-decoder.h | 3 +--
.../perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c | 3 ++-
.../perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h | 3 ++-
tools/perf/util/arm-spe.c | 21 +++++++++++++++------
5 files changed, 30 insertions(+), 17 deletions(-)

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 9e02b2bdd1177193996d071dd88f969e25b1ad86..7a3a4815fd37b7f57687189c09c618aaf7ac9801 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
@@ -120,7 +120,8 @@ static int arm_spe_get_data(struct arm_spe_decoder *decoder)
return decoder->len;
}

-static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder)
+static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder,
+ struct arm_spe_pkt *packet)
{
int ret;

@@ -134,7 +135,8 @@ static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder)
}

ret = arm_spe_get_packet(decoder->buf, decoder->len,
- &decoder->packet);
+ packet, decoder->midr);
+
if (ret <= 0) {
/* Move forward for 1 byte */
decoder->buf += 1;
@@ -144,7 +146,7 @@ static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder)

decoder->buf += ret;
decoder->len -= ret;
- } while (decoder->packet.type == ARM_SPE_PAD);
+ } while (packet->type == ARM_SPE_PAD);

return 1;
}
@@ -154,19 +156,20 @@ static int arm_spe_read_record(struct arm_spe_decoder *decoder)
int err;
int idx;
u64 payload, ip;
+ struct arm_spe_pkt packet;

memset(&decoder->record, 0x0, sizeof(decoder->record));
decoder->record.context_id = (u64)-1;

while (1) {
- err = arm_spe_get_next_packet(decoder);
+ err = arm_spe_get_next_packet(decoder, &packet);
if (err <= 0)
return err;

- idx = decoder->packet.index;
- payload = decoder->packet.payload;
+ idx = packet.index;
+ payload = packet.payload;

- switch (decoder->packet.type) {
+ switch (packet.type) {
case ARM_SPE_TIMESTAMP:
decoder->record.timestamp = payload;
return 1;
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 3310e05122f02e8ef32f79f8ed3c6932cc43eecc..0cbcb501edc9965d34cfd3ede79cab3fd9b318f8 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-decoder.h
@@ -147,8 +147,7 @@ struct arm_spe_decoder {

const unsigned char *buf;
size_t len;
-
- struct arm_spe_pkt packet;
+ u64 midr;
};

struct arm_spe_decoder *arm_spe_decoder_new(struct arm_spe_params *params);
diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
index 5769ba2f414049161f271fd8b8f40c440d15a75a..718022aecec30bf30a51ba3d2bca9cf6465259a7 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c
@@ -222,11 +222,12 @@ static int arm_spe_do_get_packet(const unsigned char *buf, size_t len,
}

int arm_spe_get_packet(const unsigned char *buf, size_t len,
- struct arm_spe_pkt *packet)
+ struct arm_spe_pkt *packet, u64 midr)
{
int ret;

ret = arm_spe_do_get_packet(buf, len, packet);
+ packet->midr = midr;
/* put multiple consecutive PADs on the same line, up to
* the fixed-width output format of 16 bytes per line.
*/
diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
index adf4cde320aad01265b5232b0d6ff6b1f752f35f..a457821f3bccb67691cfd530de2f1c5bf9d8d50c 100644
--- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
+++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.h
@@ -35,6 +35,7 @@ struct arm_spe_pkt {
enum arm_spe_pkt_type type;
unsigned char index;
uint64_t payload;
+ uint64_t midr;
};

/* Short header (HEADER0) and extended header (HEADER1) */
@@ -184,7 +185,7 @@ enum arm_spe_events {
const char *arm_spe_pkt_name(enum arm_spe_pkt_type);

int arm_spe_get_packet(const unsigned char *buf, size_t len,
- struct arm_spe_pkt *packet);
+ struct arm_spe_pkt *packet, u64 midr);

int arm_spe_pkt_desc(const struct arm_spe_pkt *packet, char *buf, size_t len);
#endif
diff --git a/tools/perf/util/arm-spe.c b/tools/perf/util/arm-spe.c
index f9188fdb8e786fccff94cd8a92f367d90efc5cfe..ed4515fef2de3dded17befc358c87c2461d397d4 100644
--- a/tools/perf/util/arm-spe.c
+++ b/tools/perf/util/arm-spe.c
@@ -134,8 +134,10 @@ struct data_source_handle {
.ds_synth = arm_spe__synth_##func, \
}

+static int arm_spe__get_midr(struct arm_spe *spe, int cpu, u64 *midr);
+
static void arm_spe_dump(struct arm_spe *spe __maybe_unused,
- unsigned char *buf, size_t len)
+ unsigned char *buf, size_t len, u64 midr)
{
struct arm_spe_pkt packet;
size_t pos = 0;
@@ -148,7 +150,8 @@ static void arm_spe_dump(struct arm_spe *spe __maybe_unused,
len);

while (len) {
- ret = arm_spe_get_packet(buf, len, &packet);
+ ret = arm_spe_get_packet(buf, len, &packet, midr);
+
if (ret > 0)
pkt_len = ret;
else
@@ -174,10 +177,10 @@ static void arm_spe_dump(struct arm_spe *spe __maybe_unused,
}

static void arm_spe_dump_event(struct arm_spe *spe, unsigned char *buf,
- size_t len)
+ size_t len, u64 midr)
{
printf(".\n");
- arm_spe_dump(spe, buf, len);
+ arm_spe_dump(spe, buf, len, midr);
}

static int arm_spe_get_trace(struct arm_spe_buffer *b, void *data)
@@ -302,8 +305,10 @@ static void arm_spe_set_pid_tid_cpu(struct arm_spe *spe,

if (speq->thread) {
speq->pid = thread__pid(speq->thread);
- if (queue->cpu == -1)
+ if (queue->cpu == -1) {
speq->cpu = thread__cpu(speq->thread);
+ arm_spe__get_midr(spe, speq->cpu, &speq->decoder->midr);
+ }
}
}

@@ -1248,6 +1253,7 @@ static int arm_spe__setup_queue(struct arm_spe *spe,

if (queue->cpu != -1)
speq->cpu = queue->cpu;
+ arm_spe__get_midr(spe, queue->cpu, &speq->decoder->midr);

if (!speq->on_heap) {
int ret;
@@ -1490,8 +1496,11 @@ static int arm_spe_process_auxtrace_event(struct perf_session *session,
/* Dump here now we have copied a piped trace out of the pipe */
if (dump_trace) {
if (auxtrace_buffer__get_data(buffer, fd)) {
+ u64 midr = 0;
+
+ arm_spe__get_midr(spe, buffer->cpu.cpu, &midr);
arm_spe_dump_event(spe, buffer->data,
- buffer->size);
+ buffer->size, midr);
auxtrace_buffer__put_data(buffer);
}
}

--
2.34.1