[PATCH v3 4/5] iommu/amd - Expose the active IOMMU device table entries

From: Gary R Hook
Date: Wed Mar 14 2018 - 19:05:39 EST


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 <gary.hook@xxxxxxx>
---
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);