Commit 156610f7 authored by Xingang Wang's avatar Xingang Wang Committed by Zheng Zengkai
Browse files

iommu/arm-smmu-v3: Add support to get SMMU mpam configuration

ascend inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I4L735


CVE: NA

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

Add interface to get mpam configuration of CD/STE context, use s1mpam
to indicate whether partid and pmg from CD or STE.

Signed-off-by: default avatarXingang Wang <wangxingang5@huawei.com>
Reviewed-by: default avatarZhen Lei <thunder.leizhen@huawei.com>
Reviewed-by: default avatarWeilong Chen <chenweilong@huawei.com>
Acked-by: default avatarXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent ae86d53e
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -4187,9 +4187,79 @@ static int arm_smmu_device_set_mpam(struct device *dev,

}

static int arm_smmu_get_mpam(struct arm_smmu_device *smmu,
		int sid, int ssid, int *partid, int *pmg, int *s1mpam)
{
	struct arm_smmu_master *master = arm_smmu_find_master(smmu, sid);
	struct arm_smmu_domain *domain = master ? master->domain : NULL;
	u64 val;
	__le64 *ste, *cd;

	if (WARN_ON(!domain))
		return -EINVAL;
	if (WARN_ON(!domain->s1_cfg.set))
		return -EINVAL;
	if (WARN_ON(ssid >= (1 << domain->s1_cfg.s1cdmax)))
		return -E2BIG;

	if (!(smmu->features & ARM_SMMU_FEAT_MPAM))
		return -ENODEV;

	/* get ste ptr */
	ste = arm_smmu_get_step_for_sid(smmu, sid);

	val = le64_to_cpu(ste[4]);
	*partid = FIELD_GET(STRTAB_STE_4_PARTID_MASK, val);

	val = le64_to_cpu(ste[5]);
	*pmg = FIELD_GET(STRTAB_STE_5_PMG_MASK, val);

	val = le64_to_cpu(ste[1]);
	*s1mpam = FIELD_GET(STRTAB_STE_1_S1MPAM, val);
	/* return STE mpam configuration when s1mpam == 0 */
	if (!(*s1mpam))
		return 0;

	/* get cd ptr */
	cd = arm_smmu_get_cd_ptr(domain, ssid);
	if (WARN_ON(!cd))
		return -ENOMEM;

	val = le64_to_cpu(cd[5]);
	*partid = FIELD_GET(CTXDESC_CD_5_PARTID_MASK, val);
	*pmg = FIELD_GET(CTXDESC_CD_5_PMG_MASK, val);

	return 0;
}

static int arm_smmu_device_get_mpam(struct device *dev,
				    struct arm_smmu_mpam *mpam)
{
	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
	int ret;

	if (WARN_ON(!master) || WARN_ON(!mpam))
		return -EINVAL;

	if (mpam->flags & ARM_SMMU_DEV_GET_MPAM) {
		ret = arm_smmu_get_mpam(master->domain->smmu,
					master->streams->id,
					mpam->pasid,
					&mpam->partid,
					&mpam->pmg,
					&mpam->s1mpam);
		if (ret < 0)
			return ret;
	}

	return 0;
}

static int arm_smmu_device_get_config(struct device *dev, int type, void *data)
{
	switch (type) {
	case ARM_SMMU_MPAM:
		return arm_smmu_device_get_mpam(dev, data);
	default:
		return -EINVAL;
	}
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ enum arm_smmu_device_config_type {

struct arm_smmu_mpam {
#define ARM_SMMU_DEV_SET_MPAM	(1 << 0)
#define ARM_SMMU_DEV_GET_MPAM	(1 << 1)
	int flags;
	int pasid;
	int partid;