public inbox for linux-riscv@lists.infradead.org
 help / color / mirror / Atom feed
From: Sean Chang <seanwascoding@gmail.com>
To: tjeznach@rivosinc.com, joro@8bytes.org
Cc: will@kernel.org, iommu@lists.linux.dev,
	linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org,
	Sean Chang <seanwascoding@gmail.com>
Subject: [PATCH] iommu/riscv: Add DebugFS support for register dump
Date: Mon, 23 Mar 2026 23:58:06 +0800	[thread overview]
Message-ID: <20260323155806.97130-1-seanwascoding@gmail.com> (raw)

Add a DebugFS interface to allow users to dump the internal state of
the RISC-V IOMMU hardware. This is essential for diagnosing hardware
initialization issues and debugging driver-hardware communication
such as Command or Fault queue stalls.

The implementation exposes a "registers" file under the device's
debugfs directory. It uses the standard debugfs_regset32 structure
to dump core registers:

* Global configuration: capabilities, fctl, ddtp
* Command Queue: cqb, cqh, cqt, cqcsr
* Fault Queue: fqb, fqh, fqt, fqcsr
* Interrupts: ipsr, icvec

Signed-off-by: Sean Chang <seanwascoding@gmail.com>
---
 drivers/iommu/riscv/Kconfig   | 11 ++++++++
 drivers/iommu/riscv/Makefile  |  1 +
 drivers/iommu/riscv/debugfs.c | 53 +++++++++++++++++++++++++++++++++++
 drivers/iommu/riscv/iommu.c   |  3 ++
 drivers/iommu/riscv/iommu.h   | 12 ++++++++
 5 files changed, 80 insertions(+)
 create mode 100644 drivers/iommu/riscv/debugfs.c

diff --git a/drivers/iommu/riscv/Kconfig b/drivers/iommu/riscv/Kconfig
index b86e5ab94183..c2ba12d97e98 100644
--- a/drivers/iommu/riscv/Kconfig
+++ b/drivers/iommu/riscv/Kconfig
@@ -22,3 +22,14 @@ config RISCV_IOMMU_PCI
 	def_bool y if RISCV_IOMMU && PCI_MSI
 	help
 	  Support for the PCIe implementation of RISC-V IOMMU architecture.
+
+config RISCV_IOMMU_DEBUGFS
+    bool "RISC-V IOMMU Debugfs Support"
+    depends on RISCV_IOMMU
+    depends on IOMMU_DEBUGFS
+    help
+      Expose RISC-V IOMMU internals via debugfs. This includes
+      register dumps, queue status, and other hardware-specific
+      information useful for debugging.
+
+      If unsure, say N.
diff --git a/drivers/iommu/riscv/Makefile b/drivers/iommu/riscv/Makefile
index b5929f9f23e6..9658a10d8b24 100644
--- a/drivers/iommu/riscv/Makefile
+++ b/drivers/iommu/riscv/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-y += iommu.o iommu-platform.o
 obj-$(CONFIG_RISCV_IOMMU_PCI) += iommu-pci.o
+obj-$(CONFIG_RISCV_IOMMU_DEBUGFS) += debugfs.o
diff --git a/drivers/iommu/riscv/debugfs.c b/drivers/iommu/riscv/debugfs.c
new file mode 100644
index 000000000000..52dc50a7fa20
--- /dev/null
+++ b/drivers/iommu/riscv/debugfs.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+
+#include "iommu.h"
+
+static const struct debugfs_reg32 riscv_iommu_regs[] = {
+	/* --- Global Configuration --- */
+	{ .name = "capabilities",       .offset = RISCV_IOMMU_REG_CAPABILITIES  },
+	{ .name = "fctl",               .offset = RISCV_IOMMU_REG_FCTL          },
+	{ .name = "ddtp",               .offset = RISCV_IOMMU_REG_DDTP          },
+	/* --- Command Queue --- */
+	{ .name = "cqb",                .offset = RISCV_IOMMU_REG_CQB           },
+	{ .name = "cqh",                .offset = RISCV_IOMMU_REG_CQH           },
+	{ .name = "cqt",                .offset = RISCV_IOMMU_REG_CQT           },
+	{ .name = "cqcsr",              .offset = RISCV_IOMMU_REG_CQCSR         },
+	/* --- Fault Queue --- */
+	{ .name = "fqb",                .offset = RISCV_IOMMU_REG_FQB           },
+	{ .name = "fqh",                .offset = RISCV_IOMMU_REG_FQH           },
+	{ .name = "fqt",                .offset = RISCV_IOMMU_REG_FQT           },
+	{ .name = "fqcsr",              .offset = RISCV_IOMMU_REG_FQCSR         },
+	/* --- Interrupts --- */
+	{ .name = "ipsr",               .offset = RISCV_IOMMU_REG_IPSR          },
+	{ .name = "icvec",              .offset = RISCV_IOMMU_REG_ICVEC         },
+};
+
+void riscv_iommu_debugfs_init(struct riscv_iommu_device *iommu)
+{
+	struct debugfs_regset32 *regset;
+
+	if (!iommu_debugfs_dir)
+		return;
+
+	iommu->debugfs_dir = debugfs_create_dir(dev_name(iommu->dev), iommu_debugfs_dir);
+	if (IS_ERR_OR_NULL(iommu->debugfs_dir))
+		return;
+
+	regset = devm_kzalloc(iommu->dev, sizeof(*regset), GFP_KERNEL);
+	if (!regset)
+		return;
+
+	regset->regs = riscv_iommu_regs;
+	regset->nregs = ARRAY_SIZE(riscv_iommu_regs);
+	regset->base = iommu->reg;
+
+	debugfs_create_regset32("registers", 0444, iommu->debugfs_dir, regset);
+}
+
+void riscv_iommu_debugfs_remove(struct riscv_iommu_device *iommu)
+{
+	debugfs_remove_recursive(iommu->debugfs_dir);
+}
diff --git a/drivers/iommu/riscv/iommu.c b/drivers/iommu/riscv/iommu.c
index 368f3cbd2d0a..a4fa0307b32a 100644
--- a/drivers/iommu/riscv/iommu.c
+++ b/drivers/iommu/riscv/iommu.c
@@ -1466,6 +1466,7 @@ void riscv_iommu_remove(struct riscv_iommu_device *iommu)
 	riscv_iommu_iodir_set_mode(iommu, RISCV_IOMMU_DDTP_IOMMU_MODE_OFF);
 	riscv_iommu_queue_disable(&iommu->cmdq);
 	riscv_iommu_queue_disable(&iommu->fltq);
+	riscv_iommu_debugfs_remove(iommu);
 }
 
 int riscv_iommu_init(struct riscv_iommu_device *iommu)
@@ -1526,6 +1527,8 @@ int riscv_iommu_init(struct riscv_iommu_device *iommu)
 		goto err_remove_sysfs;
 	}
 
+	riscv_iommu_debugfs_init(iommu);
+
 	return 0;
 
 err_remove_sysfs:
diff --git a/drivers/iommu/riscv/iommu.h b/drivers/iommu/riscv/iommu.h
index 46df79dd5495..1084e4e77455 100644
--- a/drivers/iommu/riscv/iommu.h
+++ b/drivers/iommu/riscv/iommu.h
@@ -60,6 +60,10 @@ struct riscv_iommu_device {
 	unsigned int ddt_mode;
 	dma_addr_t ddt_phys;
 	u64 *ddt_root;
+
+#ifdef CONFIG_RISCV_IOMMU_DEBUGFS
+	struct dentry *debugfs_dir;
+#endif
 };
 
 int riscv_iommu_init(struct riscv_iommu_device *iommu);
@@ -86,4 +90,12 @@ void riscv_iommu_disable(struct riscv_iommu_device *iommu);
 	readx_poll_timeout(readl_relaxed, (iommu)->reg + (addr), val, cond, \
 			   delay_us, timeout_us)
 
+#ifdef CONFIG_RISCV_IOMMU_DEBUGFS
+void riscv_iommu_debugfs_init(struct riscv_iommu_device *iommu);
+void riscv_iommu_debugfs_remove(struct riscv_iommu_device *iommu);
+#else
+static inline void riscv_iommu_debugfs_init(struct riscv_iommu_device *iommu) { }
+static inline void riscv_iommu_debugfs_remove(struct riscv_iommu_device *iommu) { }
+#endif
+
 #endif
-- 
2.34.1


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

                 reply	other threads:[~2026-03-23 15:58 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

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=20260323155806.97130-1-seanwascoding@gmail.com \
    --to=seanwascoding@gmail.com \
    --cc=iommu@lists.linux.dev \
    --cc=joro@8bytes.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=tjeznach@rivosinc.com \
    --cc=will@kernel.org \
    /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