From: Sizhe Liu <liusizhe5@huawei.com>
To: <rostedt@goodmis.org>, <mhiramat@kernel.org>,
<mathieu.desnoyers@efficios.com>, <corbet@lwn.net>,
<skhan@linuxfoundation.org>, <bhelgaas@google.com>,
<yangyccccc@gmail.com>, <jic23@kernel.org>,
<john.g.garry@oracle.com>, <will@kernel.org>,
<james.clark@linaro.org>, <mike.leach@arm.com>,
<leo.yan@linux.dev>, <peterz@infradead.org>, <mingo@redhat.com>,
<acme@kernel.org>, <namhyung@kernel.org>, <mark.rutland@arm.com>,
<alexander.shishkin@linux.intel.com>, <jolsa@kernel.org>,
<irogers@google.com>, <adrian.hunter@intel.com>,
<wangyushan12@huawei.com>, <wuzongyu1@huawei.com>
Cc: <linux-kernel@vger.kernel.org>, <linux-pci@vger.kernel.org>,
<linux-perf-users@vger.kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-doc@vger.kernel.org>, <linuxarm@huawei.com>,
<prime.zeng@hisilicon.com>, <liusizhe5@huawei.com>
Subject: [PATCH v2 8/8] perf hisi-ptt: Pass pattern version to decoder for compatibility
Date: Thu, 27 Aug 2026 22:04:42 +0800 [thread overview]
Message-ID: <20260827140442.2031128-9-liusizhe5@huawei.com> (raw)
In-Reply-To: <20260827140442.2031128-1-liusizhe5@huawei.com>
On the recording side, walk the evlist in hisi_ptt_info_fill() to find
the hisi_ptt event, read out the pattern bits from its config, and
forward the pattern version to the decoder through
auxtrace_info->priv[1] as HISI_PTT_PATTERN_LEGACY or HISI_PTT_PATTERN_V1.
On the decoding side, store the pattern version in struct hisi_ptt and
propagate it to struct hisi_ptt_pkt_buf. The printers of Header DW2
and DW3 check the version: HISI_PTT_PATTERN_V1 keeps the field-level
parsing introduced by the previous patches, while HISI_PTT_PATTERN_LEGACY
falls back to printing only the raw "Header DW2/DW3" label so legacy
traces remain decodable with the new tool.
The auxtrace priv size grows from one u64 to two. Use
HISI_PTT_AUXTRACE_PRIV_SIZE_LEGACY for the minimum header size check
and detect the actual priv_size at runtime to pick the pattern version.
For trace data recorded by an older tracer that does not support the
`pattern` parameter (no priv[1] in the header), the decoder defaults
to legacy mode (HISI_PTT_PATTERN_LEGACY) so the new tool keeps parsing
old traces correctly.
The hisi_ptt_pkt_size array is moved out of the shared header into
static definitions in the two .c files that consume it to avoid
multiple definitions.
Signed-off-by: Sizhe Liu <liusizhe5@huawei.com>
---
tools/perf/arch/arm64/util/hisi-ptt.c | 18 +++++++++
.../hisi-ptt-decoder/hisi-ptt-pkt-decoder.c | 39 ++++++++++++-------
.../hisi-ptt-decoder/hisi-ptt-pkt-decoder.h | 8 ++--
tools/perf/util/hisi-ptt.c | 28 +++++++++----
tools/perf/util/hisi-ptt.h | 9 ++++-
5 files changed, 72 insertions(+), 30 deletions(-)
diff --git a/tools/perf/arch/arm64/util/hisi-ptt.c b/tools/perf/arch/arm64/util/hisi-ptt.c
index 52257715d2b7..ae8c16b5c324 100644
--- a/tools/perf/arch/arm64/util/hisi-ptt.c
+++ b/tools/perf/arch/arm64/util/hisi-ptt.c
@@ -6,6 +6,7 @@
#include <linux/kernel.h>
#include <linux/types.h>
+#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/log2.h>
#include <linux/zalloc.h>
@@ -20,6 +21,7 @@
#include "../../../util/evlist.h"
#include "../../../util/evsel.h"
#include "../../../util/hisi-ptt.h"
+#include "../../../util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h"
#include "../../../util/pmu.h"
#include "../../../util/record.h"
#include "../../../util/session.h"
@@ -49,6 +51,8 @@ static int hisi_ptt_info_fill(struct auxtrace_record *itr,
struct hisi_ptt_recording *pttr =
container_of(itr, struct hisi_ptt_recording, itr);
struct perf_pmu *hisi_ptt_pmu = pttr->hisi_ptt_pmu;
+ struct evsel *evsel;
+ u32 pattern = 0;
if (priv_size != HISI_PTT_AUXTRACE_PRIV_SIZE)
return -EINVAL;
@@ -56,8 +60,22 @@ static int hisi_ptt_info_fill(struct auxtrace_record *itr,
if (!evlist__core(session->evlist)->nr_mmaps)
return -EINVAL;
+ /*
+ * Walk the evlist to find the hisi_ptt event and read out the pattern
+ * bits from its config, which decides the decoder version used to
+ * parse the trace data.
+ */
+ evlist__for_each_entry(session->evlist, evsel) {
+ if (evsel->core.attr.type == hisi_ptt_pmu->type) {
+ pattern = FIELD_GET(HISI_PTT_PMU_PATTERN_MASK,
+ evsel->core.attr.config);
+ break;
+ }
+ }
+
auxtrace_info->type = PERF_AUXTRACE_HISI_PTT;
auxtrace_info->priv[0] = hisi_ptt_pmu->type;
+ auxtrace_info->priv[1] = pattern;
return 0;
}
diff --git a/tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c b/tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c
index de1d4071e209..63700380bf91 100644
--- a/tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c
+++ b/tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c
@@ -20,7 +20,7 @@
/*
* For 8DW format, the bit[31:11] of DW0 is always 0x1fffff, which can be
* used to distinguish the data format.
- * 8DW format is like:
+ * 8DW format legacy pattern is like:
* bits [ 31:11 ][ 10:0 ]
* |---------------------------------------|-------------------|
* DW0 [ 0x1fffff ][ Reserved (0x7ff) ]
@@ -32,7 +32,7 @@
* DW6 [ Reserved (0x0) ]
* DW7 [ Time ]
*
- * 4DW format is like:
+ * 4DW format legacy pattern is like:
* bits [31:30] [ 29:25 ][24][23][22][21][ 20:11 ][ 10:0 ]
* |-----|---------|---|---|---|---|-------------|-------------|
* DW0 [ Fmt ][ Type ][T9][T8][TH][SO][ Length ][ Time ]
@@ -79,6 +79,11 @@ static const char * const hisi_ptt_4dw_pkt_field_name[] = {
[HISI_PTT_4DW_HEAD3] = "Header DW3",
};
+static int hisi_ptt_pkt_size[] = {
+ [HISI_PTT_4DW_PKT] = 16,
+ [HISI_PTT_8DW_PKT] = 32,
+};
+
/* TLP message parsers below according to PCIe r6.4 sec 2.2.1.1 & 2.2.1.2 */
static bool hisi_ptt_is_mwr_tlp(uint32_t format, uint32_t type)
{
@@ -207,15 +212,20 @@ static void hisi_ptt_print_head1(struct hisi_ptt_pkt_buf *pkt_buf)
static void hisi_ptt_print_head2(struct hisi_ptt_pkt_buf *pkt_buf)
{
const char *color = PERF_COLOR_BLUE;
+ const char *desc = pkt_buf->pkt_type == HISI_PTT_4DW_PKT ?
+ hisi_ptt_4dw_pkt_field_name[HISI_PTT_4DW_HEAD2] :
+ hisi_ptt_8dw_pkt_field_name[HISI_PTT_8DW_HEAD2];
uint32_t dw;
dw = get_unaligned_le32(pkt_buf->buf + pkt_buf->pos);
hisi_ptt_print_raw_record(pkt_buf->pos, dw);
- if (pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_MWR ||
- pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_MSG ||
- pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_ATOM ||
- pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_IO)
+ if (pkt_buf->pattern < HISI_PTT_PATTERN_V1)
+ color_fprintf(stdout, color, " %s\n", desc);
+ else if (pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_MWR ||
+ pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_MSG ||
+ pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_ATOM ||
+ pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_IO)
color_fprintf(stdout, color,
" %s %x %s %x %s %x %s %x %s %x %s %x %s %x\n",
"Reserved",
@@ -229,10 +239,7 @@ static void hisi_ptt_print_head2(struct hisi_ptt_pkt_buf *pkt_buf)
"Header DW2",
FIELD_GET(HISI_PTT_HEAD2_HEADER_DW2, dw));
else
- color_fprintf(stdout, color, " %s\n",
- pkt_buf->pkt_type == HISI_PTT_4DW_PKT ?
- hisi_ptt_4dw_pkt_field_name[HISI_PTT_4DW_HEAD2] :
- hisi_ptt_8dw_pkt_field_name[HISI_PTT_8DW_HEAD2]);
+ color_fprintf(stdout, color, " %s\n", desc);
pkt_buf->pos += HISI_PTT_FIELD_LENGTH;
}
@@ -240,12 +247,17 @@ static void hisi_ptt_print_head2(struct hisi_ptt_pkt_buf *pkt_buf)
static void hisi_ptt_print_head3(struct hisi_ptt_pkt_buf *pkt_buf)
{
const char *color = PERF_COLOR_BLUE;
+ const char *desc = pkt_buf->pkt_type == HISI_PTT_4DW_PKT ?
+ hisi_ptt_4dw_pkt_field_name[HISI_PTT_4DW_HEAD3] :
+ hisi_ptt_8dw_pkt_field_name[HISI_PTT_8DW_HEAD3];
uint32_t dw;
dw = get_unaligned_le32(pkt_buf->buf + pkt_buf->pos);
hisi_ptt_print_raw_record(pkt_buf->pos, dw);
- if (pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_CPL)
+ if (pkt_buf->pattern < HISI_PTT_PATTERN_V1)
+ color_fprintf(stdout, color, " %s\n", desc);
+ else if (pkt_buf->pkt_msg_type == HISI_PTT_PKT_TYPE_CPL)
color_fprintf(stdout, color,
" %s %x %s %x %s %x %s %x %s %x %s %x %s %x\n",
"Destination Segment",
@@ -272,10 +284,7 @@ static void hisi_ptt_print_head3(struct hisi_ptt_pkt_buf *pkt_buf)
"Header DW3",
FIELD_GET(HISI_PTT_HEAD3_CFG_HEADER_DW3, dw));
else
- color_fprintf(stdout, color, " %s\n",
- pkt_buf->pkt_type == HISI_PTT_4DW_PKT ?
- hisi_ptt_4dw_pkt_field_name[HISI_PTT_4DW_HEAD3] :
- hisi_ptt_8dw_pkt_field_name[HISI_PTT_8DW_HEAD3]);
+ color_fprintf(stdout, color, " %s\n", desc);
pkt_buf->pos += HISI_PTT_FIELD_LENGTH;
}
diff --git a/tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h b/tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h
index 9663615ea3b5..5aaba79ef055 100644
--- a/tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h
+++ b/tools/perf/util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h
@@ -16,6 +16,8 @@
#define HISI_PTT_IS_8DW_PKT GENMASK(31, 11)
#define HISI_PTT_MAX_SPACE_LEN 10
#define HISI_PTT_FIELD_LENGTH 4
+#define HISI_PTT_PATTERN_LEGACY 0
+#define HISI_PTT_PATTERN_V1 1
/* Header DW0 fields for 4DW format */
#define HISI_PTT_HEAD0_4DW_TIME GENMASK_U32(10, 0)
@@ -76,11 +78,6 @@ enum hisi_ptt_pkt_type {
HISI_PTT_PKT_MAX
};
-static int hisi_ptt_pkt_size[] = {
- [HISI_PTT_4DW_PKT] = 16,
- [HISI_PTT_8DW_PKT] = 32,
-};
-
enum hisi_ptt_pkt_msg_type {
HISI_PTT_PKT_TYPE_UNKNOWN, /* Types do not support analysis */
HISI_PTT_PKT_TYPE_MWR, /* P-(MemWr) */
@@ -98,6 +95,7 @@ struct hisi_ptt_pkt_buf {
size_t len;
enum hisi_ptt_pkt_type pkt_type;
enum hisi_ptt_pkt_msg_type pkt_msg_type;
+ size_t pattern;
};
int hisi_ptt_pkt_desc(struct hisi_ptt_pkt_buf *pkt_buf);
diff --git a/tools/perf/util/hisi-ptt.c b/tools/perf/util/hisi-ptt.c
index 78817ae7a8ea..7cf778837337 100644
--- a/tools/perf/util/hisi-ptt.c
+++ b/tools/perf/util/hisi-ptt.c
@@ -35,6 +35,12 @@ struct hisi_ptt {
struct perf_session *session;
struct machine *machine;
u32 pmu_type;
+ u32 pattern;
+};
+
+static int hisi_ptt_pkt_size[] = {
+ [HISI_PTT_4DW_PKT] = 16,
+ [HISI_PTT_8DW_PKT] = 32,
};
static enum hisi_ptt_pkt_type hisi_ptt_check_packet_type(unsigned char *buf,
@@ -53,8 +59,7 @@ static enum hisi_ptt_pkt_type hisi_ptt_check_packet_type(unsigned char *buf,
return HISI_PTT_4DW_PKT;
}
-static void hisi_ptt_dump(struct hisi_ptt *ptt __maybe_unused,
- unsigned char *buf, size_t len)
+static void hisi_ptt_dump(struct hisi_ptt *ptt, unsigned char *buf, size_t len)
{
const char *color = PERF_COLOR_BLUE;
struct hisi_ptt_pkt_buf pkt_buf;
@@ -64,8 +69,9 @@ static void hisi_ptt_dump(struct hisi_ptt *ptt __maybe_unused,
pkt_buf.pkt_type = hisi_ptt_check_packet_type(buf, len);
pkt_buf.len = round_down(len, hisi_ptt_pkt_size[pkt_buf.pkt_type]);
pkt_buf.pkt_msg_type = HISI_PTT_PKT_TYPE_UNKNOWN;
- color_fprintf(stdout, color, ". ... HISI PTT data: size %zu bytes\n",
- pkt_buf.len);
+ pkt_buf.pattern = (size_t)ptt->pattern;
+ color_fprintf(stdout, color, ". ... HISI PTT data: size %zu bytes, pattern %zu\n",
+ pkt_buf.len, pkt_buf.pattern);
while (pkt_buf.pos < pkt_buf.len) {
if (!hisi_ptt_pkt_desc(&pkt_buf))
@@ -158,12 +164,13 @@ static bool hisi_ptt_evsel_is_auxtrace(struct perf_session *session,
return evsel->core.attr.type == ptt->pmu_type;
}
-static void hisi_ptt_print_info(__u64 type)
+static void hisi_ptt_print_info(u32 type, u32 pattern)
{
if (!dump_trace)
return;
- fprintf(stdout, " PMU Type %" PRId64 "\n", (s64) type);
+ fprintf(stdout, " PMU Type %" PRIu32 "\n", type);
+ fprintf(stdout, " Data Pattern %" PRIu32 "\n", pattern);
}
int hisi_ptt_process_auxtrace_info(union perf_event *event,
@@ -171,10 +178,13 @@ int hisi_ptt_process_auxtrace_info(union perf_event *event,
{
struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
struct hisi_ptt *ptt;
+ size_t priv_size;
- if (auxtrace_info->header.size < HISI_PTT_AUXTRACE_PRIV_SIZE +
+ if (auxtrace_info->header.size < HISI_PTT_AUXTRACE_PRIV_SIZE_LEGACY +
sizeof(struct perf_record_auxtrace_info))
return -EINVAL;
+ priv_size = auxtrace_info->header.size -
+ sizeof(struct perf_record_auxtrace_info);
ptt = zalloc(sizeof(*ptt));
if (!ptt)
@@ -184,6 +194,8 @@ int hisi_ptt_process_auxtrace_info(union perf_event *event,
ptt->machine = &session->machines.host; /* No kvm support */
ptt->auxtrace_type = auxtrace_info->type;
ptt->pmu_type = auxtrace_info->priv[0];
+ ptt->pattern = priv_size >= HISI_PTT_AUXTRACE_PRIV_SIZE_V1 ?
+ (u32)auxtrace_info->priv[1] : HISI_PTT_PATTERN_LEGACY;
ptt->auxtrace.process_event = hisi_ptt_process_event;
ptt->auxtrace.process_auxtrace_event = hisi_ptt_process_auxtrace_event;
@@ -193,7 +205,7 @@ int hisi_ptt_process_auxtrace_info(union perf_event *event,
ptt->auxtrace.evsel_is_auxtrace = hisi_ptt_evsel_is_auxtrace;
session->auxtrace = &ptt->auxtrace;
- hisi_ptt_print_info(auxtrace_info->priv[0]);
+ hisi_ptt_print_info(ptt->pmu_type, ptt->pattern);
return 0;
}
diff --git a/tools/perf/util/hisi-ptt.h b/tools/perf/util/hisi-ptt.h
index 2db9b4056214..912453b06e62 100644
--- a/tools/perf/util/hisi-ptt.h
+++ b/tools/perf/util/hisi-ptt.h
@@ -7,8 +7,13 @@
#ifndef INCLUDE__PERF_HISI_PTT_H__
#define INCLUDE__PERF_HISI_PTT_H__
-#define HISI_PTT_PMU_NAME "hisi_ptt"
-#define HISI_PTT_AUXTRACE_PRIV_SIZE sizeof(u64)
+#include <linux/bits.h>
+
+#define HISI_PTT_PMU_NAME "hisi_ptt"
+#define HISI_PTT_AUXTRACE_PRIV_SIZE_LEGACY sizeof(u64)
+#define HISI_PTT_AUXTRACE_PRIV_SIZE_V1 (2 * sizeof(u64))
+#define HISI_PTT_AUXTRACE_PRIV_SIZE HISI_PTT_AUXTRACE_PRIV_SIZE_V1
+#define HISI_PTT_PMU_PATTERN_MASK GENMASK_ULL(39, 36)
struct auxtrace_record *hisi_ptt_recording_init(int *err,
struct perf_pmu *hisi_ptt_pmu);
--
2.33.0
prev parent reply other threads:[~2026-08-27 14:05 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-27 14:04 [PATCH v2 0/8] Enhance TLP packet decoder with field-level parsing and versioning Sizhe Liu
2026-08-27 14:04 ` [PATCH v2 1/8] perf hisi-ptt: Abstract trace data buf and offset Sizhe Liu
2026-08-27 14:04 ` [PATCH v2 2/8] perf hisi-ptt: Complete the field names for 4DW and 8DW packets Sizhe Liu
2026-08-27 14:04 ` [PATCH v2 3/8] perf hisi-ptt: Extract the raw data printing part Sizhe Liu
2026-08-27 14:04 ` [PATCH v2 4/8] perf hisi-ptt: Merge 4DW and 8DW HEAD0 printing Sizhe Liu
2026-08-27 14:04 ` [PATCH v2 5/8] perf hisi-ptt: Add parsing of supported message types Sizhe Liu
2026-08-27 14:04 ` [PATCH v2 6/8] perf hisi-ptt: Add field-level parsing for header DW2/DW3 Sizhe Liu
2026-08-27 14:04 ` [PATCH v2 7/8] hwtracing: hisi_ptt: Add pattern PMU config for trace format selection Sizhe Liu
2026-08-27 14:04 ` Sizhe Liu [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260827140442.2031128-9-liusizhe5@huawei.com \
--to=liusizhe5@huawei.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=bhelgaas@google.com \
--cc=corbet@lwn.net \
--cc=irogers@google.com \
--cc=james.clark@linaro.org \
--cc=jic23@kernel.org \
--cc=john.g.garry@oracle.com \
--cc=jolsa@kernel.org \
--cc=leo.yan@linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linuxarm@huawei.com \
--cc=mark.rutland@arm.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=mike.leach@arm.com \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=prime.zeng@hisilicon.com \
--cc=rostedt@goodmis.org \
--cc=skhan@linuxfoundation.org \
--cc=wangyushan12@huawei.com \
--cc=will@kernel.org \
--cc=wuzongyu1@huawei.com \
--cc=yangyccccc@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox