> From: Lu Baolu <baolu...@linux.intel.com> > 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...@linux.intel.com> > --- > 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.t...@intel.com>