From: Xingang Wang wangxingang5@huawei.com
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: Xingang Wang wangxingang5@huawei.com --- drivers/char/svm.c | 64 +++++++++++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 3 ++ 2 files changed, 67 insertions(+)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index 169177b17..f6ad1af2c 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -153,11 +153,14 @@ struct spalloc { 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 = { @@ -1485,6 +1488,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; }
@@ -1526,6 +1537,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; }
@@ -1619,6 +1638,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; diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index e570acfc8..32241a02a 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -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 */