iommu/amd: Add debugfs support to dump IOMMU MMIO registers

Analyzing IOMMU MMIO registers gives a view of what IOMMU is
configured with on the system and is helpful to debug issues
with IOMMU.

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

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-3-dheerajkumar.srivastava@amd.com
Signed-off-by: Will Deacon <will@kernel.org>
This commit is contained in:
Dheeraj Kumar Srivastava 2025-07-02 15:07:58 +05:30 committed by Will Deacon
parent ad48b1dd14
commit 7a4ee419e8
2 changed files with 48 additions and 0 deletions

View File

@ -795,6 +795,7 @@ struct amd_iommu {
#ifdef CONFIG_AMD_IOMMU_DEBUGFS #ifdef CONFIG_AMD_IOMMU_DEBUGFS
/* DebugFS Info */ /* DebugFS Info */
struct dentry *debugfs; struct dentry *debugfs;
int dbg_mmio_offset;
#endif #endif
/* IOPF support */ /* IOPF support */

View File

@ -15,6 +15,48 @@
static struct dentry *amd_iommu_debugfs; static struct dentry *amd_iommu_debugfs;
#define MAX_NAME_LEN 20 #define MAX_NAME_LEN 20
#define OFS_IN_SZ 8
static ssize_t iommu_mmio_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_mmio_offset = -1;
if (cnt > OFS_IN_SZ)
return -EINVAL;
ret = kstrtou32_from_user(ubuf, cnt, 0, &iommu->dbg_mmio_offset);
if (ret)
return ret;
if (iommu->dbg_mmio_offset > iommu->mmio_phys_end - 4) {
iommu->dbg_mmio_offset = -1;
return -EINVAL;
}
return cnt;
}
static int iommu_mmio_show(struct seq_file *m, void *unused)
{
struct amd_iommu *iommu = m->private;
u64 value;
if (iommu->dbg_mmio_offset < 0) {
seq_puts(m, "Please provide mmio register's offset\n");
return 0;
}
value = readq(iommu->mmio_base + iommu->dbg_mmio_offset);
seq_printf(m, "Offset:0x%x Value:0x%016llx\n", iommu->dbg_mmio_offset, value);
return 0;
}
DEFINE_SHOW_STORE_ATTRIBUTE(iommu_mmio);
void amd_iommu_debugfs_setup(void) void amd_iommu_debugfs_setup(void)
{ {
@ -24,7 +66,12 @@ void amd_iommu_debugfs_setup(void)
amd_iommu_debugfs = debugfs_create_dir("amd", iommu_debugfs_dir); amd_iommu_debugfs = debugfs_create_dir("amd", iommu_debugfs_dir);
for_each_iommu(iommu) { for_each_iommu(iommu) {
iommu->dbg_mmio_offset = -1;
snprintf(name, MAX_NAME_LEN, "iommu%02d", iommu->index); snprintf(name, MAX_NAME_LEN, "iommu%02d", iommu->index);
iommu->debugfs = debugfs_create_dir(name, amd_iommu_debugfs); iommu->debugfs = debugfs_create_dir(name, amd_iommu_debugfs);
debugfs_create_file("mmio", 0644, iommu->debugfs, iommu,
&iommu_mmio_fops);
} }
} }