mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-23 14:11:31 -05:00
iommu/vt-d: debugfs: Add support to show inv queue internals
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@linux.intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Link: https://lore.kernel.org/r/20200516062101.29541-14-baolu.lu@linux.intel.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
@@ -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",
|
||||
(u64)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);
|
||||
|
||||
Reference in New Issue
Block a user