History

iommu/vt-d: debugfs: Add support to show page table internals

Export page table internals of the domain attached to each device. Example of such dump on a Skylake machine: $ sudo cat /sys/kernel/debug/iommu/intel/domain_translation_struct [ ... ] Device 0000:00:14.0 with pasid 0 @0x15f3d9000 IOVA_PFN PML5E PML4E 0x000000008ced0 | 0x0000000000000000 0x000000015f3da003 0x000000008ced1 | 0x0000000000000000 0x000000015f3da003 0x000000008ced2 | 0x0000000000000000 0x000000015f3da003 0x000000008ced3 | 0x0000000000000000 0x000000015f3da003 0x000000008ced4 | 0x0000000000000000 0x000000015f3da003 0x000000008ced5 | 0x0000000000000000 0x000000015f3da003 0x000000008ced6 | 0x0000000000000000 0x000000015f3da003 0x000000008ced7 | 0x0000000000000000 0x000000015f3da003 0x000000008ced8 | 0x0000000000000000 0x000000015f3da003 0x000000008ced9 | 0x0000000000000000 0x000000015f3da003 PDPE PDE PTE 0x000000015f3db003 0x000000015f3dc003 0x000000008ced0003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced1003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced2003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced3003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced4003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced5003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced6003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced7003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced8003 0x000000015f3db003 0x000000015f3dc003 0x000000008ced9003 [ ... ]

Lu Baolu committed 6 years ago

Commit e2726da1 parent b802d073 files · +79 −2Browse files

Unified · Split

3 files
  1. drivers/iommu/intel-iommu-debugfs.c +75 −0
  2. drivers/iommu/intel-iommu.c +2 −2
  3. include/linux/intel-iommu.h +2 −0
drivers/iommu/intel-iommu-debugfs.c+75−0
@@ -5,6 +5,7 @@ · 4 unmodified lines
5 * Authors: Gayatri Kammela <gayatri.kammela@intel.com>5 * Authors: Gayatri Kammela <gayatri.kammela@intel.com>
6 * Sohil Mehta <sohil.mehta@intel.com>6 * Sohil Mehta <sohil.mehta@intel.com>
7 * Jacob Pan <jacob.jun.pan@linux.intel.com>7 * Jacob Pan <jacob.jun.pan@linux.intel.com>
8 * Lu Baolu <baolu.lu@linux.intel.com>
8 */9 */
9 10
10#include <linux/debugfs.h>11#include <linux/debugfs.h>
@@ -283,6 +284,77 @@ static int dmar_translation_struct_show(struct seq_file *m, void *unused) · 272 unmodified lines
283}284}
284DEFINE_SHOW_ATTRIBUTE(dmar_translation_struct);285DEFINE_SHOW_ATTRIBUTE(dmar_translation_struct);
285 286
287static inline unsigned long level_to_directory_size(int level)
288{
289 return BIT_ULL(VTD_PAGE_SHIFT + VTD_STRIDE_SHIFT * (level - 1));
290}
291
292static inline void
293dump_page_info(struct seq_file *m, unsigned long iova, u64 *path)
294{
295 seq_printf(m, "0x%013lx |\t0x%016llx\t0x%016llx\t0x%016llx\t0x%016llx\t0x%016llx\n",
296 iova >> VTD_PAGE_SHIFT, path[5], path[4],
297 path[3], path[2], path[1]);
298}
299
300static void pgtable_walk_level(struct seq_file *m, struct dma_pte *pde,
301 int level, unsigned long start,
302 u64 *path)
303{
304 int i;
305
306 if (level > 5 || level < 1)
307 return;
308
309 for (i = 0; i < BIT_ULL(VTD_STRIDE_SHIFT);
310 i++, pde++, start += level_to_directory_size(level)) {
311 if (!dma_pte_present(pde))
312 continue;
313
314 path[level] = pde->val;
315 if (dma_pte_superpage(pde) || level == 1)
316 dump_page_info(m, start, path);
317 else
318 pgtable_walk_level(m, phys_to_virt(dma_pte_addr(pde)),
319 level - 1, start, path);
320 path[level] = 0;
321 }
322}
323
324static int show_device_domain_translation(struct device *dev, void *data)
325{
326 struct dmar_domain *domain = find_domain(dev);
327 struct seq_file *m = data;
328 u64 path[6] = { 0 };
329
330 if (!domain)
331 return 0;
332
333 seq_printf(m, "Device %s with pasid %d @0x%llx\n",
334 dev_name(dev), domain->default_pasid,
335 (u64)virt_to_phys(domain->pgd));
336 seq_puts(m, "IOVA_PFN\t\tPML5E\t\t\tPML4E\t\t\tPDPE\t\t\tPDE\t\t\tPTE\n");
337
338 pgtable_walk_level(m, domain->pgd, domain->agaw + 2, 0, path);
339 seq_putc(m, '\n');
340
341 return 0;
342}
343
344static int domain_translation_struct_show(struct seq_file *m, void *unused)
345{
346 unsigned long flags;
347 int ret;
348
349 spin_lock_irqsave(&device_domain_lock, flags);
350 ret = bus_for_each_dev(&pci_bus_type, NULL, m,
351 show_device_domain_translation);
352 spin_unlock_irqrestore(&device_domain_lock, flags);
353
354 return ret;
355}
356DEFINE_SHOW_ATTRIBUTE(domain_translation_struct);
357
286#ifdef CONFIG_IRQ_REMAP358#ifdef CONFIG_IRQ_REMAP
287static void ir_tbl_remap_entry_show(struct seq_file *m,359static void ir_tbl_remap_entry_show(struct seq_file *m,
288 struct intel_iommu *iommu)360 struct intel_iommu *iommu)
@@ -396,6 +468,9 @@ void __init intel_iommu_debugfs_init(void) · 107 unmodified lines
396 &iommu_regset_fops);468 &iommu_regset_fops);
397 debugfs_create_file("dmar_translation_struct", 0444, intel_iommu_debug,469 debugfs_create_file("dmar_translation_struct", 0444, intel_iommu_debug,
398 NULL, &dmar_translation_struct_fops);470 NULL, &dmar_translation_struct_fops);
471 debugfs_create_file("domain_translation_struct", 0444,
472 intel_iommu_debug, NULL,
473 &domain_translation_struct_fops);
399#ifdef CONFIG_IRQ_REMAP474#ifdef CONFIG_IRQ_REMAP
400 debugfs_create_file("ir_translation_struct", 0444, intel_iommu_debug,475 debugfs_create_file("ir_translation_struct", 0444, intel_iommu_debug,
401 NULL, &ir_translation_struct_fops);476 NULL, &ir_translation_struct_fops);
drivers/iommu/intel-iommu.c+2−2
@@ -396,7 +396,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); · 395 unmodified lines
396 396
397#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))397#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
398#define DEFER_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-2))398#define DEFER_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-2))
399static DEFINE_SPINLOCK(device_domain_lock);399DEFINE_SPINLOCK(device_domain_lock);
400static LIST_HEAD(device_domain_list);400static LIST_HEAD(device_domain_list);
401 401
402#define device_needs_bounce(d) (!intel_no_bounce && dev_is_pci(d) && \402#define device_needs_bounce(d) (!intel_no_bounce && dev_is_pci(d) && \
@@ -2513,7 +2513,7 @@ static void domain_remove_dev_info(struct dmar_domain *domain) · 2110 unmodified lines
2513 spin_unlock_irqrestore(&device_domain_lock, flags);2513 spin_unlock_irqrestore(&device_domain_lock, flags);
2514}2514}
2515 2515
2516static struct dmar_domain *find_domain(struct device *dev)2516struct dmar_domain *find_domain(struct device *dev)
2517{2517{
2518 struct device_domain_info *info;2518 struct device_domain_info *info;
2519 2519
include/linux/intel-iommu.h+2−0
@@ -441,6 +441,7 @@ enum { · 440 unmodified lines
441#define VTD_FLAG_SVM_CAPABLE (1 << 2)441#define VTD_FLAG_SVM_CAPABLE (1 << 2)
442 442
443extern int intel_iommu_sm;443extern int intel_iommu_sm;
444extern spinlock_t device_domain_lock;
444 445
445#define sm_supported(iommu) (intel_iommu_sm && ecap_smts((iommu)->ecap))446#define sm_supported(iommu) (intel_iommu_sm && ecap_smts((iommu)->ecap))
446#define pasid_supported(iommu) (sm_supported(iommu) && \447#define pasid_supported(iommu) (sm_supported(iommu) && \
@@ -663,6 +664,7 @@ int for_each_device_domain(int (*fn)(struct device_domain_info *info, · 216 unmodified lines
663 void *data), void *data);664 void *data), void *data);
664void iommu_flush_write_buffer(struct intel_iommu *iommu);665void iommu_flush_write_buffer(struct intel_iommu *iommu);
665int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev);666int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev);
667struct dmar_domain *find_domain(struct device *dev);
666 668
667#ifdef CONFIG_INTEL_IOMMU_SVM669#ifdef CONFIG_INTEL_IOMMU_SVM
668extern void intel_svm_check(struct intel_iommu *iommu);670extern void intel_svm_check(struct intel_iommu *iommu);