[RFC PATCH 5/5] iommu/arm-smmu-v3: Add Context Descriptor display to debugfs

Qinxin Xia xiaqinxin at huawei.com
Fri Mar 13 03:43:51 PDT 2026


Add Context Descriptor (CD) display functionality to debugfs.
This allow inspecting CD contents for all Substream IDs including:
- CD validity and translation parameters
- TTBR0 and TCR configurations
- Raw CD data

/sys/kernel/debug/iommu/arm_smmu_v3/smmu0/stream_table/
└── 0000:01:00.0:0/
    ├── ste
    └── context_descriptors/
        └── all

Signed-off-by: Qinxin Xia <xiaqinxin at huawei.com>
---
 .../arm/arm-smmu-v3/arm-smmu-v3-debugfs.c     | 112 ++++++++++++++++++
 1 file changed, 112 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
index f62df02847ac..66ae1228c6ad 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-debugfs.c
@@ -27,6 +27,13 @@
  * - Context Pointers: Stage 1 and Stage 2 translation context addresses
  * - Raw Data: Complete 64-bit STE words in hexadecimal
  *
+ * CD Information Displayed:
+ * - Validity: Active state of the context descriptor
+ * - T0SZ: Input address space size configuration
+ * - EPD0/EPD1: Stage 1 translation enable flags
+ * - TTBR0: Stage 1 translation table base address
+ * - Raw Data: Complete CD structure in hexadecimal format
+ *
  * Directory Structure:
  * /sys/kernel/debug/iommu/arm_smmu_v3/
  * └── smmu0/
@@ -35,6 +42,8 @@
  *     └── stream_table
  *	   └── 0000:01:00.0:0/                    # PCI device with Stream ID 0
  *             ├── ste                           # Stream Table Entry
+ *             └── context_descriptors/
+ *                 └── all                       # All Context Descriptors
  *
  * The capabilities file provides detailed information about:
  * - Architecture version and translation stage support (Stage1/Stage2)
@@ -59,6 +68,8 @@
 static struct dentry *smmuv3_root_dir;
 static DEFINE_MUTEX(arm_smmu_debugfs_lock);
 
+#define MAX_SSIDS	32	/* Reasonable limit for SSID enumeration */
+
 /**
  * smmu_debugfs_capabilities_show() - Display SMMU capabilities
  * @seq: seq_file to write to
@@ -329,6 +340,90 @@ static int smmu_debugfs_ste_show(struct seq_file *seq, void *v)
 }
 DEFINE_SHOW_ATTRIBUTE(smmu_debugfs_ste);
 
+/**
+ * smmu_debug_dump_cd() - Dump Context Descriptor details to seq_file
+ * @seq: seq_file to write to
+ * @dev: device associated with the CD
+ * @ssid: Substream ID
+ */
+static void smmu_debug_dump_cd(struct seq_file *seq, struct device *dev, u32 ssid)
+{
+	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+	struct arm_smmu_cd *cd;
+	u64 data;
+	int i;
+
+	if (!master) {
+		seq_puts(seq, "No master data\n");
+		return;
+	}
+
+	cd = arm_smmu_get_cd_ptr(master, ssid);
+	if (!cd) {
+		seq_printf(seq, "CD not available for SSID %u\n", ssid);
+		return;
+	}
+
+	seq_printf(seq, "CD for Substream ID %u:\n", ssid);
+
+	/* CD 0 */
+	data = le64_to_cpu(cd->data[0]);
+	seq_printf(seq, "  Valid: %s\n", data & CTXDESC_CD_0_V ? "Yes" : "No");
+	seq_printf(seq, "  T0SZ: 0x%llx\n", data & CTXDESC_CD_0_TCR_T0SZ);
+	seq_printf(seq, "  EPD0: %s\n", data & CTXDESC_CD_0_TCR_EPD0 ? "Yes" : "No");
+	seq_printf(seq, "  EPD1: %s\n", data & CTXDESC_CD_0_TCR_EPD1 ? "Yes" : "No");
+
+	/* CD 1 */
+	data = le64_to_cpu(cd->data[1]);
+	seq_printf(seq, "  TTBR0: 0x%016llx\n", data & CTXDESC_CD_1_TTB0_MASK);
+
+	/* Display raw CD data */
+	seq_puts(seq, "  Raw Data:\n");
+	for (i = 0; i < CTXDESC_CD_DWORDS; i++)
+		seq_printf(seq, "    CD[%d]: 0x%016llx\n", i,
+			   le64_to_cpu(cd->data[i]));
+}
+
+/**
+ * smmu_debug_dump_all_cds() - Dump all valid Context Descriptors for a device
+ * @seq: seq_file to write to
+ * @dev: target device
+ */
+static void smmu_debug_dump_all_cds(struct seq_file *seq, struct device *dev)
+{
+	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
+	u32 max_ssids, ssid;
+
+	if (!master) {
+		seq_puts(seq, "No master data\n");
+		return;
+	}
+
+	max_ssids = min_t(u32, 1 << master->ssid_bits, MAX_SSIDS);
+
+	seq_printf(seq, "Context Descriptors for device (max SSIDs: %u):\n",
+		   max_ssids);
+
+	for (ssid = 0; ssid < max_ssids; ssid++) {
+		struct arm_smmu_cd *cd = arm_smmu_get_cd_ptr(master, ssid);
+
+		if (cd && (le64_to_cpu(cd->data[0]) & CTXDESC_CD_0_V)) {
+			seq_printf(seq, "\n--- SSID %u ---\n", ssid);
+			smmu_debug_dump_cd(seq, dev, ssid);
+		}
+	}
+}
+
+/* All CDs debugfs file operations */
+static int smmu_debugfs_all_cds_show(struct seq_file *seq, void *v)
+{
+	struct device *dev = seq->private;
+
+	smmu_debug_dump_all_cds(seq, dev);
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(smmu_debugfs_all_cds);
+
 /**
  * smmu_debugfs_create_stream_table() - Create debugfs entries for stream table
  * @dev: device to create entries for
@@ -388,9 +483,26 @@ int smmu_debugfs_create_stream_table(struct device *dev,
 			goto cleanup_dev;
 		}
 
+		/* Create CD directory */
+		cd_dir = debugfs_create_dir("context_descriptors", dev_dir);
+		if (!cd_dir) {
+			ret = -ENOMEM;
+			goto cleanup_dev;
+		}
+
+		/* Create "all" file to show all valid CDs */
+		all_cds_file = debugfs_create_file("all", 0444, cd_dir, dev,
+						   &smmu_debugfs_all_cds_fops);
+		if (!all_cds_file) {
+			ret = -ENOMEM;
+			goto cleanup_cd;
+		}
+
 		/* Success for this stream ID, continue to next */
 		continue;
 
+cleanup_cd:
+		debugfs_remove(cd_dir);
 cleanup_dev:
 		debugfs_remove_recursive(dev_dir);
 cleanup:
-- 
2.33.0




More information about the linux-arm-kernel mailing list