diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 2a719ee0f7fa..0e7d37c382c3 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -562,6 +562,7 @@ config IOMMU_DEBUG_TRACKING config IOMMU_TESTS bool "Interactive IOMMU performance/functional tests" select IOMMU_API + select ARM64_PTDUMP_CORE help Enables a suite of IOMMU unit tests. The tests are runnable through debugfs. Unlike the IOMMU_DEBUG_TRACKING option, the diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c index 3714634a8d61..d747fe9dc06a 100644 --- a/drivers/iommu/iommu-debug.c +++ b/drivers/iommu/iommu-debug.c @@ -34,6 +34,10 @@ #include #include "iommu-debug.h" +#ifdef CONFIG_ARM64_PTDUMP_CORE +#include +#endif + #if defined(CONFIG_IOMMU_TESTS) static const char *iommu_debug_attr_to_string(enum iommu_attr attr) @@ -182,6 +186,9 @@ struct iommu_debug_device { unsigned int clk_count; /* Protects domain */ struct mutex state_lock; +#ifdef CONFIG_ARM64_PTDUMP_CORE + struct ptdump_info pt_info; +#endif }; static int iommu_debug_build_phoney_sg_table(struct device *dev, @@ -2112,6 +2119,44 @@ static const struct file_operations iommu_debug_trigger_fault_fops = { .write = iommu_debug_trigger_fault_write, }; +#ifdef CONFIG_ARM64_PTDUMP_CORE +static int ptdump_show(struct seq_file *s, void *v) +{ + struct iommu_debug_device *ddev = s->private; + struct ptdump_info *info = &(ddev->pt_info); + struct mm_struct mm; + phys_addr_t phys; + + info->markers = (struct addr_marker[]){ + { 0, "start" }, + { -1, NULL}, + }; + info->base_addr = 0; + info->mm = &mm; + + if (ddev->domain) { + iommu_domain_get_attr(ddev->domain, DOMAIN_ATTR_PT_BASE_ADDR, + &(phys)); + + info->mm->pgd = (pgd_t *)phys_to_virt(phys); + ptdump_walk_pgd(s, info); + } + return 0; +} + +static int ptdump_open(struct inode *inode, struct file *file) +{ + return single_open(file, ptdump_show, inode->i_private); +} + +static const struct file_operations ptdump_fops = { + .open = ptdump_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; +#endif + /* * The following will only work for drivers that implement the generic * device tree bindings described in @@ -2283,6 +2328,15 @@ static int iommu_debug_device_setup(struct device *dev) goto err_rmdir; } +#ifdef CONFIG_ARM64_PTDUMP_CORE + if (!debugfs_create_file("iommu_page_tables", 0200, dir, ddev, + &ptdump_fops)) { + pr_err_ratelimited("Couldn't create iommu/devices/%s/iommu_page_tables debugfs file\n", + dev_name(dev)); + goto err_rmdir; + } +#endif + list_add(&ddev->list, &iommu_debug_devices); return 0;