Commit c50ad40d authored by Xingang Wang's avatar Xingang Wang Committed by Yang Yingliang
Browse files

svm: Add svm_set_user_mpam_en to enable/disable mpam for smmu

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


CVE: NA

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

The user_mpam_en configuration is used to enable/disable
mpam for SMMU. If user_mpam_en is set as true, the memory
requests across SMMU will carry the mpamid information,
otherwise the mpamid will not take effect.

Signed-off-by: default avatarXingang Wang <wangxingang5@huawei.com>
Reviewed-by: default avatarYingtai Xie <xieyingtai@huawei.com>
Reviewed-by: default avatarDing Tianhong <dingtianhong@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parent 464f6990
Loading
Loading
Loading
Loading
+64 −0
Original line number Diff line number Diff line
@@ -131,11 +131,14 @@ struct meminfo {
struct svm_mpam {
#define SVM_GET_DEV_MPAM	(1 << 0)
#define SVM_SET_DEV_MPAM	(1 << 1)
#define SVM_GET_USER_MPAM_EN	(1 << 2)
#define SVM_SET_USER_MPAM_EN	(1 << 3)
	int flags;
	int pasid;
	int partid;
	int pmg;
	int s1mpam;
	int user_mpam_en;
};

static struct bus_type svm_bus_type = {
@@ -1211,6 +1214,14 @@ static int svm_get_core_mpam(struct device *dev, void *data)
		}
	}

	if (mpam->flags & SVM_GET_USER_MPAM_EN) {
		err = arm_smmu_get_dev_user_mpam_en(dev, &mpam->user_mpam_en);
		if (err) {
			dev_err(dev, "set user_mpam_en failed, %d\n", err);
			return err;
		}
	}

	return err;
}

@@ -1252,6 +1263,14 @@ static int svm_set_core_mpam(struct device *dev, void *data)
		}
	}

	if (mpam->flags & SVM_SET_USER_MPAM_EN) {
		err = arm_smmu_set_dev_user_mpam_en(dev, mpam->user_mpam_en);
		if (err) {
			dev_err(dev, "set user_mpam_en failed, %d\n", err);
			return err;
		}
	}

	return 0;
}

@@ -1345,6 +1364,51 @@ int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam)
}
EXPORT_SYMBOL_GPL(svm_get_mpam);

/**
 * svm_set_user_mpam_en() - set user_mpam_en
 * @user_mpam_en: 0 for smmu mpam, 1 for user mpam
 */
int svm_set_user_mpam_en(int user_mpam_en)
{
	int err;
	struct svm_mpam mpam, old_mpam;

	old_mpam.flags = SVM_GET_USER_MPAM_EN;
	err = __svm_get_mpam(&old_mpam);

	mpam.flags = SVM_SET_USER_MPAM_EN,
	mpam.user_mpam_en = user_mpam_en,
	err = __svm_set_mpam(&mpam);
	if (err)
		goto rollback;

	return 0;

rollback:
	__svm_set_mpam(&mpam);
	return err;
}
EXPORT_SYMBOL_GPL(svm_set_user_mpam_en);

/**
 * svm_set_user_mpam_en() - set user_mpam_en
 * @user_mpam_en: pointer to user_mpam_en
 */
int svm_get_user_mpam_en(int *user_mpam_en)
{
	int err;
	struct svm_mpam mpam;

	mpam.flags = SVM_GET_USER_MPAM_EN;
	err = __svm_get_mpam(&mpam);
	if (err)
		return err;

	*user_mpam_en = mpam.user_mpam_en;
	return 0;
}
EXPORT_SYMBOL_GPL(svm_get_user_mpam_en);

static int svm_set_rc(unsigned long __user *arg)
{
	unsigned long addr, size, rc;
+3 −0
Original line number Diff line number Diff line
@@ -15,4 +15,7 @@ extern int arm_smmu_get_dev_user_mpam_en(struct device *dev, int *user_mpam_en);
extern int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam);
extern int svm_set_mpam(int pasid, int partid, int pmg, int s1mpam);

extern int svm_set_user_mpam_en(int user_mpam_en);
extern int svm_get_user_mpam_en(int *user_mpam_en);

#endif /* __LINUX_ASCEND_SMMU_H */