From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
To support limiting qos of device, the partid and pmg need to be set into the SMMU STE/CD context. This introduce support of SMMU mpam feature and add interface to set mpam configuration in STE/CD.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Signed-off-by: Rui Zhu zhurui3@huawei.com Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Zhen Lei thunder.leizhen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/iommu/arm-smmu-v3-context.c | 25 +++++ drivers/iommu/arm-smmu-v3.c | 151 ++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 9 ++ 3 files changed, 185 insertions(+) create mode 100644 include/linux/ascend_smmu.h
diff --git a/drivers/iommu/arm-smmu-v3-context.c b/drivers/iommu/arm-smmu-v3-context.c index 2351de86d31f1..b30a93e076608 100644 --- a/drivers/iommu/arm-smmu-v3-context.c +++ b/drivers/iommu/arm-smmu-v3-context.c @@ -66,6 +66,9 @@
#define CTXDESC_CD_1_TTB0_MASK GENMASK_ULL(51, 4)
+#define CTXDESC_CD_5_PARTID_MASK GENMASK_ULL(47, 32) +#define CTXDESC_CD_5_PMG_MASK GENMASK_ULL(55, 48) + /* Convert between AArch64 (CPU) TCR format and SMMU CD format */ #define ARM_SMMU_TCR2CD(tcr, fld) FIELD_PREP(CTXDESC_CD_0_TCR_##fld, \ FIELD_GET(ARM64_TCR_##fld, tcr)) @@ -563,6 +566,28 @@ static int arm_smmu_set_cd(struct iommu_pasid_table_ops *ops, int pasid, return arm_smmu_write_ctx_desc(tbl, pasid, cd); }
+int arm_smmu_set_cd_mpam(struct iommu_pasid_table_ops *ops, + int ssid, int partid, int pmg) +{ + struct arm_smmu_cd_tables *tbl = pasid_ops_to_tables(ops); + u64 val; + __le64 *cdptr = arm_smmu_get_cd_ptr(tbl, ssid); + + if (!cdptr) + return -ENOMEM; + + val = le64_to_cpu(cdptr[5]); + val &= ~CTXDESC_CD_5_PARTID_MASK; + val |= FIELD_PREP(CTXDESC_CD_5_PARTID_MASK, partid); + val &= ~CTXDESC_CD_5_PMG_MASK; + val |= FIELD_PREP(CTXDESC_CD_5_PMG_MASK, pmg); + WRITE_ONCE(cdptr[5], cpu_to_le64(val)); + + iommu_pasid_flush(&tbl->pasid, ssid, true); + + return 0; +} + static void arm_smmu_clear_cd(struct iommu_pasid_table_ops *ops, int pasid, struct iommu_pasid_entry *entry) { diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 6731b47558f4d..c282fc129222f 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -88,6 +88,10 @@ #define IDR1_SSIDSIZE GENMASK(10, 6) #define IDR1_SIDSIZE GENMASK(5, 0)
+#define ARM_SMMU_IDR3 0xc +#define IDR3_MPAM (1 << 7) +#define ARM_SMMU_IDR3_CFG 0x140C + #define ARM_SMMU_IDR5 0x14 #define IDR5_STALL_MAX GENMASK(31, 16) #define IDR5_GRAN64K (1 << 6) @@ -186,6 +190,10 @@ #define ARM_SMMU_PRIQ_IRQ_CFG1 0xd8 #define ARM_SMMU_PRIQ_IRQ_CFG2 0xdc
+#define ARM_SMMU_MPAMIDR 0x130 +#define MPAMIDR_PMG_MAX GENMASK(23, 16) +#define MPAMIDR_PARTID_MAX GENMASK(15, 0) + /* Common MSI config fields */ #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2) #define MSI_CFG2_SH GENMASK(5, 4) @@ -250,6 +258,7 @@ #define STRTAB_STE_1_S1COR GENMASK_ULL(5, 4) #define STRTAB_STE_1_S1CSH GENMASK_ULL(7, 6)
+#define STRTAB_STE_1_S1MPAM (1UL << 26) #define STRTAB_STE_1_S1STALLD (1UL << 27)
#define STRTAB_STE_1_EATS GENMASK_ULL(29, 28) @@ -273,6 +282,11 @@
#define STRTAB_STE_3_S2TTB_MASK GENMASK_ULL(51, 4)
+#define STRTAB_STE_4_PARTID_MASK GENMASK_ULL(31, 16) + +#define STRTAB_STE_5_MPAM_NS (1UL << 8) +#define STRTAB_STE_5_PMG_MASK GENMASK_ULL(7, 0) + /* Command queue */ #define CMDQ_ENT_SZ_SHIFT 4 #define CMDQ_ENT_DWORDS ((1 << CMDQ_ENT_SZ_SHIFT) >> 3) @@ -634,6 +648,7 @@ struct arm_smmu_device { #define ARM_SMMU_FEAT_SVA (1 << 17) #define ARM_SMMU_FEAT_HA (1 << 18) #define ARM_SMMU_FEAT_HD (1 << 19) +#define ARM_SMMU_FEAT_MPAM (1 << 20) u32 features;
#define ARM_SMMU_OPT_SKIP_PREFETCH (1 << 0) @@ -672,6 +687,9 @@ struct arm_smmu_device { struct mutex streams_mutex;
struct iopf_queue *iopf_queue; + + unsigned int mpam_partid_max; + unsigned int mpam_pmg_max; };
struct arm_smmu_stream { @@ -3977,6 +3995,25 @@ static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu) if (smmu->sid_bits <= STRTAB_SPLIT) smmu->features &= ~ARM_SMMU_FEAT_2_LVL_STRTAB;
+ /* IDR3 */ + reg = readl_relaxed(smmu->base + ARM_SMMU_IDR3); + + if (!(reg & IDR3_MPAM)) { + reg |= FIELD_PREP(IDR3_MPAM, 1); + writel(reg, smmu->base + ARM_SMMU_IDR3_CFG); + reg = readl_relaxed(smmu->base + ARM_SMMU_IDR3); + if (!(reg & IDR3_MPAM)) + dev_warn(smmu->dev, "enable smmu mpam failed\n"); + } + + if (reg & IDR3_MPAM) { + reg = readl_relaxed(smmu->base + ARM_SMMU_MPAMIDR); + smmu->mpam_partid_max = FIELD_GET(MPAMIDR_PARTID_MAX, reg); + smmu->mpam_pmg_max = FIELD_GET(MPAMIDR_PMG_MAX, reg); + if (smmu->mpam_partid_max || smmu->mpam_pmg_max) + smmu->features |= ARM_SMMU_FEAT_MPAM; + } + /* IDR5 */ reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
@@ -4124,6 +4161,120 @@ static unsigned long arm_smmu_resource_size(struct arm_smmu_device *smmu) return SZ_128K; }
+static int arm_smmu_set_ste_mpam(struct arm_smmu_device *smmu, + int sid, int partid, int pmg, int s1mpam) +{ + u64 val; + __le64 *ste; + + if (!arm_smmu_sid_in_range(smmu, sid)) + return -ERANGE; + + /* get ste ptr */ + ste = arm_smmu_get_step_for_sid(smmu, sid); + + /* write s1mpam to ste */ + val = le64_to_cpu(ste[1]); + val &= ~STRTAB_STE_1_S1MPAM; + val |= FIELD_PREP(STRTAB_STE_1_S1MPAM, s1mpam); + WRITE_ONCE(ste[1], cpu_to_le64(val)); + + val = le64_to_cpu(ste[4]); + val &= ~STRTAB_STE_4_PARTID_MASK; + val |= FIELD_PREP(STRTAB_STE_4_PARTID_MASK, partid); + WRITE_ONCE(ste[4], cpu_to_le64(val)); + + val = le64_to_cpu(ste[5]); + val &= ~STRTAB_STE_5_PMG_MASK; + val |= FIELD_PREP(STRTAB_STE_5_PMG_MASK, pmg); + WRITE_ONCE(ste[5], cpu_to_le64(val)); + + arm_smmu_sync_ste_for_sid(smmu, sid); + + return 0; +} + +int arm_smmu_set_cd_mpam(struct iommu_pasid_table_ops *ops, + int ssid, int partid, int pmg); + +static int arm_smmu_set_mpam(struct arm_smmu_device *smmu, + int sid, int ssid, int partid, int pmg, int s1mpam) +{ + struct arm_smmu_master_data *master = arm_smmu_find_master(smmu, sid); + struct arm_smmu_s1_cfg *cfg = master ? master->ste.s1_cfg : NULL; + struct arm_smmu_domain *domain = master ? master->domain : NULL; + int ret; + + struct arm_smmu_cmdq_ent prefetch_cmd = { + .opcode = CMDQ_OP_PREFETCH_CFG, + .prefetch = { + .sid = sid, + }, + }; + + if (!(smmu->features & ARM_SMMU_FEAT_MPAM)) + return -ENODEV; + + if (WARN_ON(!domain)) + return -EINVAL; + + if (WARN_ON(!cfg)) + return -EINVAL; + + if (WARN_ON(ssid >= (1 << master->ssid_bits))) + return -E2BIG; + + if (partid > smmu->mpam_partid_max || pmg > smmu->mpam_pmg_max) { + dev_err(smmu->dev, + "mpam rmid out of range: partid[0, %d] pmg[0, %d]\n", + smmu->mpam_partid_max, smmu->mpam_pmg_max); + return -ERANGE; + } + + ret = arm_smmu_set_ste_mpam(smmu, sid, partid, pmg, s1mpam); + if (ret < 0) { + dev_err(smmu->dev, "set ste mpam configuration error %d\n", + ret); + return ret; + } + + /* do not modify cd table which owned by guest */ + if (domain->stage == ARM_SMMU_DOMAIN_NESTED) { + dev_err(smmu->dev, + "mpam: smmu cd is owned by guest, not modified\n"); + return 0; + } + + ret = arm_smmu_set_cd_mpam(cfg->ops, ssid, partid, pmg); + if (s1mpam && ret < 0) { + dev_err(smmu->dev, "set cd mpam configuration error %d\n", + ret); + return ret; + } + + /* It's likely that we'll want to use the new STE soon */ + if (!(smmu->options & ARM_SMMU_OPT_SKIP_PREFETCH)) + arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd); + + dev_info(smmu->dev, "partid %d, pmg %d\n", partid, pmg); + + return 0; +} + +/** + * arm_smmu_set_dev_mpam() - Set mpam configuration to SMMU STE/CD + */ +int arm_smmu_set_dev_mpam(struct device *dev, int ssid, int partid, int pmg, + int s1mpam) +{ + struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv; + struct arm_smmu_device *smmu = master->domain->smmu; + int sid = master->streams->id; + + return arm_smmu_set_mpam(smmu, sid, ssid, partid, pmg, s1mpam); +} +EXPORT_SYMBOL(arm_smmu_set_dev_mpam); + static int arm_smmu_device_probe(struct platform_device *pdev) { int irq, ret; diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h new file mode 100644 index 0000000000000..bd0edd25057e1 --- /dev/null +++ b/include/linux/ascend_smmu.h @@ -0,0 +1,9 @@ +#ifndef __LINUX_ASCEND_SMMU_H +#define __LINUX_ASCEND_SMMU_H + +#include <linux/device.h> + +extern int arm_smmu_set_dev_mpam(struct device *dev, int ssid, int partid, + int pmg, int s1mpam); + +#endif /* __LINUX_ASCEND_SMMU_H */
From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 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: Xingang Wang wangxingang5@huawei.com Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Zhen Lei thunder.leizhen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/iommu/arm-smmu-v3-context.c | 17 +++++++ drivers/iommu/arm-smmu-v3.c | 71 +++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 3 ++ 3 files changed, 91 insertions(+)
diff --git a/drivers/iommu/arm-smmu-v3-context.c b/drivers/iommu/arm-smmu-v3-context.c index b30a93e076608..d87d6f72e8642 100644 --- a/drivers/iommu/arm-smmu-v3-context.c +++ b/drivers/iommu/arm-smmu-v3-context.c @@ -588,6 +588,23 @@ int arm_smmu_set_cd_mpam(struct iommu_pasid_table_ops *ops, return 0; }
+int arm_smmu_get_cd_mpam(struct iommu_pasid_table_ops *ops, + int ssid, int *partid, int *pmg) +{ + struct arm_smmu_cd_tables *tbl = pasid_ops_to_tables(ops); + u64 val; + __le64 *cdptr = arm_smmu_get_cd_ptr(tbl, ssid); + + if (!cdptr) + return -ENOMEM; + + val = le64_to_cpu(cdptr[5]); + *partid = FIELD_GET(CTXDESC_CD_5_PARTID_MASK, val); + *pmg = FIELD_GET(CTXDESC_CD_5_PMG_MASK, val); + + return 0; +} + static void arm_smmu_clear_cd(struct iommu_pasid_table_ops *ops, int pasid, struct iommu_pasid_entry *entry) { diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index c282fc129222f..5e9f3e14a1ea9 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -4194,9 +4194,38 @@ static int arm_smmu_set_ste_mpam(struct arm_smmu_device *smmu, return 0; }
+static int arm_smmu_get_ste_mpam(struct arm_smmu_device *smmu, + int sid, int *partid, int *pmg, int *s1mpam) +{ + u64 val; + __le64 *ste; + + if (!arm_smmu_sid_in_range(smmu, sid)) + return -ERANGE; + + /* get ste ptr */ + ste = arm_smmu_get_step_for_sid(smmu, sid); + + val = le64_to_cpu(ste[1]); + *s1mpam = FIELD_GET(STRTAB_STE_1_S1MPAM, val); + if (*s1mpam) + return 0; + + 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); + + return 0; +} + int arm_smmu_set_cd_mpam(struct iommu_pasid_table_ops *ops, int ssid, int partid, int pmg);
+int arm_smmu_get_cd_mpam(struct iommu_pasid_table_ops *ops, + int ssid, int *partid, int *pmg); + static int arm_smmu_set_mpam(struct arm_smmu_device *smmu, int sid, int ssid, int partid, int pmg, int s1mpam) { @@ -4275,6 +4304,48 @@ int arm_smmu_set_dev_mpam(struct device *dev, int ssid, int partid, int pmg, } EXPORT_SYMBOL(arm_smmu_set_dev_mpam);
+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_data *master = arm_smmu_find_master(smmu, sid); + struct arm_smmu_s1_cfg *cfg = master ? master->ste.s1_cfg : NULL; + int ret; + + if (!(smmu->features & ARM_SMMU_FEAT_MPAM)) + return -ENODEV; + + ret = arm_smmu_get_ste_mpam(smmu, sid, partid, pmg, s1mpam); + if (ret) + return ret; + + /* return STE mpam configuration when s1mpam == 0 */ + if (!(*s1mpam)) + return 0; + + if (WARN_ON(!cfg)) + return -EINVAL; + + if (WARN_ON(ssid >= (1 << master->ssid_bits))) + return -E2BIG; + + return arm_smmu_get_cd_mpam(cfg->ops, ssid, partid, pmg); +} + +/** + * arm_smmu_get_dev_mpam() - get mpam configuration + * @dev: the device + */ +int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, int *pmg, + int *s1mpam) +{ + struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv; + struct arm_smmu_device *smmu = master->domain->smmu; + int sid = master->streams->id; + + return arm_smmu_get_mpam(smmu, sid, ssid, partid, pmg, s1mpam); +} +EXPORT_SYMBOL(arm_smmu_get_dev_mpam); + static int arm_smmu_device_probe(struct platform_device *pdev) { int irq, ret; diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index bd0edd25057e1..a9f449a135781 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -6,4 +6,7 @@ extern int arm_smmu_set_dev_mpam(struct device *dev, int ssid, int partid, int pmg, int s1mpam);
+extern int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, + int *pmg, int *s1mpam); + #endif /* __LINUX_ASCEND_SMMU_H */
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 whether SMMU mpam configuration will be used. If user_mpam_en is 1, the memory requests across SMMU will not carry the SMMU mpam configuration.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Zhen Lei thunder.leizhen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/iommu/arm-smmu-v3.c | 37 +++++++++++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 3 +++ 2 files changed, 40 insertions(+)
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 5e9f3e14a1ea9..f3d26e4d8d2c4 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -194,6 +194,9 @@ #define MPAMIDR_PMG_MAX GENMASK(23, 16) #define MPAMIDR_PARTID_MAX GENMASK(15, 0)
+#define ARM_SMMU_USER_CFG0 0xe00 +#define ARM_SMMU_USER_MPAM_EN (1UL << 30) + /* Common MSI config fields */ #define MSI_CFG0_ADDR_MASK GENMASK_ULL(51, 2) #define MSI_CFG2_SH GENMASK(5, 4) @@ -4346,6 +4349,40 @@ int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, int *pmg, } EXPORT_SYMBOL(arm_smmu_get_dev_mpam);
+/** + * arm_smmu_set_dev_user_mpam_en() - set user_mpam_en to smmu user cfg0 + */ +int arm_smmu_set_dev_user_mpam_en(struct device *dev, int user_mpam_en) +{ + struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv; + struct arm_smmu_device *smmu = master->domain->smmu; + u32 reg, __iomem *cfg = smmu->base + ARM_SMMU_USER_CFG0; + + reg = readl_relaxed(cfg); + reg &= ~ARM_SMMU_USER_MPAM_EN; + reg |= FIELD_PREP(ARM_SMMU_USER_MPAM_EN, user_mpam_en); + writel_relaxed(reg, cfg); + + return 0; +} +EXPORT_SYMBOL(arm_smmu_set_dev_user_mpam_en); + +/** + * arm_smmu_get_dev_user_mpam_en() - get user_mpam_en from smmu user cfg0 + */ +int arm_smmu_get_dev_user_mpam_en(struct device *dev, int *user_mpam_en) +{ + struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv; + struct arm_smmu_device *smmu = master->domain->smmu; + u32 reg, __iomem *cfg = smmu->base + ARM_SMMU_USER_CFG0; + + reg = readl_relaxed(cfg); + *user_mpam_en = FIELD_GET(ARM_SMMU_USER_MPAM_EN, reg); + + return 0; +} +EXPORT_SYMBOL(arm_smmu_get_dev_user_mpam_en); + static int arm_smmu_device_probe(struct platform_device *pdev) { int irq, ret; diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index a9f449a135781..c52968e98944c 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -9,4 +9,7 @@ extern int arm_smmu_set_dev_mpam(struct device *dev, int ssid, int partid, extern int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, int *pmg, int *s1mpam);
+extern int arm_smmu_set_dev_user_mpam_en(struct device *dev, int user_mpam_en); +extern int arm_smmu_get_dev_user_mpam_en(struct device *dev, int *user_mpam_en); + #endif /* __LINUX_ASCEND_SMMU_H */
From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
This add interface to get mpam configuration of accelarators managed by svm. The svm mpam get interface traverse all accelrators, and if all succeed, return the last successful result.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/char/svm.c | 85 +++++++++++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 2 + 2 files changed, 87 insertions(+)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index 71aecf22c7007..7134823500a22 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -32,6 +32,7 @@ #include <linux/sched/mm.h> #include <linux/msi.h> #include <linux/acpi.h> +#include <linux/ascend_smmu.h>
#define SVM_DEVICE_NAME "svm" #define ASID_SHIFT 48 @@ -72,8 +73,11 @@ struct svm_device { struct device *dev; phys_addr_t l2buff; unsigned long l2size; + struct list_head entry; };
+static LIST_HEAD(sdev_list); + struct svm_bind_process { pid_t vpid; u64 ttbr; @@ -124,6 +128,15 @@ struct meminfo { unsigned long hugetlbtotal; };
+struct svm_mpam { +#define SVM_GET_DEV_MPAM (1 << 0) + int flags; + int pasid; + int partid; + int pmg; + int s1mpam; +}; + static struct bus_type svm_bus_type = { .name = "svm_bus", }; @@ -1183,6 +1196,76 @@ int svm_get_pasid(pid_t vpid, int dev_id __maybe_unused) } EXPORT_SYMBOL_GPL(svm_get_pasid);
+static int svm_get_core_mpam(struct device *dev, void *data) +{ + int err = 0; + struct svm_mpam *mpam = data; + + if (mpam->flags & SVM_GET_DEV_MPAM) { + err = arm_smmu_get_dev_mpam(dev, mpam->pasid, &mpam->partid, + &mpam->pmg, &mpam->s1mpam); + if (err) { + dev_err(dev, "get mpam failed, %d\n", err); + return err; + } + } + + return err; +} + +int __svm_get_mpam(struct svm_mpam *mpam) +{ + int err = 0; +#ifdef CONFIG_ACPI + struct core_device *cdev = NULL; +#else + struct svm_device *sdev = NULL; +#endif +#ifdef CONFIG_ACPI + list_for_each_entry(cdev, &child_list, entry) { + err = svm_get_core_mpam(&cdev->dev, mpam); + if (err) + return err; + } +#else + list_for_each_entry(sdev, &sdev_list, entry) { + err = device_for_each_child(sdev->dev, mpam, svm_get_core_mpam); + if (err) + return err; + } +#endif + return 0; +} + +/** + * svm_get_mpam() - get smmu mpam configuration of core device + * @pasid: substream id + * @partid: pointer to partid + * @pmg: pointer to pmg + * @s1mpam: pointer to s1mpam + */ +int svm_get_mpam(int pasid, int *partid, int *pmg, int *s1mpam) +{ + int err = 0; + struct svm_mpam mpam; + + if (!partid || !pmg || !s1mpam) + return -EINVAL; + + mpam.flags = SVM_GET_DEV_MPAM, + mpam.pasid = pasid, + err = __svm_get_mpam(&mpam); + if (err) + return err; + + *partid = mpam.partid; + *pmg = mpam.pmg; + *s1mpam = mpam.s1mpam; + + return 0; +} +EXPORT_SYMBOL_GPL(svm_get_mpam); + static int svm_set_rc(unsigned long __user *arg) { unsigned long addr, size, rc; @@ -1792,6 +1875,7 @@ static int svm_device_probe(struct platform_device *pdev) if (sdev->miscdev.name == NULL) return -ENOMEM;
+ list_add(&sdev->entry, &sdev_list); dev_set_drvdata(dev, sdev); err = misc_register(&sdev->miscdev); if (err) { @@ -1840,6 +1924,7 @@ static int svm_device_remove(struct platform_device *pdev)
device_for_each_child(sdev->dev, NULL, svm_remove_core); misc_deregister(&sdev->miscdev); + list_del(&sdev->entry);
return 0; } diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index c52968e98944c..a6d2058599be5 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -12,4 +12,6 @@ extern int arm_smmu_get_dev_mpam(struct device *dev, int ssid, int *partid, extern int arm_smmu_set_dev_user_mpam_en(struct device *dev, int user_mpam_en); 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); + #endif /* __LINUX_ASCEND_SMMU_H */
From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
This add svm_set_mpam interface in svm module, which traverse all accelerators, and set the mpam configuration in SMMU. If error occurs during the traverse process, mpam configuration of all accelerators will rollback to previous.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/char/svm.c | 79 +++++++++++++++++++++++++++++++++++++ include/linux/ascend_smmu.h | 1 + 2 files changed, 80 insertions(+)
diff --git a/drivers/char/svm.c b/drivers/char/svm.c index 7134823500a22..d60f1bb320362 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -130,6 +130,7 @@ struct meminfo {
struct svm_mpam { #define SVM_GET_DEV_MPAM (1 << 0) +#define SVM_SET_DEV_MPAM (1 << 1) int flags; int pasid; int partid; @@ -1237,6 +1238,84 @@ int __svm_get_mpam(struct svm_mpam *mpam) return 0; }
+static int svm_set_core_mpam(struct device *dev, void *data) +{ + int err = 0; + struct svm_mpam *mpam = data; + + if (mpam->flags & SVM_SET_DEV_MPAM) { + err = arm_smmu_set_dev_mpam(dev, mpam->pasid, mpam->partid, + mpam->pmg, mpam->s1mpam); + if (err) { + dev_err(dev, "set mpam failed, %d\n", err); + return err; + } + } + + return 0; +} + +static int __svm_set_mpam(struct svm_mpam *mpam) +{ + int err = 0; +#ifdef CONFIG_ACPI + struct core_device *cdev = NULL; +#else + struct svm_device *sdev = NULL; +#endif + +#ifdef CONFIG_ACPI + list_for_each_entry(cdev, &child_list, entry) { + err = svm_set_core_mpam(&cdev->dev, mpam); + if (err) + return err; + } +#else + list_for_each_entry(sdev, &sdev_list, entry) { + err = device_for_each_child(sdev->dev, mpam, svm_set_core_mpam); + if (err) + return err; + } +#endif + + return 0; +} + +/** + * svm_set_mpam() - set mpam configuration of all core device in smmu + * @pasid: substream id + * @partid: mpam partition id + * @pmg: mpam pmg + * @s1mpam: 0 for ste mpam, 1 for cd mpam + */ +int svm_set_mpam(int pasid, int partid, int pmg, int s1mpam) +{ + int err; + struct svm_mpam mpam, old_mpam; + + old_mpam.flags = SVM_GET_DEV_MPAM; + old_mpam.pasid = pasid; + err = __svm_get_mpam(&old_mpam); + if (err) + return err; + + mpam.flags = SVM_SET_DEV_MPAM; + mpam.pasid = pasid; + mpam.partid = partid; + mpam.pmg = pmg; + mpam.s1mpam = s1mpam; + err = __svm_set_mpam(&mpam); + if (err) + goto rollback; + + return 0; + +rollback: + __svm_set_mpam(&old_mpam); + return err; +} +EXPORT_SYMBOL_GPL(svm_set_mpam); + /** * svm_get_mpam() - get smmu mpam configuration of core device * @pasid: substream id diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index a6d2058599be5..e570acfc8f6ac 100644 --- a/include/linux/ascend_smmu.h +++ b/include/linux/ascend_smmu.h @@ -13,5 +13,6 @@ extern int arm_smmu_set_dev_user_mpam_en(struct device *dev, int user_mpam_en); 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);
#endif /* __LINUX_ASCEND_SMMU_H */
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 Reviewed-by: Yingtai Xie xieyingtai@huawei.com Reviewed-by: Ding Tianhong dingtianhong@huawei.com Signed-off-by: Yang Yingliang yangyingliang@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 d60f1bb320362..6ffeff4601c39 100644 --- a/drivers/char/svm.c +++ b/drivers/char/svm.c @@ -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; diff --git a/include/linux/ascend_smmu.h b/include/linux/ascend_smmu.h index e570acfc8f6ac..32241a02a8a89 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 */
From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
The rdt_mon_capable should be enabled when the msmon_mbwu feature is supported, so that the mpam monitor function can be effective.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Shaobo Wang bobo.shaobowang@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/arm64/kernel/mpam/mpam_setup.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/arch/arm64/kernel/mpam/mpam_setup.c b/arch/arm64/kernel/mpam/mpam_setup.c index 8fd76dc38d893..f32ece505c786 100644 --- a/arch/arm64/kernel/mpam/mpam_setup.c +++ b/arch/arm64/kernel/mpam/mpam_setup.c @@ -335,6 +335,7 @@ static void mpam_resctrl_pick_event_mbm_local(void)
if (mpam_has_feature(mpam_feat_msmon_mbwu, res->class->features)) { res->resctrl_res.mon_capable = true; + rdt_mon_capable = true; mpam_resctrl_events[QOS_L3_MBM_LOCAL_EVENT_ID] = *res; } }
From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
The mpam driver controls the allocation of rmid, however there are some ocassions that the partid and pmg of a group might come from elsewhere. This add support for group rmid modify. The sysfs rmid file is set to write accessible, and this add a write interface to accept rmid from user. When the rmid from user is different and valid, update the group with new rmid. When error occurs, rollback to old rmid.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Shaobo Wang bobo.shaobowang@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/arm64/kernel/mpam/mpam_resctrl.c | 128 ++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 8 deletions(-)
diff --git a/arch/arm64/kernel/mpam/mpam_resctrl.c b/arch/arm64/kernel/mpam/mpam_resctrl.c index a7fef0ac36f29..d23ccfb3a91a3 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -808,6 +808,11 @@ static void unset_rmid_remap_bmp_occ(unsigned long *bmp) set_bit(0, bmp); }
+static int is_rmid_remap_bmp_bdr_set(unsigned long *bmp, int b) +{ + return (test_bit(b + 1, bmp) == 0) ? 1 : 0; +} + static void rmid_remap_bmp_bdr_set(unsigned long *bmp, int b) { set_bit(b + 1, bmp); @@ -914,11 +919,11 @@ static int rmid_to_partid_pmg(int rmid, int *partid, int *pmg) return 0; }
-static int __rmid_alloc(int partid) +static int __rmid_alloc(int partid, int pmg) { int stride = 0; int partid_sel = 0; - int ret, pmg; + int ret; int rmid[2] = {-1, -1}; unsigned long **cmp, **bmp;
@@ -933,10 +938,19 @@ static int __rmid_alloc(int partid) continue; set_rmid_remap_bmp_occ(*bmp);
- ret = rmid_remap_bmp_alloc_pmg(*bmp); - if (ret < 0) - goto out; - pmg = ret; + if (pmg >= 0) { + if (is_rmid_remap_bmp_bdr_set(*bmp, pmg)) { + ret = -EEXIST; + goto out; + } + rmid_remap_bmp_bdr_clear(*bmp, pmg); + } else { + ret = rmid_remap_bmp_alloc_pmg(*bmp); + if (ret < 0) + goto out; + pmg = ret; + } + rmid[stride] = to_rmid(partid + stride, pmg); if (STRIDE_INC_CHK(stride)) break; @@ -976,7 +990,7 @@ static int __rmid_alloc(int partid)
int rmid_alloc(int partid) { - return __rmid_alloc(partid); + return __rmid_alloc(partid, -1); }
void rmid_free(int rmid) @@ -1851,6 +1865,103 @@ static int resctrl_group_rmid_show(struct kernfs_open_file *of, return ret; }
+static ssize_t resctrl_group_rmid_write(struct kernfs_open_file *of, + char *buf, size_t nbytes, loff_t off) +{ + struct rdtgroup *rdtgrp; + int ret = 0; + int partid; + int pmg; + int rmid; + int old_rmid; + int old_reqpartid; + struct task_struct *p, *t; + + if (kstrtoint(strstrip(buf), 0, &rmid) || rmid < 0) + return -EINVAL; + + rdtgrp = resctrl_group_kn_lock_live(of->kn); + if (!rdtgrp) { + ret = -ENOENT; + goto unlock; + } + + rdt_last_cmd_clear(); + + if (rmid == 0 || rdtgrp->mon.rmid == 0) { + ret = -EINVAL; + goto unlock; + } + + ret = rmid_to_partid_pmg(rmid, &partid, &pmg); + if (ret < 0) { + ret = -EINVAL; + goto unlock; + } + + if (rmid == rdtgrp->mon.rmid) + goto unlock; + + if (rdtgrp->type != RDTCTRL_GROUP || + !list_empty(&rdtgrp->mon.crdtgrp_list)) { + rdt_last_cmd_puts("unsupported operation\n"); + goto unlock; + } + + ret = __rmid_alloc(partid, pmg); + if (ret < 0) { + rdt_last_cmd_puts("set rmid failed\n"); + goto unlock; + } + + old_rmid = rdtgrp->mon.rmid; + old_reqpartid = rdtgrp->closid.reqpartid; + + /* + * we use intpartid as group control, use reqpartid for config + * synchronization and monitor, only update the reqpartid + */ + rdtgrp->closid.reqpartid = partid; + rdtgrp->mon.rmid = rmid; + + read_lock(&tasklist_lock); + for_each_process_thread(p, t) { + if (t->closid == rdtgrp->closid.intpartid) { + ret = __resctrl_group_move_task(t, rdtgrp); + if (ret) { + read_unlock(&tasklist_lock); + goto rollback; + } + } + } + read_unlock(&tasklist_lock); + + update_closid_rmid(&rdtgrp->cpu_mask, rdtgrp); + rmid_free(old_rmid); + +unlock: + resctrl_group_kn_unlock(of->kn); + if (ret) + return ret; + + return nbytes; + +rollback: + rdtgrp->mon.rmid = old_rmid; + rdtgrp->closid.reqpartid = old_reqpartid; + + read_lock(&tasklist_lock); + for_each_process_thread(p, t) { + if (t->closid == rdtgrp->closid.intpartid) + WARN_ON_ONCE(__resctrl_group_move_task(t, rdtgrp)); + } + read_unlock(&tasklist_lock); + + rmid_free(rmid); + resctrl_group_kn_unlock(of->kn); + return ret; +} + /* rdtgroup information files for one cache resource. */ static struct rftype res_specific_files[] = { { @@ -1950,8 +2061,9 @@ static struct rftype res_specific_files[] = { }, { .name = "rmid", - .mode = 0444, + .mode = 0644, .kf_ops = &resctrl_group_kf_single_ops, + .write = resctrl_group_rmid_write, .seq_show = resctrl_group_rmid_show, .fflags = RFTYPE_BASE, },
From: Xingang Wang wangxingang5@huawei.com
ascend inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I49RB2 CVE: NA
-------------------------------------------------
When group rmid changes, as introduced by 6bbf2791b ("mpam: Add support for group rmid modify") the sysfs monitor data file rmid needs to update as well. This add support for updating rmid for monitoring, and then resync the group configuration. When update failed, roll back to the previous rmid.
Signed-off-by: Xingang Wang wangxingang5@huawei.com Reviewed-by: Shaobo Wang bobo.shaobowang@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/arm64/include/asm/resctrl.h | 1 + arch/arm64/kernel/mpam/mpam_ctrlmon.c | 93 +++++++++++++++++++++++---- arch/arm64/kernel/mpam/mpam_resctrl.c | 21 ++++++ 3 files changed, 102 insertions(+), 13 deletions(-)
diff --git a/arch/arm64/include/asm/resctrl.h b/arch/arm64/include/asm/resctrl.h index a31df7fdc4778..ff4ce56430d1f 100644 --- a/arch/arm64/include/asm/resctrl.h +++ b/arch/arm64/include/asm/resctrl.h @@ -162,6 +162,7 @@ struct rdtgroup { atomic_t waitcount; enum rdt_group_type type; struct mongroup mon; + int resync; };
enum resctrl_ctrl_type { diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c index 9759eb223dac4..4b8429ceddb69 100644 --- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c +++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c @@ -189,6 +189,55 @@ resctrl_dom_ctrl_config(bool cdp_both_ctrl, struct resctrl_resource *r, } }
+/** + * Resync resctrl group domain ctrls, use rdtgrp->resync to indicate + * whether the resync procedure will be called. When resync==1, all + * domain ctrls of this group be synchronized again. This happens + * when rmid of this group is changed, and all configurations need to + * be remapped again accordingly. + */ +static void resctrl_group_resync_domain_ctrls(struct rdtgroup *rdtgrp, + struct resctrl_resource *r, struct rdt_domain *dom) +{ + int i; + int staged_start, staged_end; + struct resctrl_staged_config *cfg; + struct sd_closid closid; + struct list_head *head; + struct rdtgroup *entry; + struct msr_param para; + bool cdp_both_ctrl; + + cfg = dom->staged_cfg; + para.closid = &closid; + + staged_start = (r->cdp_enable) ? CDP_CODE : CDP_BOTH; + staged_end = (r->cdp_enable) ? CDP_DATA : CDP_BOTH; + + for (i = staged_start; i <= staged_end; i++) { + cdp_both_ctrl = cfg[i].cdp_both_ctrl; + /* + * for ctrl group configuration, hw_closid of cfg[i] equals + * to rdtgrp->closid.intpartid. + */ + closid.intpartid = hw_closid_val(cfg[i].hw_closid); + resctrl_cdp_mpamid_map_val(rdtgrp->closid.reqpartid, + cfg[i].conf_type, closid.reqpartid); + resctrl_dom_ctrl_config(cdp_both_ctrl, r, dom, ¶); + + /* + * we should synchronize all child mon groups' + * configuration from this ctrl rdtgrp + */ + head = &rdtgrp->mon.crdtgrp_list; + list_for_each_entry(entry, head, mon.crdtgrp_list) { + resctrl_cdp_mpamid_map_val(entry->closid.reqpartid, + cfg[i].conf_type, closid.reqpartid); + resctrl_dom_ctrl_config(cdp_both_ctrl, r, dom, ¶); + } + } +} + static void resctrl_group_update_domain_ctrls(struct rdtgroup *rdtgrp, struct resctrl_resource *r, struct rdt_domain *dom) { @@ -251,8 +300,12 @@ static int resctrl_group_update_domains(struct rdtgroup *rdtgrp, { struct rdt_domain *d;
- list_for_each_entry(d, &r->domains, list) - resctrl_group_update_domain_ctrls(rdtgrp, r, d); + list_for_each_entry(d, &r->domains, list) { + if (rdtgrp->resync) + resctrl_group_resync_domain_ctrls(rdtgrp, r, d); + else + resctrl_group_update_domain_ctrls(rdtgrp, r, d); + }
return 0; } @@ -667,20 +720,31 @@ static int resctrl_mkdir_mondata_dom(struct kernfs_node *parent_kn,
md.u.cdp_both_mon = s->cdp_mc_both;
+ if (!parent_kn) { + pr_err("%s: error parent_kn null\n", __func__); + return -EINVAL; + } + snprintf(name, sizeof(name), "mon_%s_%02d", s->name, d->id); - kn = __kernfs_create_file(parent_kn, name, 0444, - GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 0, - &kf_mondata_ops, md.priv, NULL, NULL); - if (IS_ERR(kn)) - return PTR_ERR(kn); - - ret = resctrl_group_kn_set_ugid(kn); - if (ret) { - pr_info("%s: create name %s, error ret %d\n", __func__, name, ret); - kernfs_remove(kn); - return ret; + kn = kernfs_find_and_get(parent_kn, name); + if (!kn) { + kn = __kernfs_create_file(parent_kn, name, 0444, + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 0, + &kf_mondata_ops, md.priv, NULL, NULL); + if (IS_ERR(kn)) + return PTR_ERR(kn); + + ret = resctrl_group_kn_set_ugid(kn); + if (ret) { + pr_info("%s: create name %s, error ret %d\n", + __func__, name, ret); + kernfs_remove(kn); + return ret; + } }
+ kn->priv = md.priv; + /* Could we remove the MATCH_* param ? */ rr->mon_write(d, md.priv);
@@ -958,5 +1022,8 @@ int resctrl_update_groups_config(struct rdtgroup *rdtgrp) } }
+ /* after resync all configurations, restore resync to 0 */ + rdtgrp->resync = 0; + return ret; } diff --git a/arch/arm64/kernel/mpam/mpam_resctrl.c b/arch/arm64/kernel/mpam/mpam_resctrl.c index d23ccfb3a91a3..79b711e2b7a5c 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -1924,6 +1924,21 @@ static ssize_t resctrl_group_rmid_write(struct kernfs_open_file *of, rdtgrp->closid.reqpartid = partid; rdtgrp->mon.rmid = rmid;
+ /* update rmid for mondata */ + ret = resctrl_mkdir_mondata_all_subdir(rdtgrp->mon.mon_data_kn, rdtgrp); + if (ret) { + rdt_last_cmd_puts("update rmid for mondata failed\n"); + goto rollback; + } + + /* resync groups configuration */ + rdtgrp->resync = 1; + ret = resctrl_update_groups_config(rdtgrp); + if (ret) { + rdt_last_cmd_puts("update groups config failed\n"); + goto rollback; + } + read_lock(&tasklist_lock); for_each_process_thread(p, t) { if (t->closid == rdtgrp->closid.intpartid) { @@ -1950,6 +1965,12 @@ static ssize_t resctrl_group_rmid_write(struct kernfs_open_file *of, rdtgrp->mon.rmid = old_rmid; rdtgrp->closid.reqpartid = old_reqpartid;
+ /* the old rmid is valid, so mkdir mondata here won't fail */ + resctrl_mkdir_mondata_all_subdir(rdtgrp->mon.mon_data_kn, rdtgrp); + + rdtgrp->resync = 1; + WARN_ON_ONCE(resctrl_update_groups_config(rdtgrp)); + read_lock(&tasklist_lock); for_each_process_thread(p, t) { if (t->closid == rdtgrp->closid.intpartid)