]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
iommu/amd: Add debugfs support to dump device table
authorDheeraj Kumar Srivastava <dheerajkumar.srivastava@amd.com>
Wed, 2 Jul 2025 09:38:02 +0000 (15:08 +0530)
committerWill Deacon <will@kernel.org>
Tue, 15 Jul 2025 10:41:53 +0000 (11:41 +0100)
IOMMU uses device table data structure to get per-device information for
DMA remapping, interrupt remapping, and other functionalities. It's a
valuable data structure to visualize for debugging issues related to
IOMMU.

eg.
-> To dump device table entry for a particular device
   #echo 0000:c4:00.0 > /sys/kernel/debug/iommu/amd/devid
   #cat /sys/kernel/debug/iommu/amd/devtbl

   or

   #echo c4:00.0 > /sys/kernel/debug/iommu/amd/devid
   #cat /sys/kernel/debug/iommu/amd/devtbl

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-7-dheerajkumar.srivastava@amd.com
Signed-off-by: Will Deacon <will@kernel.org>
drivers/iommu/amd/debugfs.c

index 065b150bba15d2fbac85864fcd163c7694751cb7..b01eea2fbe03ba015dd8f934b7384e7bdefd7011 100644 (file)
@@ -208,6 +208,53 @@ static int devid_show(struct seq_file *m, void *unused)
 }
 DEFINE_SHOW_STORE_ATTRIBUTE(devid);
 
+static void dump_dte(struct seq_file *m, struct amd_iommu_pci_seg *pci_seg, u16 devid)
+{
+       struct dev_table_entry *dev_table;
+       struct amd_iommu *iommu;
+
+       iommu = pci_seg->rlookup_table[devid];
+       if (!iommu)
+               return;
+
+       dev_table = get_dev_table(iommu);
+       if (!dev_table) {
+               seq_puts(m, "Device table not found");
+               return;
+       }
+
+       seq_printf(m, "%-12s %16s %16s %16s %16s iommu\n", "DeviceId",
+                  "QWORD[3]", "QWORD[2]", "QWORD[1]", "QWORD[0]");
+       seq_printf(m, "%04x:%02x:%02x.%x ", pci_seg->id, PCI_BUS_NUM(devid),
+                  PCI_SLOT(devid), PCI_FUNC(devid));
+       for (int i = 3; i >= 0; --i)
+               seq_printf(m, "%016llx ", dev_table[devid].data[i]);
+       seq_printf(m, "iommu%d\n", iommu->index);
+}
+
+static int iommu_devtbl_show(struct seq_file *m, void *unused)
+{
+       struct amd_iommu_pci_seg *pci_seg;
+       u16 seg, devid;
+
+       if (sbdf < 0) {
+               seq_puts(m, "Enter a valid device ID to 'devid' file\n");
+               return 0;
+       }
+       seg = PCI_SBDF_TO_SEGID(sbdf);
+       devid = PCI_SBDF_TO_DEVID(sbdf);
+
+       for_each_pci_segment(pci_seg) {
+               if (pci_seg->id != seg)
+                       continue;
+               dump_dte(m, pci_seg, devid);
+               break;
+       }
+
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(iommu_devtbl);
+
 void amd_iommu_debugfs_setup(void)
 {
        struct amd_iommu *iommu;
@@ -232,4 +279,6 @@ void amd_iommu_debugfs_setup(void)
 
        debugfs_create_file("devid", 0644, amd_iommu_debugfs, NULL,
                            &devid_fops);
+       debugfs_create_file("devtbl", 0444, amd_iommu_debugfs, NULL,
+                           &iommu_devtbl_fops);
 }