Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a4a1a9e9 authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu: iommu-debug: Fix race conditions in iommu debug"

parents 1ff435a1 cd180699
Loading
Loading
Loading
Loading
+61 −9
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ struct iommu_debug_device {
	struct list_head list;
	struct mutex clk_lock;
	unsigned int clk_count;
	struct mutex debug_dev_lock;
};

static int iommu_debug_build_phoney_sg_table(struct device *dev,
@@ -435,8 +436,10 @@ static int iommu_debug_profiling_show(struct seq_file *s, void *ignored)
	int htw_disable = 1, atomic = 1;
	void *attr_values[] = { &htw_disable, &atomic };

	mutex_lock(&ddev->debug_dev_lock);
	iommu_debug_device_profiling(s, ddev->dev, attrs, attr_values,
				     ARRAY_SIZE(attrs), sizes);
	mutex_unlock(&ddev->debug_dev_lock);

	return 0;
}
@@ -466,9 +469,10 @@ static int iommu_debug_secure_profiling_show(struct seq_file *s, void *ignored)
	int one = 1, secure_vmid = VMID_CP_PIXEL;
	void *attr_values[] = { &one, &secure_vmid };

	mutex_lock(&ddev->debug_dev_lock);
	iommu_debug_device_profiling(s, ddev->dev, attrs, attr_values,
				     ARRAY_SIZE(attrs), sizes);

	mutex_unlock(&ddev->debug_dev_lock);
	return 0;
}

@@ -497,9 +501,10 @@ static int iommu_debug_profiling_fast_show(struct seq_file *s, void *ignored)
	int one = 1;
	void *attr_values[] = { &one, &one };

	mutex_lock(&ddev->debug_dev_lock);
	iommu_debug_device_profiling(s, ddev->dev, attrs, attr_values,
				     ARRAY_SIZE(attrs), sizes);

	mutex_unlock(&ddev->debug_dev_lock);
	return 0;
}

@@ -1315,6 +1320,7 @@ static ssize_t __iommu_debug_dma_attach_write(struct file *file,
	ssize_t retval = -EINVAL;
	int val;

	mutex_lock(&ddev->debug_dev_lock);
	if (kstrtoint_from_user(ubuf, count, 0, &val)) {
		pr_err("Invalid format. Expected a hex or decimal integer");
		retval = -EFAULT;
@@ -1363,11 +1369,13 @@ static ssize_t __iommu_debug_dma_attach_write(struct file *file,
		pr_err("Detached\n");
	}
	retval = count;
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;

out_release_mapping:
	arm_iommu_release_mapping(dma_mapping);
out:
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;
}

@@ -1382,6 +1390,7 @@ static ssize_t __iommu_debug_attach_write(struct file *file,
	ssize_t retval;
	int val;

	mutex_lock(&ddev->debug_dev_lock);
	if (kstrtoint_from_user(ubuf, count, 0, &val)) {
		pr_err("Invalid format. Expected a hex or decimal integer");
		retval = -EFAULT;
@@ -1421,6 +1430,7 @@ static ssize_t __iommu_debug_attach_write(struct file *file,

	retval = count;
out:
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;
}

@@ -1585,17 +1595,23 @@ static ssize_t iommu_debug_pte_read(struct file *file, char __user *ubuf,
		pr_err("kptr_restrict needs to be disabled.\n");
		return -EPERM;
	}

	mutex_lock(&ddev->debug_dev_lock);
	if (!dev->archdata.mapping) {
		pr_err("No mapping. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}
	if (!dev->archdata.mapping->domain) {
		pr_err("No domain. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}

	if (*offset)
	if (*offset) {
		mutex_unlock(&ddev->debug_dev_lock);
		return 0;
	}

	memset(buf, 0, sizeof(buf));

@@ -1615,7 +1631,7 @@ static ssize_t iommu_debug_pte_read(struct file *file, char __user *ubuf,
		*offset = 1;	/* non-zero means we're done */
		retval = buflen;
	}

	mutex_unlock(&ddev->debug_dev_lock);
	return retval;
}

@@ -1656,13 +1672,18 @@ static ssize_t iommu_debug_atos_read(struct file *file, char __user *ubuf,
		pr_err("kptr_restrict needs to be disabled.\n");
		return -EPERM;
	}

	mutex_lock(&ddev->debug_dev_lock);
	if (!ddev->domain) {
		pr_err("No domain. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}

	if (*offset)
	if (*offset) {
		mutex_unlock(&ddev->debug_dev_lock);
		return 0;
	}

	memset(buf, 0, 100);

@@ -1685,6 +1706,7 @@ static ssize_t iommu_debug_atos_read(struct file *file, char __user *ubuf,
		retval = buflen;
	}

	mutex_unlock(&ddev->debug_dev_lock);
	return retval;
}

@@ -1708,18 +1730,23 @@ static ssize_t iommu_debug_dma_atos_read(struct file *file, char __user *ubuf,
		pr_err("kptr_restrict needs to be disabled.\n");
		return -EPERM;
	}

	mutex_lock(&ddev->debug_dev_lock);
	if (!dev->archdata.mapping) {
		pr_err("No mapping. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}
	if (!dev->archdata.mapping->domain) {
		pr_err("No domain. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}

	if (*offset)
	if (*offset) {
		mutex_unlock(&ddev->debug_dev_lock);
		return 0;

	}
	memset(buf, 0, sizeof(buf));

	phys = iommu_iova_to_phys_hard(dev->archdata.mapping->domain,
@@ -1737,7 +1764,7 @@ static ssize_t iommu_debug_dma_atos_read(struct file *file, char __user *ubuf,
		*offset = 1;	/* non-zero means we're done */
		retval = buflen;
	}

	mutex_unlock(&ddev->debug_dev_lock);
	return retval;
}

@@ -1765,8 +1792,10 @@ static ssize_t iommu_debug_map_write(struct file *file, const char __user *ubuf,
		return -EINVAL;
	}

	mutex_lock(&ddev->debug_dev_lock);
	if (!ddev->domain) {
		pr_err("No domain. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}

@@ -1815,10 +1844,12 @@ static ssize_t iommu_debug_map_write(struct file *file, const char __user *ubuf,
	pr_err("Mapped %pa to %pa (len=0x%zx, prot=0x%x)\n",
	       &iova, &phys, size, prot);
out:
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;

invalid_format:
	pr_err("Invalid format. Expected: iova,phys,len,prot where `prot' is the bitwise OR of IOMMU_READ, IOMMU_WRITE, etc.\n");
	mutex_unlock(&ddev->debug_dev_lock);
	return -EINVAL;
}

@@ -1856,6 +1887,7 @@ static ssize_t iommu_debug_dma_map_write(struct file *file,
		return -EINVAL;
	}

	mutex_lock(&ddev->debug_dev_lock);
	if (!dev->archdata.mapping) {
		pr_err("No mapping. Did you already attach?\n");
		retval = -EINVAL;
@@ -1924,14 +1956,17 @@ static ssize_t iommu_debug_dma_map_write(struct file *file,
	ddev->iova = iova;
		pr_err("Saved iova=%pa for future PTE commands\n", &iova);
out:
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;

invalid_format:
	pr_err("Invalid format. Expected: addr,len,dma attr where 'dma attr' is\n0: normal mapping\n1: force coherent\n2: force non-cohernet\n3: use system cache\n");
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;

invalid_addr:
	pr_err("Invalid addr given! Address should be within 1MB size from start addr returned by doing 'cat test_virt_addr'.\n");
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;
}

@@ -1997,8 +2032,10 @@ static ssize_t iommu_debug_unmap_write(struct file *file,
		return -EINVAL;
	}

	mutex_lock(&ddev->debug_dev_lock);
	if (!ddev->domain) {
		pr_err("No domain. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}

@@ -2027,16 +2064,19 @@ static ssize_t iommu_debug_unmap_write(struct file *file,
	if (unmapped != size) {
		pr_err("iommu_unmap failed. Expected to unmap: 0x%zx, unmapped: 0x%zx",
		       size, unmapped);
		mutex_unlock(&ddev->debug_dev_lock);
		return -EIO;
	}

	retval = count;
	pr_err("Unmapped %pa (len=0x%zx)\n", &iova, size);
out:
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;

invalid_format:
	pr_err("Invalid format. Expected: iova,len\n");
	mutex_unlock(&ddev->debug_dev_lock);
	return -EINVAL;
}

@@ -2064,6 +2104,7 @@ static ssize_t iommu_debug_dma_unmap_write(struct file *file,
		return -EINVAL;
	}

	mutex_lock(&ddev->debug_dev_lock);
	if (!dev->archdata.mapping) {
		pr_err("No mapping. Did you already attach?\n");
		retval = -EINVAL;
@@ -2118,10 +2159,12 @@ static ssize_t iommu_debug_dma_unmap_write(struct file *file,
	retval = count;
	pr_err("Unmapped %pa (len=0x%zx)\n", &iova, size);
out:
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;

invalid_format:
	pr_err("Invalid format. Expected: iova,len, dma attr\n");
	mutex_unlock(&ddev->debug_dev_lock);
	return retval;
}

@@ -2144,13 +2187,16 @@ static ssize_t iommu_debug_config_clocks_write(struct file *file,
		return -EINVAL;
	}

	mutex_lock(&ddev->debug_dev_lock);
	if (!ddev->domain) {
		dev_err(dev, "No domain. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}

	if (copy_from_user(&buf, ubuf, 1)) {
		dev_err(dev, "Couldn't copy from user\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EFAULT;
	}

@@ -2179,10 +2225,11 @@ static ssize_t iommu_debug_config_clocks_write(struct file *file,
	default:
		dev_err(dev, "Invalid value. Should be 0 or 1.\n");
		mutex_unlock(&ddev->clk_lock);
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}
	mutex_unlock(&ddev->clk_lock);

	mutex_unlock(&ddev->debug_dev_lock);
	return count;
}

@@ -2198,17 +2245,21 @@ static ssize_t iommu_debug_trigger_fault_write(
	struct iommu_debug_device *ddev = file->private_data;
	unsigned long flags;

	mutex_lock(&ddev->debug_dev_lock);
	if (!ddev->domain) {
		pr_err("No domain. Did you already attach?\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EINVAL;
	}

	if (kstrtoul_from_user(ubuf, count, 0, &flags)) {
		pr_err("Invalid flags format\n");
		mutex_unlock(&ddev->debug_dev_lock);
		return -EFAULT;
	}

	iommu_trigger_fault(ddev->domain, flags);
	mutex_unlock(&ddev->debug_dev_lock);

	return count;
}
@@ -2243,6 +2294,7 @@ static int snarf_iommu_devices(struct device *dev, void *ignored)
		return -ENODEV;

	mutex_init(&ddev->clk_lock);
	mutex_init(&ddev->debug_dev_lock);
	ddev->dev = dev;
	dir = debugfs_create_dir(dev_name(dev), debugfs_tests_dir);
	if (!dir) {