diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c index edfc9aeac730..1ecbedd37e0c 100644 --- a/drivers/iommu/iommu-debug.c +++ b/drivers/iommu/iommu-debug.c @@ -21,10 +21,57 @@ #include #include #include +#include #include #include #include +static const char *iommu_debug_attr_to_string(enum iommu_attr attr) +{ + switch (attr) { + case DOMAIN_ATTR_GEOMETRY: + return "DOMAIN_ATTR_GEOMETRY"; + case DOMAIN_ATTR_PAGING: + return "DOMAIN_ATTR_PAGING"; + case DOMAIN_ATTR_WINDOWS: + return "DOMAIN_ATTR_WINDOWS"; + case DOMAIN_ATTR_FSL_PAMU_STASH: + return "DOMAIN_ATTR_FSL_PAMU_STASH"; + case DOMAIN_ATTR_FSL_PAMU_ENABLE: + return "DOMAIN_ATTR_FSL_PAMU_ENABLE"; + case DOMAIN_ATTR_FSL_PAMUV1: + return "DOMAIN_ATTR_FSL_PAMUV1"; + case DOMAIN_ATTR_NESTING: + return "DOMAIN_ATTR_NESTING"; + case DOMAIN_ATTR_COHERENT_HTW_DISABLE: + return "DOMAIN_ATTR_COHERENT_HTW_DISABLE"; + case DOMAIN_ATTR_PT_BASE_ADDR: + return "DOMAIN_ATTR_PT_BASE_ADDR"; + case DOMAIN_ATTR_SECURE_VMID: + return "DOMAIN_ATTR_SECURE_VMID"; + case DOMAIN_ATTR_ATOMIC: + return "DOMAIN_ATTR_ATOMIC"; + case DOMAIN_ATTR_CONTEXT_BANK: + return "DOMAIN_ATTR_CONTEXT_BANK"; + case DOMAIN_ATTR_TTBR0: + return "DOMAIN_ATTR_TTBR0"; + case DOMAIN_ATTR_CONTEXTIDR: + return "DOMAIN_ATTR_CONTEXTIDR"; + case DOMAIN_ATTR_PROCID: + return "DOMAIN_ATTR_PROCID"; + case DOMAIN_ATTR_DYNAMIC: + return "DOMAIN_ATTR_DYNAMIC"; + case DOMAIN_ATTR_NON_FATAL_FAULTS: + return "DOMAIN_ATTR_NON_FATAL_FAULTS"; + case DOMAIN_ATTR_S1_BYPASS: + return "DOMAIN_ATTR_S1_BYPASS"; + case DOMAIN_ATTR_FAST: + return "DOMAIN_ATTR_FAST"; + default: + return "Unknown attr!"; + } +} + #ifdef CONFIG_IOMMU_DEBUG_TRACKING static DEFINE_MUTEX(iommu_debug_attachments_lock); @@ -461,6 +508,10 @@ static const char * const _size_to_string(unsigned long size) switch (size) { case SZ_4K: return "4K"; + case SZ_8K: + return "8K"; + case SZ_16K: + return "16K"; case SZ_64K: return "64K"; case SZ_2M: @@ -493,16 +544,16 @@ DEFINE_SIMPLE_ATTRIBUTE(iommu_debug_nr_iters_ops, nr_iters_get, nr_iters_set, "%llu\n"); static void iommu_debug_device_profiling(struct seq_file *s, struct device *dev, - bool secure) + enum iommu_attr attrs[], + void *attr_values[], int nattrs, + const unsigned long sizes[]) { - unsigned long sizes[] = { SZ_4K, SZ_64K, SZ_2M, SZ_1M * 12, - SZ_1M * 20, 0 }; - unsigned long *sz; + int i; + const unsigned long *sz; struct iommu_domain *domain; struct bus_type *bus; unsigned long iova = 0x10000; phys_addr_t paddr = 0xa000; - int htw_disable = 1, atomic_domain = 1; bus = msm_iommu_get_bus(dev); if (!bus) @@ -514,26 +565,18 @@ static void iommu_debug_device_profiling(struct seq_file *s, struct device *dev, return; } - if (iommu_domain_set_attr(domain, DOMAIN_ATTR_COHERENT_HTW_DISABLE, - &htw_disable)) { - seq_puts(s, "Couldn't disable coherent htw\n"); - goto out_domain_free; + seq_puts(s, "Domain attributes: [ "); + for (i = 0; i < nattrs; ++i) { + /* not all attrs are ints, but this will get us by for now */ + seq_printf(s, "%s=%d%s", iommu_debug_attr_to_string(attrs[i]), + *((int *)attr_values[i]), + i < nattrs ? " " : ""); } - - if (iommu_domain_set_attr(domain, DOMAIN_ATTR_ATOMIC, - &atomic_domain)) { - seq_printf(s, "Couldn't set atomic_domain to %d\n", - atomic_domain); - goto out_domain_free; - } - - if (secure) { - int secure_vmid = VMID_CP_PIXEL; - - if (iommu_domain_set_attr(domain, DOMAIN_ATTR_SECURE_VMID, - &secure_vmid)) { - seq_printf(s, "Couldn't set secure vmid to %d\n", - secure_vmid); + seq_puts(s, "]\n"); + for (i = 0; i < nattrs; ++i) { + if (iommu_domain_set_attr(domain, attrs[i], attr_values[i])) { + seq_printf(s, "Couldn't set %d to the value at %p\n", + attrs[i], attr_values[i]); goto out_domain_free; } } @@ -663,8 +706,17 @@ out_domain_free: static int iommu_debug_profiling_show(struct seq_file *s, void *ignored) { struct iommu_debug_device *ddev = s->private; + const unsigned long sizes[] = { SZ_4K, SZ_64K, SZ_2M, SZ_1M * 12, + SZ_1M * 20, 0 }; + enum iommu_attr attrs[] = { + DOMAIN_ATTR_COHERENT_HTW_DISABLE, + DOMAIN_ATTR_ATOMIC, + }; + int htw_disable = 1, atomic = 1; + void *attr_values[] = { &htw_disable, &atomic }; - iommu_debug_device_profiling(s, ddev->dev, false); + iommu_debug_device_profiling(s, ddev->dev, attrs, attr_values, + ARRAY_SIZE(attrs), sizes); return 0; } @@ -684,8 +736,19 @@ static const struct file_operations iommu_debug_profiling_fops = { static int iommu_debug_secure_profiling_show(struct seq_file *s, void *ignored) { struct iommu_debug_device *ddev = s->private; + const unsigned long sizes[] = { SZ_4K, SZ_64K, SZ_2M, SZ_1M * 12, + SZ_1M * 20, 0 }; - iommu_debug_device_profiling(s, ddev->dev, true); + enum iommu_attr attrs[] = { + DOMAIN_ATTR_COHERENT_HTW_DISABLE, + DOMAIN_ATTR_ATOMIC, + DOMAIN_ATTR_SECURE_VMID, + }; + int one = 1, secure_vmid = VMID_CP_PIXEL; + void *attr_values[] = { &one, &one, &secure_vmid }; + + iommu_debug_device_profiling(s, ddev->dev, attrs, attr_values, + ARRAY_SIZE(attrs), sizes); return 0; } @@ -704,6 +767,38 @@ static const struct file_operations iommu_debug_secure_profiling_fops = { .release = single_release, }; +static int iommu_debug_profiling_fast_show(struct seq_file *s, void *ignored) +{ + struct iommu_debug_device *ddev = s->private; + size_t sizes[] = {SZ_4K, SZ_8K, SZ_16K, SZ_64K, 0}; + enum iommu_attr attrs[] = { + DOMAIN_ATTR_FAST, + DOMAIN_ATTR_COHERENT_HTW_DISABLE, + DOMAIN_ATTR_ATOMIC, + }; + int one = 1; + void *attr_values[] = { &one, &one, &one }; + + iommu_debug_device_profiling(s, ddev->dev, attrs, attr_values, + ARRAY_SIZE(attrs), sizes); + + return 0; +} + +static int iommu_debug_profiling_fast_open(struct inode *inode, + struct file *file) +{ + return single_open(file, iommu_debug_profiling_fast_show, + inode->i_private); +} + +static const struct file_operations iommu_debug_profiling_fast_fops = { + .open = iommu_debug_profiling_fast_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int iommu_debug_attach_do_attach(struct iommu_debug_device *ddev, int val, bool is_secure) { @@ -1096,6 +1191,13 @@ static int snarf_iommu_devices(struct device *dev, const char *name) goto err_rmdir; } + if (!debugfs_create_file("profiling_fast", S_IRUSR, dir, ddev, + &iommu_debug_profiling_fast_fops)) { + pr_err("Couldn't create iommu/devices/%s/profiling_fast debugfs file\n", + name); + goto err_rmdir; + } + if (!debugfs_create_file("attach", S_IRUSR, dir, ddev, &iommu_debug_attach_fops)) { pr_err("Couldn't create iommu/devices/%s/attach debugfs file\n",