[PATCH v6 13/14] perf tools: Initial support for gtrace decoder

From: Mayuresh Chitale

Date: Thu Oct 01 2026 - 01:25:15 EST


Add bare bones support for gtrace decoder so that the data received
from the hardware by the gtrace perf driver can be written to the
perf record output file. Actual decoding of the trace payload is not yet
implemented.

Co-developed-by: Anup Patel <anup.patel@xxxxxxxxxxxxxxxx>
Signed-off-by: Anup Patel <anup.patel@xxxxxxxxxxxxxxxx>
Reviewed-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
Signed-off-by: Mayuresh Chitale <mayuresh.chitale@xxxxxxxxxxxxxxxx>
---
tools/perf/util/Build | 1 +
tools/perf/util/auxtrace.c | 3 +
tools/perf/util/gtrace-decoder.c | 95 ++++++++++++++++++++++++++++++++
tools/perf/util/gtrace.h | 1 +
4 files changed, 100 insertions(+)
create mode 100644 tools/perf/util/gtrace-decoder.c

diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index b26a0b1ddfa3..d25140a0d64f 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -149,6 +149,7 @@ perf-util-y += cs-etm.o
perf-util-y += cs-etm-decoder/
endif
perf-util-y += cs-etm-base.o
+perf-util-y += gtrace-decoder.o

perf-util-y += parse-branch-options.o
perf-util-y += parse-regs-options.o
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 1ecdde597153..ba750d089a7a 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -54,6 +54,7 @@
#include "arm-spe.h"
#include "hisi-ptt.h"
#include "s390-cpumsf.h"
+#include "gtrace.h"
#include "util/mmap.h"
#include "powerpc-vpadtl.h"

@@ -1433,6 +1434,8 @@ int perf_event__process_auxtrace_info(const struct perf_tool *tool __maybe_unuse
err = powerpc_vpadtl_process_auxtrace_info(event, session);
break;
case PERF_AUXTRACE_GTRACE:
+ err = gtrace__process_auxtrace_info(event, session);
+ break;
case PERF_AUXTRACE_UNKNOWN:
default:
return -EINVAL;
diff --git a/tools/perf/util/gtrace-decoder.c b/tools/perf/util/gtrace-decoder.c
new file mode 100644
index 000000000000..c25fbfc61928
--- /dev/null
+++ b/tools/perf/util/gtrace-decoder.c
@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generic hardware trace (gtrace) decoder
+ * Copyright (c) 2026 Qualcomm Technologies, Inc.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <internal/lib.h>
+#include <linux/zalloc.h>
+#include "evlist.h"
+#include "session.h"
+#include "gtrace.h"
+
+struct gtrace_decoder {
+ struct auxtrace auxtrace;
+ u32 auxtrace_type;
+ struct perf_session *session;
+ struct machine *machine;
+ u32 pmu_type;
+};
+
+static int gtrace_process_event(struct perf_session *session __maybe_unused,
+ union perf_event *event __maybe_unused,
+ struct perf_sample *sample __maybe_unused,
+ const struct perf_tool *tool __maybe_unused)
+{
+ return 0;
+}
+
+static int gtrace_process_auxtrace_event(struct perf_session *session __maybe_unused,
+ union perf_event *event __maybe_unused,
+ const struct perf_tool *tool __maybe_unused)
+{
+ return 0;
+}
+
+static int gtrace_flush(struct perf_session *session __maybe_unused,
+ const struct perf_tool *tool __maybe_unused)
+{
+ return 0;
+}
+
+static void gtrace_free_events(struct perf_session *session __maybe_unused)
+{
+}
+
+static void gtrace_free(struct perf_session *session)
+{
+ struct gtrace_decoder *ptr = container_of(session->auxtrace, struct gtrace_decoder,
+ auxtrace);
+
+ session->auxtrace = NULL;
+ free(ptr);
+}
+
+static bool gtrace_evsel_is_auxtrace(struct perf_session *session,
+ struct evsel *evsel)
+{
+ struct gtrace_decoder *ptr = container_of(session->auxtrace,
+ struct gtrace_decoder, auxtrace);
+
+ return evsel->core.attr.type == ptr->pmu_type;
+}
+
+int gtrace__process_auxtrace_info(union perf_event *event,
+ struct perf_session *session)
+{
+ struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
+ struct gtrace_decoder *ptr;
+
+ if (auxtrace_info->header.size < GTRACE_AUXTRACE_PRIV_SIZE +
+ sizeof(struct perf_record_auxtrace_info))
+ return -EINVAL;
+
+ ptr = zalloc(sizeof(*ptr));
+ if (!ptr)
+ return -ENOMEM;
+
+ ptr->session = session;
+ ptr->machine = &session->machines.host;
+ ptr->auxtrace_type = auxtrace_info->type;
+ ptr->pmu_type = auxtrace_info->priv[0];
+
+ ptr->auxtrace.process_event = gtrace_process_event;
+ ptr->auxtrace.process_auxtrace_event = gtrace_process_auxtrace_event;
+ ptr->auxtrace.flush_events = gtrace_flush;
+ ptr->auxtrace.free_events = gtrace_free_events;
+ ptr->auxtrace.free = gtrace_free;
+ ptr->auxtrace.evsel_is_auxtrace = gtrace_evsel_is_auxtrace;
+ session->auxtrace = &ptr->auxtrace;
+
+ return 0;
+}
diff --git a/tools/perf/util/gtrace.h b/tools/perf/util/gtrace.h
index 343d2e9d4fa1..02db4f2ff9f5 100644
--- a/tools/perf/util/gtrace.h
+++ b/tools/perf/util/gtrace.h
@@ -13,5 +13,6 @@ struct perf_session;

#define GTRACE_AUXTRACE_PRIV_SIZE sizeof(u64)

+int gtrace__process_auxtrace_info(union perf_event *event, struct perf_session *session);
#endif

--
2.43.0