RE: [PATCH v4 2/5] iommu/vt-d: debugfs: Add support to show inv queue internals
From: Tian, Kevin
Date: Thu May 07 2020 - 01:40:00 EST
> From: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
> Sent: Thursday, May 7, 2020 8:56 AM
>
> Export invalidation queue internals of each iommu device through the
> debugfs.
>
> Example of such dump on a Skylake machine:
>
> $ sudo cat /sys/kernel/debug/iommu/intel/invalidation_queue
> Invalidation queue on IOMMU: dmar1
> Base: 0x1672c9000 Head: 80 Tail: 80
> Index qw0 qw1 status
> 0 0000000000000004 0000000000000000 0000000000000000
> 1 0000000200000025 00000001672be804 0000000000000000
> 2 0000000000000011 0000000000000000 0000000000000000
> 3 0000000200000025 00000001672be80c 0000000000000000
> 4 00000000000000d2 0000000000000000 0000000000000000
> 5 0000000200000025 00000001672be814 0000000000000000
> 6 0000000000000014 0000000000000000 0000000000000000
> 7 0000000200000025 00000001672be81c 0000000000000000
> 8 0000000000000014 0000000000000000 0000000000000000
> 9 0000000200000025 00000001672be824 0000000000000000
>
> Signed-off-by: Lu Baolu <baolu.lu@xxxxxxxxxxxxxxx>
> ---
> drivers/iommu/intel-iommu-debugfs.c | 62
> +++++++++++++++++++++++++++++
> 1 file changed, 62 insertions(+)
>
> diff --git a/drivers/iommu/intel-iommu-debugfs.c b/drivers/iommu/intel-
> iommu-debugfs.c
> index 3eb1fe240fb0..e3089865b8f3 100644
> --- a/drivers/iommu/intel-iommu-debugfs.c
> +++ b/drivers/iommu/intel-iommu-debugfs.c
> @@ -372,6 +372,66 @@ static int domain_translation_struct_show(struct
> seq_file *m, void *unused)
> }
> DEFINE_SHOW_ATTRIBUTE(domain_translation_struct);
>
> +static void invalidation_queue_entry_show(struct seq_file *m,
> + struct intel_iommu *iommu)
> +{
> + int index, shift = qi_shift(iommu);
> + struct qi_desc *desc;
> + int offset;
> +
> + if (ecap_smts(iommu->ecap))
> + seq_puts(m,
> "Index\t\tqw0\t\t\tqw1\t\t\tqw2\t\t\tqw3\t\t\tstatus\n");
> + else
> + seq_puts(m, "Index\t\tqw0\t\t\tqw1\t\t\tstatus\n");
> +
> + for (index = 0; index < QI_LENGTH; index++) {
> + offset = index << shift;
> + desc = iommu->qi->desc + offset;
> + if (ecap_smts(iommu->ecap))
> + seq_printf(m,
> "%5d\t%016llx\t%016llx\t%016llx\t%016llx\t%016x\n",
> + index, desc->qw0, desc->qw1,
> + desc->qw2, desc->qw3,
> + iommu->qi->desc_status[index]);
> + else
> + seq_printf(m, "%5d\t%016llx\t%016llx\t%016x\n",
> + index, desc->qw0, desc->qw1,
> + iommu->qi->desc_status[index]);
> + }
> +}
> +
> +static int invalidation_queue_show(struct seq_file *m, void *unused)
> +{
> + struct dmar_drhd_unit *drhd;
> + struct intel_iommu *iommu;
> + unsigned long flags;
> + struct q_inval *qi;
> + int shift;
> +
> + rcu_read_lock();
> + for_each_active_iommu(iommu, drhd) {
> + qi = iommu->qi;
> + shift = qi_shift(iommu);
> +
> + if (!qi || !ecap_qis(iommu->ecap))
> + continue;
> +
> + seq_printf(m, "Invalidation queue on IOMMU: %s\n",
> iommu->name);
> +
> + raw_spin_lock_irqsave(&qi->q_lock, flags);
> + seq_printf(m, " Base: 0x%llx\tHead: %lld\tTail: %lld\n",
> + virt_to_phys(qi->desc),
> + dmar_readq(iommu->reg + DMAR_IQH_REG) >>
> shift,
> + dmar_readq(iommu->reg + DMAR_IQT_REG) >>
> shift);
> + invalidation_queue_entry_show(m, iommu);
> + raw_spin_unlock_irqrestore(&qi->q_lock, flags);
> + seq_putc(m, '\n');
> + }
> + rcu_read_unlock();
> +
> + return 0;
> +}
> +DEFINE_SHOW_ATTRIBUTE(invalidation_queue);
> +
> #ifdef CONFIG_IRQ_REMAP
> static void ir_tbl_remap_entry_show(struct seq_file *m,
> struct intel_iommu *iommu)
> @@ -490,6 +550,8 @@ void __init intel_iommu_debugfs_init(void)
> debugfs_create_file("domain_translation_struct", 0444,
> intel_iommu_debug, NULL,
> &domain_translation_struct_fops);
> + debugfs_create_file("invalidation_queue", 0444, intel_iommu_debug,
> + NULL, &invalidation_queue_fops);
> #ifdef CONFIG_IRQ_REMAP
> debugfs_create_file("ir_translation_struct", 0444,
> intel_iommu_debug,
> NULL, &ir_translation_struct_fops);
> --
> 2.17.1
Reviewed-by: Kevin Tian <kevin.tian@xxxxxxxxx>