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 872de67b8ab95..25dbe037c4171 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -803,6 +803,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); @@ -909,11 +914,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;
@@ -928,10 +933,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; @@ -971,7 +985,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) @@ -1846,6 +1860,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[] = { { @@ -1945,8 +2056,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, },