From: Athira Rajeev <atrajeev@linux.ibm.com>
To: linuxppc-dev@lists.ozlabs.org, maddy@linux.ibm.com
Cc: linux-perf-users@vger.kernel.org, atrajeev@linux.ibm.com,
hbathini@linux.vnet.ibm.com, tejas05@linux.ibm.com,
venkat88@linux.ibm.com, tshah@linux.ibm.com
Subject: [PATCH 3/5] powerpc/perf: Capture the HTM memory configuration as part of perf data
Date: Wed, 1 Jul 2026 14:08:04 +0530 [thread overview]
Message-ID: <20260701083806.79358-4-atrajeev@linux.ibm.com> (raw)
In-Reply-To: <20260701083806.79358-1-atrajeev@linux.ibm.com>
H_HTM (Hardware Trace Macro) hypervisor call has capability
to capture SystemMemory Configuration for a system. This
information helps to understand the physical to logical real
address mapping for the logical partitions in the system.
Along with saving HTM trace data, add support to capture
the memory mapping information also using the hcall.
Patch adds support in perf driver to expose HTM memory
configuration as part of perf.data
When monitoring the HTM pmu, auxiliary buffer captures
the "trace" data and SystemMemory Configuration. This
will be post processed later using perf. The size of memory
mapping data captured depends on how large is the system
and how much memory is allocated. To help with relating
and identifying the start of memory mapping data in the
auxiliary buffer, insert two PERF_SAMPLE_RAW records in the
ring buffer. First PERF_SAMPLE_RAW record will mark the
beginning of system memory mapping data in aux buffer. And second
PERF_SAMPLE_RAW record will be written at the end to make the
end of the data in aux buffer and also contains the total size
of the memory map data. These sample raw records
will be used during post processing in perf report.
Use sample raw to mark memory mapping in aux buffer.
Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com>
---
arch/powerpc/perf/htm-perf.c | 110 ++++++++++++++++++++++++++++++++++-
1 file changed, 108 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/perf/htm-perf.c b/arch/powerpc/perf/htm-perf.c
index ae7f469b6840..fe458bc3ec05 100644
--- a/arch/powerpc/perf/htm-perf.c
+++ b/arch/powerpc/perf/htm-perf.c
@@ -76,6 +76,10 @@ struct htm_pmu_buf {
bool full;
int htm_stopped;
int collect_htm_trace;
+ u64 mem_head;
+ void *htm_mem_buf;
+ u64 mem_start;
+ int collect_htm_mem;
};
struct htm_pmu_ctx {
@@ -143,6 +147,86 @@ static ssize_t htm_return_check(int rc)
return -EINVAL;
}
+static int htm_collect_memory_config(struct perf_event *event,
+ struct htm_pmu_buf *aux_buf)
+{
+ struct perf_sample_data data;
+ struct perf_raw_record raw;
+ struct pt_regs regs;
+ u64 *num_entries;
+ u64 to_copy = 0;
+ int htm_val;
+ long rc;
+ int ret;
+ int retries = 0;
+ size_t size;
+ size_t space_to_end = aux_buf->size - aux_buf->mem_head;
+
+ /* Capture HTM system memory configuration in aux buffer */
+ do {
+ rc = htm_hcall_wrapper(htmflags, 0, 0, 0,
+ 0, H_HTM_OP_DUMP_SYSMEM_CONF, virt_to_phys(aux_buf->htm_mem_buf),
+ PAGE_SIZE, aux_buf->mem_start);
+ ret = htm_return_check(rc);
+ } while (ret == -EBUSY && ++retries < 100);
+
+ /* Return once there is no more data in HTM buffer */
+ if (ret <= 0) {
+ perf_sample_data_init(&data, 0, event->hw.last_period);
+ memset(&raw, 0, sizeof(raw));
+ memset(®s, 0, sizeof(regs));
+
+ htm_val = (aux_buf->head/((aux_buf->nr_pages * PAGE_SIZE)));
+ raw.frag.data = &htm_val;
+ raw.frag.size = sizeof(htm_val);
+
+ aux_buf->collect_htm_mem = 0;
+ perf_sample_save_raw_data(&data, event, &raw);
+ perf_event_overflow(event, &data, ®s);
+ return 0;
+ }
+
+ /*
+ * Find how much data to copy to aux buffer
+ * If hcall returned H_PARTIAL, set mem_start to
+ * indicate next offset of memory to read from
+ */
+ num_entries = aux_buf->htm_mem_buf + 0x10;
+ aux_buf->mem_start = be64_to_cpu(*(u64 *)(aux_buf->htm_mem_buf + 0x8));
+
+ to_copy = 32 + (be64_to_cpu(*num_entries) * 32);
+
+ if (to_copy <= space_to_end) {
+ if ((to_copy + aux_buf->mem_head) >= ((aux_buf->nr_pages * PAGE_SIZE)/2)) {
+ /*
+ * Crossing 50% threshold - flush and wrap.
+ * Write current chunk, then pad to end of buffer.
+ * This ensures next write starts at beginning with
+ * perf head also at beginning (synchronized).
+ */
+ memcpy(aux_buf->base + aux_buf->mem_head, aux_buf->htm_mem_buf, to_copy);
+ aux_buf->mem_head = 0;
+
+ /*
+ * Return space_to_end to include padding.
+ * Perf will advance head to end (wrapping to 0),
+ * matching our mem_head position.
+ */
+ size = space_to_end;
+ } else {
+ /* Normal case - chunk fits without crossing threshold */
+ memcpy(aux_buf->base + aux_buf->mem_head, aux_buf->htm_mem_buf, to_copy);
+ aux_buf->mem_head += to_copy;
+ size = to_copy;
+ }
+ } else {
+ return 0;
+ }
+
+ /* Return non-zero to indicate that one record is written to aux buffer */
+ return size;
+}
+
static int htm_dump_sample_data(struct perf_event *event)
{
struct htm_pmu_ctx *htm_ctx = this_cpu_ptr(&htm_pmu_ctx);
@@ -162,7 +246,7 @@ static int htm_dump_sample_data(struct perf_event *event)
if (!aux_buf)
return -1;
- if (!aux_buf->collect_htm_trace) {
+ if (!aux_buf->collect_htm_mem && !aux_buf->collect_htm_trace) {
perf_aux_output_end(&htm_ctx->handle, 0);
return 0;
}
@@ -202,12 +286,17 @@ static int htm_dump_sample_data(struct perf_event *event)
if (ret > 0) {
aux_buf->head += (aux_buf->nr_pages * PAGE_SIZE);
perf_aux_output_end(&htm_ctx->handle, (aux_buf->nr_pages * PAGE_SIZE));
+ return ret;
} else {
aux_buf->collect_htm_trace = 0;
- perf_aux_output_end(&htm_ctx->handle, 0);
}
}
+ if (aux_buf->collect_htm_mem) {
+ ret = htm_collect_memory_config(event, aux_buf);
+ perf_aux_output_end(&htm_ctx->handle, ret);
+ }
+
return ret;
}
@@ -397,6 +486,13 @@ static void *htm_setup_aux(struct perf_event *event, void **pages,
return NULL;
}
+ buf->htm_mem_buf = kmalloc_node(PAGE_SIZE, GFP_KERNEL, cpu_to_node(cpu));
+ if (!buf->htm_mem_buf) {
+ kfree(buf);
+ pr_err("Failed to allocate htm mem buf\n");
+ return NULL;
+ }
+
buf->nr_pages = nr_pages;
buf->snapshot = false;
buf->size = nr_pages << PAGE_SHIFT;
@@ -404,6 +500,9 @@ static void *htm_setup_aux(struct perf_event *event, void **pages,
buf->head_size = 0;
buf->htm_stopped = 0;
buf->collect_htm_trace = 1;
+ buf->mem_head = 0;
+ buf->collect_htm_mem = 1;
+ buf->mem_start = 0;
return buf;
}
@@ -413,10 +512,17 @@ static void *htm_setup_aux(struct perf_event *event, void **pages,
static void htm_free_aux(void *aux)
{
struct htm_pmu_buf *buf = aux;
+ void *free_mem;
if (!buf)
return;
+ free_mem = buf->htm_mem_buf;
+ buf->htm_mem_buf = NULL;
+
+ smp_mb();
+
+ kfree(free_mem);
kfree(buf);
}
--
2.52.0
next prev parent reply other threads:[~2026-07-01 8:38 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-01 8:38 [PATCH 0/5] powerpc/htm: Add interface to expose HTM trace data via perf Athira Rajeev
2026-07-01 8:38 ` [PATCH 1/5] " Athira Rajeev
2026-07-01 8:50 ` sashiko-bot
2026-07-01 8:38 ` [PATCH 2/5] powerpc/htm: Add support to setup and free aux buffer for capturing HTM data Athira Rajeev
2026-07-01 8:50 ` sashiko-bot
2026-07-01 8:38 ` Athira Rajeev [this message]
2026-07-01 9:02 ` [PATCH 3/5] powerpc/perf: Capture the HTM memory configuration as part of perf data sashiko-bot
2026-07-01 8:38 ` [PATCH 4/5] docs: ABI: sysfs-bus-event_source-devices-htm: Document sysfs event format entries for htm pmu Athira Rajeev
2026-07-01 8:38 ` [PATCH 5/5] powerpc/perf/htm: Add documentation for Hardware Trace Macro PMU Athira Rajeev
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=20260701083806.79358-4-atrajeev@linux.ibm.com \
--to=atrajeev@linux.ibm.com \
--cc=hbathini@linux.vnet.ibm.com \
--cc=linux-perf-users@vger.kernel.org \
--cc=linuxppc-dev@lists.ozlabs.org \
--cc=maddy@linux.ibm.com \
--cc=tejas05@linux.ibm.com \
--cc=tshah@linux.ibm.com \
--cc=venkat88@linux.ibm.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