Commit 69e61ede authored by Joerg Roedel's avatar Joerg Roedel
Browse files
iommu: Define EINVAL as device/domain incompatibility

This series is to replace the previous EMEDIUMTYPE patch in a VFIO series:
https://lore.kernel.org/kvm/Yxnt9uQTmbqul5lf@8bytes.org/

The purpose is to regulate all existing ->attach_dev callback functions to
use EINVAL exclusively for an incompatibility error between a device and a
domain. This allows VFIO and IOMMUFD to detect such a soft error, and then
try a different domain with the same device.

Among all the patches, the first two are preparatory changes. And then one
patch to update kdocs and another three patches for the enforcement
effort.

Link: https://lore.kernel.org/r/cover.1666042872.git.nicolinc@nvidia.com
parents 757636ed 04cee82e
Loading
Loading
Loading
Loading
+2 −10
Original line number Original line Diff line number Diff line
@@ -2155,21 +2155,13 @@ static void amd_iommu_detach_device(struct iommu_domain *dom,
static int amd_iommu_attach_device(struct iommu_domain *dom,
static int amd_iommu_attach_device(struct iommu_domain *dom,
				   struct device *dev)
				   struct device *dev)
{
{
	struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
	struct protection_domain *domain = to_pdomain(dom);
	struct protection_domain *domain = to_pdomain(dom);
	struct iommu_dev_data *dev_data;
	struct amd_iommu *iommu = rlookup_amd_iommu(dev);
	struct amd_iommu *iommu;
	int ret;
	int ret;


	if (!check_device(dev))
		return -EINVAL;

	dev_data = dev_iommu_priv_get(dev);
	dev_data->defer_attach = false;
	dev_data->defer_attach = false;


	iommu = rlookup_amd_iommu(dev);
	if (!iommu)
		return -EINVAL;

	if (dev_data->domain)
	if (dev_data->domain)
		detach_device(dev);
		detach_device(dev);


+1 −10
Original line number Original line Diff line number Diff line
@@ -2433,23 +2433,14 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
			goto out_unlock;
			goto out_unlock;
		}
		}
	} else if (smmu_domain->smmu != smmu) {
	} else if (smmu_domain->smmu != smmu) {
		dev_err(dev,
		ret = -EINVAL;
			"cannot attach to SMMU %s (upstream of %s)\n",
			dev_name(smmu_domain->smmu->dev),
			dev_name(smmu->dev));
		ret = -ENXIO;
		goto out_unlock;
		goto out_unlock;
	} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
	} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
		   master->ssid_bits != smmu_domain->s1_cfg.s1cdmax) {
		   master->ssid_bits != smmu_domain->s1_cfg.s1cdmax) {
		dev_err(dev,
			"cannot attach to incompatible domain (%u SSID bits != %u)\n",
			smmu_domain->s1_cfg.s1cdmax, master->ssid_bits);
		ret = -EINVAL;
		ret = -EINVAL;
		goto out_unlock;
		goto out_unlock;
	} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
	} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
		   smmu_domain->stall_enabled != master->stall_enabled) {
		   smmu_domain->stall_enabled != master->stall_enabled) {
		dev_err(dev, "cannot attach to stall-%s domain\n",
			smmu_domain->stall_enabled ? "enabled" : "disabled");
		ret = -EINVAL;
		ret = -EINVAL;
		goto out_unlock;
		goto out_unlock;
	}
	}
+0 −3
Original line number Original line Diff line number Diff line
@@ -1150,9 +1150,6 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
	 * different SMMUs.
	 * different SMMUs.
	 */
	 */
	if (smmu_domain->smmu != smmu) {
	if (smmu_domain->smmu != smmu) {
		dev_err(dev,
			"cannot attach to SMMU %s whilst already attached to domain on SMMU %s\n",
			dev_name(smmu_domain->smmu->dev), dev_name(smmu->dev));
		ret = -EINVAL;
		ret = -EINVAL;
		goto rpm_put;
		goto rpm_put;
	}
	}
+1 −6
Original line number Original line Diff line number Diff line
@@ -381,13 +381,8 @@ static int qcom_iommu_attach_dev(struct iommu_domain *domain, struct device *dev
	 * Sanity check the domain. We don't support domains across
	 * Sanity check the domain. We don't support domains across
	 * different IOMMUs.
	 * different IOMMUs.
	 */
	 */
	if (qcom_domain->iommu != qcom_iommu) {
	if (qcom_domain->iommu != qcom_iommu)
		dev_err(dev, "cannot attach to IOMMU %s while already "
			"attached to domain on IOMMU %s\n",
			dev_name(qcom_domain->iommu->dev),
			dev_name(qcom_iommu->dev));
		return -EINVAL;
		return -EINVAL;
	}


	return 0;
	return 0;
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -211,7 +211,7 @@ int pamu_config_ppaace(int liodn, u32 omi, u32 stashid, int prot)
		ppaace->op_encode.index_ot.omi = omi;
		ppaace->op_encode.index_ot.omi = omi;
	} else if (~omi != 0) {
	} else if (~omi != 0) {
		pr_debug("bad operation mapping index: %d\n", omi);
		pr_debug("bad operation mapping index: %d\n", omi);
		return -EINVAL;
		return -ENODEV;
	}
	}


	/* configure stash id */
	/* configure stash id */
Loading