Thread (10 messages) 10 messages, 1 author, 11d ago
COOLING11d

[PATCH 5/9] tools/perf: process htm auxtrace events and display in perf report -D

From: Athira Rajeev <hidden>
Date: 2026-07-01 08:41:54
Also in: linux-perf-users
Subsystem: performance events subsystem, the rest · Maintainers: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo, Namhyung Kim, Linus Torvalds

Add htm pmu auxtrace process function for "perf script -D".
The auxtrace event processing functions are defined in file
"util/powerpc-htm.c". Different PERF_RECORD_XXX are generated
during recording. PERF_RECORD_AUXTRACE_INFO is processed first
since it is of type perf_user_event_type and perf session event
delivers perf_session__process_user_event() first. Define function
powerpc_htm_process_auxtrace_info() to handle the processing of
PERF_RECORD_AUXTRACE_INFO records. In this function, initialize
the aux buffer queues using auxtrace_queues__init(). Setup the
required infrastructure for aux data processing.

The trace data which is part of each AUXTRACE record will be written
to a file named htm.bin.n<nodeindex>.p<nodalchipindex>.c<coreindexonchip>

Sample output:
 # perf record -C 8 -m,256 -e htm/event=0x901032/ ls
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 2048.915 MB perf.data ]

 # perf script -D -i perf.data
 . ... HTM PMU data: size <N> bytes

 # perf record -C 1 -e htm/nodalchipindex=2,nodeindex=0,htm_type=1/ -o perf_1.data ls 1>out
 [ perf record: Woken up 1 times to write data ]
 [ perf record: Captured and wrote 257.504 MB perf_1.data ]

Signed-off-by: Athira Rajeev <redacted>
---
 tools/perf/arch/powerpc/util/htm.c |   3 +
 tools/perf/util/auxtrace.c         |   4 +
 tools/perf/util/auxtrace.h         |   1 +
 tools/perf/util/powerpc-htm.c      | 149 +++++++++++++++++++++++++++++
 tools/perf/util/powerpc-htm.h      |   2 +
 5 files changed, 159 insertions(+)
diff --git a/tools/perf/arch/powerpc/util/htm.c b/tools/perf/arch/powerpc/util/htm.c
index cc733f45ac9b..0e6638c02716 100644
--- a/tools/perf/arch/powerpc/util/htm.c
+++ b/tools/perf/arch/powerpc/util/htm.c
@@ -56,6 +56,7 @@ htm_recording_options(struct auxtrace_record *ar __maybe_unused,
 		if (strstarts(pos->name, "htm")) {
 			pos->needs_auxtrace_mmap = true;
 			pos->core.attr.aux_watermark = opts->auxtrace_mmap_pages * (size_t)page_size;
+			pos->core.attr.sample_type |= PERF_SAMPLE_RAW;
 			break;
 		}
 	}
@@ -75,6 +76,8 @@ htm_info_fill(struct auxtrace_record *itr __maybe_unused,
 		struct perf_record_auxtrace_info *auxtrace_info __maybe_unused,
 		size_t priv_size __maybe_unused)
 {
+	auxtrace_info->type = PERF_AUXTRACE_POWERPC_HTM;
+
 	return 0;
 }
 
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index 0b851f32e98c..9f32f54fad43 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -56,6 +56,7 @@
 #include "s390-cpumsf.h"
 #include "util/mmap.h"
 #include "powerpc-vpadtl.h"
+#include "powerpc-htm.h"
 
 #include <linux/ctype.h>
 #include "symbol/kallsyms.h"
@@ -1427,6 +1428,9 @@ int perf_event__process_auxtrace_info(const struct perf_tool *tool __maybe_unuse
 	case PERF_AUXTRACE_VPA_DTL:
 		err = powerpc_vpadtl_process_auxtrace_info(event, session);
 		break;
+	case PERF_AUXTRACE_POWERPC_HTM:
+		err = powerpc_htm_process_auxtrace_info(event, session);
+		break;
 	case PERF_AUXTRACE_UNKNOWN:
 	default:
 		return -EINVAL;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 6947f3f284c0..68b17802a419 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -46,6 +46,7 @@ enum auxtrace_type {
 	PERF_AUXTRACE_S390_CPUMSF,
 	PERF_AUXTRACE_HISI_PTT,
 	PERF_AUXTRACE_VPA_DTL,
+	PERF_AUXTRACE_POWERPC_HTM,
 };
 
 enum itrace_period_type {
diff --git a/tools/perf/util/powerpc-htm.c b/tools/perf/util/powerpc-htm.c
index 5043ff41a609..ffddf0e59fc1 100644
--- a/tools/perf/util/powerpc-htm.c
+++ b/tools/perf/util/powerpc-htm.c
@@ -9,6 +9,24 @@
 #include "session.h"
 #include "debug.h"
 #include <internal/xyarray.h>
+#include <linux/string.h>
+#include "color.h"
+#include <inttypes.h>
+#include "powerpc-htm.h"
+#include <errno.h>
+
+struct perf_session;
+
+struct powerpc_htm {
+	struct auxtrace			auxtrace;
+	struct auxtrace_queues		queues;
+	struct auxtrace_heap		heap;
+	u32				auxtrace_type;
+	struct perf_session		*session;
+	struct machine			*machine;
+	u32				pmu_type;
+	char				htmbin_file[64];
+};
 
 /*
  * Check if HTM events have more data to collect.
@@ -72,3 +90,134 @@ int arch_perf_record__need_read(struct evlist *evlist)
 
 	return 1;
 }
+
+static void powerpc_htm_dump_event(size_t len)
+{
+	const char *color = PERF_COLOR_BLUE;
+
+	color_fprintf(stdout, color,
+			". ... HTM PMU data: size %zu bytes\n",
+			len);
+}
+
+static int powerpc_htm_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 powerpc_htm_process_auxtrace_event(struct perf_session *session __maybe_unused,
+					  union perf_event *event,
+					  const struct perf_tool *tool __maybe_unused)
+{
+	powerpc_htm_dump_event(event->auxtrace.size);
+
+	return 0;
+}
+
+static int powerpc_htm_flush(struct perf_session *session __maybe_unused,
+			 const struct perf_tool *tool __maybe_unused)
+{
+	return 0;
+}
+
+static void powerpc_htm_free_events(struct perf_session *session)
+{
+	struct powerpc_htm *htm = container_of(session->auxtrace, struct powerpc_htm,
+					     auxtrace);
+	struct auxtrace_queues *queues = &htm->queues;
+	unsigned int i;
+
+	for (i = 0; i < queues->nr_queues; i++)
+		zfree(&queues->queue_array[i].priv);
+
+	auxtrace_queues__free(queues);
+}
+
+static void powerpc_htm_free(struct perf_session *session)
+{
+	struct powerpc_htm *htm = container_of(session->auxtrace, struct powerpc_htm,
+					     auxtrace);
+
+	powerpc_htm_free_events(session);
+	session->auxtrace = NULL;
+	free(htm);
+}
+static const char * const powerpc_htm_info_fmts[] = {
+	[POWERPC_HTM_TYPE]		= "  PMU Type           %"PRId64"\n",
+};
+
+static void powerpc_htm_print_info(__u64 *arr)
+{
+	if (!dump_trace)
+		return;
+
+	fprintf(stdout, powerpc_htm_info_fmts[POWERPC_HTM_TYPE], arr[POWERPC_HTM_TYPE]);
+}
+
+int powerpc_htm_process_auxtrace_info(union perf_event *event,
+				  struct perf_session *session)
+{
+	struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
+	struct evsel *evsel = evlist__event2evsel(session->evlist, event);
+	u32 nodeindex, nodalchipindex, coreindexonchip;
+	int config = (evsel->core.attr.config);
+	size_t min_sz = sizeof(u64) * POWERPC_HTM_TYPE;
+	struct powerpc_htm *htm;
+	int err;
+	FILE *fp;
+
+	nodeindex = (config >> 4) & 0xff;
+	nodalchipindex = (config >> 12) & 0xff;
+	coreindexonchip = (config >> 20) & 0xff;
+
+	if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) +
+					min_sz)
+		return -EINVAL;
+
+	htm = zalloc(sizeof(struct powerpc_htm));
+	if (!htm)
+		return -ENOMEM;
+
+	err = auxtrace_queues__init(&htm->queues);
+	if (err)
+		goto err_free;
+
+	htm->session = session;
+	htm->machine = &session->machines.host; /* No kvm support */
+	htm->auxtrace_type = auxtrace_info->type;
+	htm->pmu_type = auxtrace_info->priv[POWERPC_HTM_TYPE];
+
+	htm->auxtrace.process_event = powerpc_htm_process_event;
+	htm->auxtrace.process_auxtrace_event = powerpc_htm_process_auxtrace_event;
+	htm->auxtrace.flush_events = powerpc_htm_flush;
+	htm->auxtrace.free_events = powerpc_htm_free_events;
+	htm->auxtrace.free = powerpc_htm_free;
+	session->auxtrace = &htm->auxtrace;
+
+	snprintf(htm->htmbin_file, sizeof(htm->htmbin_file), "htm.bin.n%d.p%d.c%d", nodeindex, nodalchipindex, coreindexonchip);
+	fp = fopen(htm->htmbin_file, "w");
+	if (!fp) {
+		pr_err("Failed to create %s: %s\n", htm->htmbin_file, strerror(errno));
+		return -errno;
+	}
+	fclose(fp);
+
+	powerpc_htm_print_info(&auxtrace_info->priv[0]);
+
+	err = auxtrace_queues__process_index(&htm->queues, session);
+	if (err)
+		goto err_free_queues;
+
+	return 0;
+
+err_free_queues:
+	auxtrace_queues__free(&htm->queues);
+	session->auxtrace = NULL;
+
+err_free:
+	free(htm);
+	return err;
+}
diff --git a/tools/perf/util/powerpc-htm.h b/tools/perf/util/powerpc-htm.h
index be7f8c03e161..0dc31fa252b4 100644
--- a/tools/perf/util/powerpc-htm.h
+++ b/tools/perf/util/powerpc-htm.h
@@ -20,4 +20,6 @@ struct perf_session;
 struct perf_pmu;
 
 struct auxtrace_record *htm_recording_init(struct evsel *pos);
+int powerpc_htm_process_auxtrace_info(union perf_event *event,
+					struct perf_session *session);
 #endif
-- 
2.52.0

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help