Commit 04039cc9 authored by Eric Auger's avatar Eric Auger Committed by Zheng Zengkai
Browse files

iommu/smmuv3: Implement cache_invalidate

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I401IF


CVE: NA

------------------------------

Implement domain-selective, pasid selective and page-selective
IOTLB invalidations.

Signed-off-by: default avatarEric Auger <eric.auger@redhat.com>
Signed-off-by: default avatarKunkun <Jiang&lt;jiangkunkun@huawei.com>
Reviewed-by: default avatarKeqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent eeb79c56
Loading
Loading
Loading
Loading
+89 −0
Original line number Original line Diff line number Diff line
@@ -3401,6 +3401,94 @@ static void arm_smmu_detach_pasid_table(struct iommu_domain *domain)
	mutex_unlock(&smmu_domain->init_mutex);
	mutex_unlock(&smmu_domain->init_mutex);
}
}


static int
arm_smmu_cache_invalidate(struct iommu_domain *domain, struct device *dev,
			  struct iommu_cache_invalidate_info *inv_info)
{
	struct arm_smmu_cmdq_ent cmd = {.opcode = CMDQ_OP_TLBI_NSNH_ALL};
	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
	struct arm_smmu_device *smmu = smmu_domain->smmu;

	if (smmu_domain->stage != ARM_SMMU_DOMAIN_NESTED)
		return -EINVAL;

	if (!smmu)
		return -EINVAL;

	if (inv_info->version != IOMMU_CACHE_INVALIDATE_INFO_VERSION_1)
		return -EINVAL;

	if (inv_info->cache & IOMMU_CACHE_INV_TYPE_PASID ||
	    inv_info->cache & IOMMU_CACHE_INV_TYPE_DEV_IOTLB) {
		return -ENOENT;
	}

	if (!(inv_info->cache & IOMMU_CACHE_INV_TYPE_IOTLB))
		return -EINVAL;

	/* IOTLB invalidation */

	switch (inv_info->granularity) {
	case IOMMU_INV_GRANU_PASID:
	{
		struct iommu_inv_pasid_info *info =
			&inv_info->granu.pasid_info;

		if (info->flags & IOMMU_INV_ADDR_FLAGS_PASID)
			return -ENOENT;
		if (!(info->flags & IOMMU_INV_PASID_FLAGS_ARCHID))
			return -EINVAL;

		__arm_smmu_tlb_inv_context(smmu_domain, info->archid);
		return 0;
	}
	case IOMMU_INV_GRANU_ADDR:
	{
		struct iommu_inv_addr_info *info = &inv_info->granu.addr_info;
		size_t granule_size  = info->granule_size;
		size_t size = info->nb_granules * info->granule_size;
		bool leaf = info->flags & IOMMU_INV_ADDR_FLAGS_LEAF;
		int tg;

		if (info->flags & IOMMU_INV_ADDR_FLAGS_PASID)
			return -ENOENT;

		if (!(info->flags & IOMMU_INV_ADDR_FLAGS_ARCHID))
			break;

		tg = __ffs(granule_size);
		if (granule_size & ~(1 << tg))
			return -EINVAL;
		/*
		 * When RIL is not supported, make sure the granule size that is
		 * passed is supported. In RIL mode, this is enforced in
		 * __arm_smmu_tlb_inv_range()
		 */
		if (!(smmu->features & ARM_SMMU_FEAT_RANGE_INV) &&
		    !(granule_size & smmu_domain->domain.pgsize_bitmap)) {
			tg = __ffs(smmu_domain->domain.pgsize_bitmap);
			granule_size = 1 << tg;
			size = size >> tg;
		}

		arm_smmu_tlb_inv_range_domain(info->addr, size,
					      granule_size, leaf,
					      info->archid, smmu_domain);
		return 0;
	}
	case IOMMU_INV_GRANU_DOMAIN:
		break;
	default:
		return -EINVAL;
	}

	/* Global S1 invalidation */
	cmd.tlbi.vmid   = smmu_domain->s2_cfg.vmid;
	arm_smmu_cmdq_issue_cmd(smmu, &cmd);
	arm_smmu_cmdq_issue_sync(smmu);
	return 0;
}

static bool arm_smmu_dev_has_feature(struct device *dev,
static bool arm_smmu_dev_has_feature(struct device *dev,
				     enum iommu_dev_features feat)
				     enum iommu_dev_features feat)
{
{
@@ -3626,6 +3714,7 @@ static struct iommu_ops arm_smmu_ops = {
	.put_resv_regions	= generic_iommu_put_resv_regions,
	.put_resv_regions	= generic_iommu_put_resv_regions,
	.attach_pasid_table	= arm_smmu_attach_pasid_table,
	.attach_pasid_table	= arm_smmu_attach_pasid_table,
	.detach_pasid_table	= arm_smmu_detach_pasid_table,
	.detach_pasid_table	= arm_smmu_detach_pasid_table,
	.cache_invalidate	= arm_smmu_cache_invalidate,
	.dev_has_feat		= arm_smmu_dev_has_feature,
	.dev_has_feat		= arm_smmu_dev_has_feature,
	.dev_feat_enabled	= arm_smmu_dev_feature_enabled,
	.dev_feat_enabled	= arm_smmu_dev_feature_enabled,
	.dev_enable_feat	= arm_smmu_dev_enable_feature,
	.dev_enable_feat	= arm_smmu_dev_enable_feature,