powerpc/pseries/htmdump: Add htm_hcall_wrapper to integrate other htm operations
authorAthira Rajeev <atrajeev@linux.ibm.com>
Sun, 20 Apr 2025 18:08:36 +0000 (23:38 +0530)
committerMadhavan Srinivasan <maddy@linux.ibm.com>
Sun, 4 May 2025 03:35:47 +0000 (09:05 +0530)
H_HTM (Hardware Trace Macro) hypervisor call is an HCALL to export data
from Hardware Trace Macro (HTM) function. The debugfs interface to
export the HTM function data in an lpar currently supports only dumping
of HTM data in an lpar. To add support for setup, configuration and
control of HTM function via debugfs interface, update the hcall wrapper
function. Rename and update htm_get_dump_hardware to htm_hcall_wrapper()
so that it can be used for other HTM operations as well. Additionally
include parameter "htm_op". Update htmdump module to check the return
code of hcall in a separate function so that it can be reused for other
option too. Add check to disable the interface in guest environment.

Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com>
Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com>
Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
Link: https://patch.msgid.link/20250420180844.53128-2-atrajeev@linux.ibm.com
arch/powerpc/include/asm/plpar_wrappers.h
arch/powerpc/platforms/pseries/htmdump.c

index 91be7b8859449a0bda941f4d1be3c41f997d61b6..f3efa9946b3c365dd424bcfa62b569cc2e7f9ff1 100644 (file)
@@ -65,6 +65,14 @@ static inline long register_dtl(unsigned long cpu, unsigned long vpa)
        return vpa_call(H_VPA_REG_DTL, cpu, vpa);
 }
 
+/*
+ * Invokes H_HTM hcall with parameters passed from htm_hcall_wrapper.
+ * flags: Set to hardwareTarget.
+ * target: Specifies target using node index, nodal chip index and core index.
+ * operation : action to perform ie configure, start, stop, deconfigure, trace
+ * based on the HTM type.
+ * param1, param2, param3: parameters for each action.
+ */
 static inline long htm_call(unsigned long flags, unsigned long target,
                unsigned long operation, unsigned long param1,
                unsigned long param2, unsigned long param3)
@@ -73,17 +81,17 @@ static inline long htm_call(unsigned long flags, unsigned long target,
                                  param1, param2, param3);
 }
 
-static inline long htm_get_dump_hardware(unsigned long nodeindex,
+static inline long htm_hcall_wrapper(unsigned long nodeindex,
                unsigned long nodalchipindex, unsigned long coreindexonchip,
-               unsigned long type, unsigned long addr, unsigned long size,
-               unsigned long offset)
+              unsigned long type, unsigned long htm_op, unsigned long param1, unsigned long param2,
+              unsigned long param3)
 {
        return htm_call(H_HTM_FLAGS_HARDWARE_TARGET,
                        H_HTM_TARGET_NODE_INDEX(nodeindex) |
                        H_HTM_TARGET_NODAL_CHIP_INDEX(nodalchipindex) |
                        H_HTM_TARGET_CORE_INDEX_ON_CHIP(coreindexonchip),
-                       H_HTM_OP(H_HTM_OP_DUMP_DATA) | H_HTM_TYPE(type),
-                       addr, size, offset);
+                      H_HTM_OP(htm_op) | H_HTM_TYPE(type),
+                      param1, param2, param3);
 }
 
 extern void vpa_init(int cpu);
index 57fc1700f604e1a38a79f803e1486d2ebd3dca17..604fde6a05597b670c24debd8dff19478904e4ee 100644 (file)
@@ -18,20 +18,19 @@ static u32 coreindexonchip;
 static u32 htmtype;
 static struct dentry *htmdump_debugfs_dir;
 
-static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
-                            size_t count, loff_t *ppos)
+/*
+ * Check the return code for H_HTM hcall.
+ * Return non-zero value (1) if either H_PARTIAL or H_SUCCESS
+ * is returned. For other return codes:
+ * Return zero if H_NOT_AVAILABLE.
+ * Return -EBUSY if hcall return busy.
+ * Return -EINVAL if any parameter or operation is not valid.
+ * Return -EPERM if HTM Virtualization Engine Technology code
+ * is not applied.
+ * Return -EIO if the HTM state is not valid.
+ */
+static ssize_t htm_return_check(long rc)
 {
-       void *htm_buf = filp->private_data;
-       unsigned long page, read_size, available;
-       loff_t offset;
-       long rc;
-
-       page = ALIGN_DOWN(*ppos, PAGE_SIZE);
-       offset = (*ppos) % PAGE_SIZE;
-
-       rc = htm_get_dump_hardware(nodeindex, nodalchipindex, coreindexonchip,
-                                  htmtype, virt_to_phys(htm_buf), PAGE_SIZE, page);
-
        switch (rc) {
        case H_SUCCESS:
        /* H_PARTIAL for the case where all available data can't be
@@ -65,6 +64,38 @@ static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
                return -EPERM;
        }
 
+       /*
+        * Return 1 for H_SUCCESS/H_PARTIAL
+        */
+       return 1;
+}
+
+static ssize_t htmdump_read(struct file *filp, char __user *ubuf,
+                            size_t count, loff_t *ppos)
+{
+       void *htm_buf = filp->private_data;
+       unsigned long page, read_size, available;
+       loff_t offset;
+       long rc, ret;
+
+       page = ALIGN_DOWN(*ppos, PAGE_SIZE);
+       offset = (*ppos) % PAGE_SIZE;
+
+       /*
+        * Invoke H_HTM call with:
+        * - operation as htm dump (H_HTM_OP_DUMP_DATA)
+        * - last three values are address, size and offset
+        */
+       rc = htm_hcall_wrapper(nodeindex, nodalchipindex, coreindexonchip,
+                                  htmtype, H_HTM_OP_DUMP_DATA, virt_to_phys(htm_buf),
+                                  PAGE_SIZE, page);
+
+       ret = htm_return_check(rc);
+       if (ret <= 0) {
+               pr_debug("H_HTM hcall failed for op: H_HTM_OP_DUMP_DATA, returning %ld\n", ret);
+               return ret;
+       }
+
        available = PAGE_SIZE;
        read_size = min(count, available);
        *ppos += read_size;
@@ -103,6 +134,12 @@ static int htmdump_init_debugfs(void)
 
 static int __init htmdump_init(void)
 {
+       /* Disable on kvm guest */
+       if (is_kvm_guest()) {
+               pr_info("htmdump not supported inside KVM guest\n");
+               return -EOPNOTSUPP;
+       }
+
        if (htmdump_init_debugfs())
                return -ENOMEM;