It is often useful to know the state of all contexts and what devices
are in it. It can also be used to know what device belong to which domains.

Signed-off-by: Teddy Astie <[email protected]>
---
v7: introduced

 xen/drivers/passthrough/amd/iommu_init.c | 46 ++++++++++++++++++++++++
 xen/drivers/passthrough/vtd/iommu.c      | 45 ++++++++++++++++++++++-
 2 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/xen/drivers/passthrough/amd/iommu_init.c 
b/xen/drivers/passthrough/amd/iommu_init.c
index bf32b6c718..1c38ac0369 100644
--- a/xen/drivers/passthrough/amd/iommu_init.c
+++ b/xen/drivers/passthrough/amd/iommu_init.c
@@ -1332,6 +1332,51 @@ static int __init cf_check amd_iommu_setup_device_table(
     return 0;
 }
 
+static void cf_check amd_dump_domain_iommu_contexts(struct domain *d)
+{
+    unsigned int i, iommu_no;
+    struct domain_iommu *hd = dom_iommu(d);
+    struct iommu_context *ctx;
+    struct pci_dev *pdev;
+
+    if (d == dom_io)
+        printk("d[IO] contexts\n");
+    else
+        printk("d%hu contexts\n", d->domain_id);
+
+    for (i = 0; i < (1 + hd->other_contexts.count); ++i)
+    {
+        if ( (ctx = iommu_get_context(d, i)) )
+        {
+            printk(" Context %d (%"PRI_mfn")\n", i,
+                   mfn_x(page_to_mfn(ctx->arch.amd.root_table)));
+
+            for (iommu_no = 0; iommu_no < nr_amd_iommus; iommu_no++)
+                printk("  IOMMU %u (used=%lu; did=%hu)\n", iommu_no,
+                       ctx->arch.amd.iommu_dev_cnt[iommu_no],
+                       ctx->arch.amd.didmap[iommu_no]);
+
+            list_for_each_entry(pdev, &ctx->devices, context_list)
+            {
+                printk("  - %pp\n", &pdev->sbdf);
+            }
+
+            iommu_put_context(ctx);
+        }
+    }
+}
+
+static void cf_check amd_dump_iommu_contexts(unsigned char key)
+{
+    struct domain *d;
+
+    for_each_domain(d)
+        if (is_iommu_enabled(d))
+            amd_dump_domain_iommu_contexts(d);
+
+    amd_dump_domain_iommu_contexts(dom_io);
+}
+
 /* Check whether SP5100 SATA Combined mode is on */
 static bool __init amd_sp5100_erratum28(void)
 {
@@ -1486,6 +1531,7 @@ int __init amd_iommu_init(bool xt)
         register_keyhandler('V', &amd_iommu_dump_intremap_tables,
                             "dump IOMMU intremap tables", 0);
 
+    register_keyhandler('X', amd_dump_iommu_contexts, "dump iommu contexts", 
1);
     return 0;
 
 error_out:
diff --git a/xen/drivers/passthrough/vtd/iommu.c 
b/xen/drivers/passthrough/vtd/iommu.c
index 3319903297..a602edd755 100644
--- a/xen/drivers/passthrough/vtd/iommu.c
+++ b/xen/drivers/passthrough/vtd/iommu.c
@@ -1954,6 +1954,49 @@ static int __must_check init_vtd_hw(bool resume)
     return iommu_flush_all();
 }
 
+static void cf_check vtd_dump_domain_contexts(struct domain *d)
+{
+    unsigned int i, iommu_no;
+    struct pci_dev *pdev;
+    struct iommu_context *ctx;
+    struct domain_iommu *hd = dom_iommu(d);
+
+    if (d == dom_io)
+        printk("d[IO] contexts\n");
+    else
+        printk("d%hu contexts\n", d->domain_id);
+
+    for (i = 0; i < (1 + hd->other_contexts.count); ++i)
+    {
+        if ( (ctx = iommu_get_context(d, i)) )
+        {
+            printk(" Context %d (%"PRIx64")\n", i, ctx->arch.vtd.pgd_maddr);
+
+            for (iommu_no = 0; iommu_no < nr_iommus; iommu_no++)
+                printk("  IOMMU %u (used=%lu; did=%hu)\n", iommu_no,
+                       ctx->arch.vtd.iommu_dev_cnt[iommu_no],
+                       ctx->arch.vtd.didmap[iommu_no]);
+
+            list_for_each_entry(pdev, &ctx->devices, context_list)
+            {
+                printk("  - %pp\n", &pdev->sbdf);
+            }
+
+            iommu_put_context(ctx);
+        }
+    }
+}
+
+static void cf_check vtd_dump_contexts(unsigned char key)
+{
+    struct domain *d;
+
+    for_each_domain(d)
+        if (is_iommu_enabled(d))
+            vtd_dump_domain_contexts(d);
+
+    vtd_dump_domain_contexts(dom_io);
+}
 
 static struct iommu_state {
     uint32_t fectl;
@@ -2088,7 +2131,7 @@ static int __init cf_check vtd_setup(void)
     iommu_ops.page_sizes |= large_sizes;
 
     register_keyhandler('V', vtd_dump_iommu_info, "dump iommu info", 1);
-
+    register_keyhandler('X', vtd_dump_contexts, "dump iommu contexts", 1);
     return 0;
 
  error:
-- 
2.51.2



--
Teddy Astie | Vates XCP-ng Developer

XCP-ng & Xen Orchestra - Vates solutions

web: https://vates.tech


Reply via email to