Add a debugfs entry to dump the active device table entries from
the IOMMU's table. Active is determined by non-default values
in the first and second long words of the DTE. Aside from IOMMU
devices, this output should list every device reported by lspci.

Signed-off-by: Gary R Hook <[email protected]>
---
 drivers/iommu/amd_iommu_debugfs.c |   60 +++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/drivers/iommu/amd_iommu_debugfs.c 
b/drivers/iommu/amd_iommu_debugfs.c
index d95428b1ef90..1d941c5329be 100644
--- a/drivers/iommu/amd_iommu_debugfs.c
+++ b/drivers/iommu/amd_iommu_debugfs.c
@@ -92,9 +92,62 @@ static const struct file_operations 
amd_iommu_debugfs_dtecount_ops = {
        .write = NULL,
 };
 
+#define        MAX_PCI_ID      0xFFFF
+
+#define        PRINTDTE(i)     OSCNPRINTF("%02x:%02x:%x - %016llx %016llx 
%016llx %016llx\n", \
+                                  PCI_BUS_NUM(i), PCI_SLOT(i), PCI_FUNC(i), \
+                                  amd_iommu_dev_table[i].data[0], \
+                                  amd_iommu_dev_table[i].data[1], \
+                                  amd_iommu_dev_table[i].data[2], \
+                                  amd_iommu_dev_table[i].data[3]);
+
+static ssize_t amd_iommu_debugfs_dte_read(struct file *filp,
+                                         char __user *ubuf,
+                                         size_t count, loff_t *offp)
+{
+       unsigned int obuflen;
+       unsigned int oboff = 0;
+       unsigned int istart, iend;
+       ssize_t ret;
+       u32 i, n;
+       char *obuf;
+
+       /* Count the number of valid entries in the device table */
+       istart = 0;
+       iend = MAX_PCI_ID;
+       n = amd_iommu_count_valid_dtes(istart, iend);
+       obuflen = n * 80;
+
+       obuf = kmalloc(OBUFLEN, GFP_KERNEL);
+       if (!obuf)
+               return -ENOMEM;
+
+       for (i = istart ; i <= iend ; i++)
+               if ((amd_iommu_dev_table[i].data[0] ^ 0x3)
+                    || amd_iommu_dev_table[i].data[1])
+                       oboff += PRINTDTE(i);
+
+       ret = simple_read_from_buffer(ubuf, count, offp, obuf, oboff);
+       kfree(obuf);
+
+       return ret;
+}
+
+static const struct file_operations amd_iommu_debugfs_dte_ops = {
+       .owner = THIS_MODULE,
+       .open = simple_open,
+       .read = amd_iommu_debugfs_dte_read,
+       .write = NULL,
+};
+
 static char readmetext[] =
+"devicetable             Print active entries in the device table\n"
 "count                   Count of active devices\n"
 "verbose                 Provide additional descriptive text\n"
+"\n"
+"                        Dumping the Device Table\n"
+"The device table is scanned for entries that appear to be active. The\n"
+"default range is from 0 to 0xFFFF, and only active entries will be reported\n"
 "\n";
 
 static ssize_t amd_iommu_debugfs_readme_read(struct file *filp,
@@ -144,6 +197,13 @@ void amd_iommu_debugfs_setup(struct amd_iommu *iommu)
        if (!d_verbose)
                goto err;
 
+       /* Device Table Entries */
+       d_dte = debugfs_create_file("devicetable", 0400,
+                                   iommu->debugfs_instance, iommu,
+                                   &amd_iommu_debugfs_dte_ops);
+       if (!d_dte)
+               goto err;
+
        d_dte = debugfs_create_file("count", 0400,
                                    iommu->debugfs_instance, iommu,
                                    &amd_iommu_debugfs_dtecount_ops);

Reply via email to