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
