]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iommu/amd: Add debugfs support to dump IOMMU Capability registers
authorDheeraj Kumar Srivastava <dheerajkumar.srivastava@amd.com>
Wed, 2 Jul 2025 09:37:59 +0000 (15:07 +0530)
committerWill Deacon <will@kernel.org>
Tue, 15 Jul 2025 10:41:52 +0000 (11:41 +0100)
IOMMU Capability registers defines capabilities of IOMMU and information
needed for initialising MMIO registers and device table. This is useful
to dump these registers for debugging IOMMU related issues.

e.g.
-> To get capability registers value at offset 0x10 for iommu<x> (say,
   iommu00)
   # echo "0x10" > /sys/kernel/debug/iommu/amd/iommu00/capability
   # cat /sys/kernel/debug/iommu/amd/iommu00/capability

Signed-off-by: Dheeraj Kumar Srivastava <dheerajkumar.srivastava@amd.com>
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
Link: https://lore.kernel.org/r/20250702093804.849-4-dheerajkumar.srivastava@amd.com
Signed-off-by: Will Deacon <will@kernel.org>
drivers/iommu/amd/amd_iommu_types.h
drivers/iommu/amd/debugfs.c

index e3148d7ddffe310f102800a027141d140b7279f1..ac61f73a110bc88fa6286ed3557ab46e3d65fa78 100644 (file)
@@ -796,6 +796,7 @@ struct amd_iommu {
        /* DebugFS Info */
        struct dentry *debugfs;
        int dbg_mmio_offset;
+       int dbg_cap_offset;
 #endif
 
        /* IOPF support */
index c025b4d2398de66aefc225a94b79cf8270bfeb49..f843e184a62b2bb1a55b8e6f00da94fc6103eff0 100644 (file)
@@ -58,6 +58,55 @@ static int iommu_mmio_show(struct seq_file *m, void *unused)
 }
 DEFINE_SHOW_STORE_ATTRIBUTE(iommu_mmio);
 
+static ssize_t iommu_capability_write(struct file *filp, const char __user *ubuf,
+                                     size_t cnt, loff_t *ppos)
+{
+       struct seq_file *m = filp->private_data;
+       struct amd_iommu *iommu = m->private;
+       int ret;
+
+       iommu->dbg_cap_offset = -1;
+
+       if (cnt > OFS_IN_SZ)
+               return -EINVAL;
+
+       ret = kstrtou32_from_user(ubuf, cnt, 0, &iommu->dbg_cap_offset);
+       if (ret)
+               return ret;
+
+       /* Capability register at offset 0x14 is the last IOMMU capability register. */
+       if (iommu->dbg_cap_offset > 0x14) {
+               iommu->dbg_cap_offset = -1;
+               return -EINVAL;
+       }
+
+       return cnt;
+}
+
+static int iommu_capability_show(struct seq_file *m, void *unused)
+{
+       struct amd_iommu *iommu = m->private;
+       u32 value;
+       int err;
+
+       if (iommu->dbg_cap_offset < 0) {
+               seq_puts(m, "Please provide capability register's offset in the range [0x00 - 0x14]\n");
+               return 0;
+       }
+
+       err = pci_read_config_dword(iommu->dev, iommu->cap_ptr + iommu->dbg_cap_offset, &value);
+       if (err) {
+               seq_printf(m, "Not able to read capability register at 0x%x\n",
+                          iommu->dbg_cap_offset);
+               return 0;
+       }
+
+       seq_printf(m, "Offset:0x%x Value:0x%08x\n", iommu->dbg_cap_offset, value);
+
+       return 0;
+}
+DEFINE_SHOW_STORE_ATTRIBUTE(iommu_capability);
+
 void amd_iommu_debugfs_setup(void)
 {
        struct amd_iommu *iommu;
@@ -67,11 +116,14 @@ void amd_iommu_debugfs_setup(void)
 
        for_each_iommu(iommu) {
                iommu->dbg_mmio_offset = -1;
+               iommu->dbg_cap_offset = -1;
 
                snprintf(name, MAX_NAME_LEN, "iommu%02d", iommu->index);
                iommu->debugfs = debugfs_create_dir(name, amd_iommu_debugfs);
 
                debugfs_create_file("mmio", 0644, iommu->debugfs, iommu,
                                    &iommu_mmio_fops);
+               debugfs_create_file("capability", 0644, iommu->debugfs, iommu,
+                                   &iommu_capability_fops);
        }
 }