[PATCH] powerpc/pseries/htmdump: Add memory configuration dump support to htmdump module

Athira Rajeev atrajeev at linux.ibm.com
Sun Mar 15 00:29:53 AEDT 2026


H_HTM (Hardware Trace Macro) hypervisor call has capability
to capture SystemMemory Configuration. This information
helps to understand the address mapping for the partitions
in the system.

Support dumping system memory configuration from Hardware
Trace Macro (HTM) function via debugfs interface. Under
debugfs folder "/sys/kernel/debug/powerpc/htmdump", add
file "htmsystem_mem".

The interface allows only read of this file which will present the
content of HTM buffer from the hcall. The 16th offset of HTM
buffer has value for the number of entries for array of processors.
Use this information to copy data to the debugfs file

Signed-off-by: Athira Rajeev <atrajeev at linux.ibm.com>
---
Note: This is dependent on patch set posted here which added
bug fixes/clean up:
https://lore.kernel.org/linuxppc-dev/20260314132432.25581-1-atrajeev@linux.ibm.com/T/#t

 arch/powerpc/platforms/pseries/htmdump.c | 70 ++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/arch/powerpc/platforms/pseries/htmdump.c b/arch/powerpc/platforms/pseries/htmdump.c
index 76444c6c5cc1..489a80e87082 100644
--- a/arch/powerpc/platforms/pseries/htmdump.c
+++ b/arch/powerpc/platforms/pseries/htmdump.c
@@ -16,6 +16,7 @@ static void *htm_buf;
 static void *htm_status_buf;
 static void *htm_info_buf;
 static void *htm_caps_buf;
+static void *htm_mem_buf;
 static u32 nodeindex;
 static u32 nodalchipindex;
 static u32 coreindexonchip;
@@ -115,12 +116,72 @@ static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
 	return simple_read_from_buffer(ubuf, count, &offset, htm_buf_data, available);
 }
 
+static ssize_t htmsystem_mem_read(struct file *filp, char __user *ubuf,
+		size_t count, loff_t *ppos)
+{
+	void *htm_mem_data = filp->private_data;
+	long rc, ret;
+	u64 *num_entries;
+	u64 to_copy = 0;
+	loff_t offset = 0;
+	u64 mem_offset = 0;
+
+	/*
+	 * Invoke H_HTM call with:
+	 * - operation as htm status (H_HTM_OP_STATUS)
+	 * - last three values as addr, size and offset. "offset"
+	 *   is value from output buffer header that points to next
+	 *   entry to dump. 0 is the first entry to dump. next entry
+	 *   is read from the output bufferbyte offset 0x8.
+	 *
+	 *   When first time hcall is invoked, mem_offset should be
+	 *   zero because zero is the first entry.
+	 *   In the next hcall, offset of next entry to read from is
+	 *   picked from output buffer header itself. So don't fill
+	 *   mem_offset for first read.
+	 *
+	 *  If there is no further data to read in next iteration,
+	 *  offset value from output buffer header will point to -1.
+	 */
+	if (*ppos) {
+		mem_offset = *(u64 *)(htm_mem_data  + 0x8);
+		if (mem_offset == -1)
+			return 0;
+	}
+	rc = htm_hcall_wrapper(htmflags, nodeindex, nodalchipindex, coreindexonchip,
+			htmtype, H_HTM_OP_DUMP_SYSMEM_CONF, virt_to_phys(htm_mem_data),
+			PAGE_SIZE, be64_to_cpu(mem_offset));
+	ret = htm_return_check(rc);
+	if (ret <= 0) {
+		pr_debug("H_HTM hcall returned for op: H_HTM_OP_DUMP_SYSMEM_CONF with hcall returning  %ld\n", ret);
+		return ret;
+	}
+
+	/*
+	 * HTM system mem buffer, start of buffer + 0x10 gives the
+	 * number of HTM entries in the buffer.
+	 * So total count to copy is:
+	 * 32 bytes (for first 5 fields) + (number of HTM entries * entry size)
+	 */
+	num_entries = htm_mem_data + 0x10;
+	to_copy = 32 + (be64_to_cpu(*num_entries) * 32);
+
+	*ppos += to_copy;
+	return simple_read_from_buffer(ubuf, count, &offset, htm_mem_data, to_copy);
+}
+
 static const struct file_operations htmdump_fops = {
 	.llseek = NULL,
 	.read	= htmdump_read,
 	.open	= simple_open,
 };
 
+static const struct file_operations htmsystem_mem_fops = {
+	.llseek = NULL,
+	.read   = htmsystem_mem_read,
+	.open   = simple_open,
+};
+
 static int  htmconfigure_set(void *data, u64 val)
 {
 	long rc, ret;
@@ -483,9 +544,17 @@ static int htmdump_init_debugfs(void)
 		return -ENOMEM;
 	}
 
+	/* Memory to present HTM system memory configuration */
+	htm_mem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!htm_mem_buf) {
+		pr_err("Failed to allocate htm mem buf\n");
+		return -ENOMEM;
+	}
+
 	debugfs_create_file("htmstatus", 0400, htmdump_debugfs_dir, htm_status_buf, &htmstatus_fops);
 	debugfs_create_file("htminfo", 0400, htmdump_debugfs_dir, htm_info_buf, &htminfo_fops);
 	debugfs_create_file("htmcaps", 0400, htmdump_debugfs_dir, htm_caps_buf, &htmcaps_fops);
+	debugfs_create_file("htmsystem_mem", 0400, htmdump_debugfs_dir, htm_mem_buf, &htmsystem_mem_fops);
 
 	return 0;
 }
@@ -511,6 +580,7 @@ static void __exit htmdump_exit(void)
 	kfree(htm_status_buf);
 	kfree(htm_info_buf);
 	kfree(htm_caps_buf);
+	kfree(htm_mem_buf);
 }
 
 module_init(htmdump_init);
-- 
2.47.3



More information about the Linuxppc-dev mailing list