From: Xie XiuQi <xiexiuqi(a)huawei.com>
commit b4617397605d3b8842d9e39bb8921223eccc2f92 openEuler-1.0
hulk inclusion
category: feature
bugzilla: 5510
CVE: NA
Signed-off-by: Xie XiuQi <xiexiuqi(a)huawei.com>
Reviewed-by: Hanjun Guo <guohanjun(a)huawei.com>
Signed-off-by: Yang Yingliang <yangyingliang(a)huawei.com>
Signed-off-by: Xin Hao <haoxing990(a)gmail.com>
---
arch/arm64/include/asm/mpam.h | 1 +
arch/arm64/include/asm/resctrl.h | 8 +
arch/arm64/kernel/mpam_ctrlmon.c | 277 +++++++++++++++++++++++++++++++
fs/resctrlfs.c | 1 +
4 files changed, 287 insertions(+)
diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h
index 4f092802982f..4bb583b6a053 100644
--- a/arch/arm64/include/asm/mpam.h
+++ b/arch/arm64/include/asm/mpam.h
@@ -140,6 +140,7 @@ struct mongroup {
* @kn: kernfs node
* @resctrl_group_list: linked list for all rdtgroups
* @closid: closid for this rdtgroup
+ * #endif
* @cpu_mask: CPUs assigned to this rdtgroup
* @flags: status bits
* @waitcount: how many cpus expect to find this
diff --git a/arch/arm64/include/asm/resctrl.h b/arch/arm64/include/asm/resctrl.h
index cb02aae8497f..ffebafa85839 100644
--- a/arch/arm64/include/asm/resctrl.h
+++ b/arch/arm64/include/asm/resctrl.h
@@ -55,4 +55,12 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of,
r < resctrl_resources_all + MPAM_NUM_RESOURCES; \
r++) \
+int mkdir_mondata_all(struct kernfs_node *parent_kn,
+ struct resctrl_group *prgrp,
+ struct kernfs_node **dest_kn);
+
+int
+mongroup_create_dir(struct kernfs_node *parent_kn, struct resctrl_group *prgrp,
+ char *name, struct kernfs_node **dest_kn);
+
#endif /* _ASM_ARM64_RESCTRL_H */
diff --git a/arch/arm64/kernel/mpam_ctrlmon.c b/arch/arm64/kernel/mpam_ctrlmon.c
index b7af781cdf3d..78bc26272340 100644
--- a/arch/arm64/kernel/mpam_ctrlmon.c
+++ b/arch/arm64/kernel/mpam_ctrlmon.c
@@ -28,6 +28,8 @@
#include <linux/slab.h>
#include <linux/resctrlfs.h>
+#include <asm/mpam.h>
+#include <asm/mpam_resource.h>
#include <asm/resctrl.h>
/*
@@ -248,3 +250,278 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of,
resctrl_group_kn_unlock(of->kn);
return ret;
}
+
+/*
+ * [FIXME]
+ * use pmg as monitor id
+ * just use match_pardid only.
+ */
+static u64 mbwu_read(struct rdt_domain *d, struct rdtgroup *g)
+{
+ u32 pmg = g->mon.rmid;
+
+ mpam_writel(pmg, d->base + MSMON_CFG_MON_SEL);
+ return mpam_readl(d->base + MSMON_MBWU);
+}
+
+static u64 csu_read(struct rdt_domain *d, struct rdtgroup *g)
+{
+ u32 pmg = g->mon.rmid;
+
+ mpam_writel(pmg, d->base + MSMON_CFG_MON_SEL);
+ return mpam_readl(d->base + MSMON_CSU);
+}
+
+int resctrl_group_mondata_show(struct seq_file *m, void *arg)
+{
+ struct kernfs_open_file *of = m->private;
+ struct rdtgroup *rdtgrp;
+ struct rdt_domain *d;
+ int ret = 0;
+
+ rdtgrp = resctrl_group_kn_lock_live(of->kn);
+
+ d = of->kn->priv;
+
+ /* for debug */
+ seq_printf(m, "group: partid: %d, pmg: %d",
+ rdtgrp->closid, rdtgrp->mon.rmid);
+
+ /* show monitor data */
+
+ resctrl_group_kn_unlock(of->kn);
+ return ret;
+}
+
+static struct kernfs_ops kf_mondata_ops = {
+ .atomic_write_len = PAGE_SIZE,
+ .seq_show = resctrl_group_mondata_show,
+};
+
+/* set uid and gid of resctrl_group dirs and files to that of the creator */
+static int resctrl_group_kn_set_ugid(struct kernfs_node *kn)
+{
+ struct iattr iattr = { .ia_valid = ATTR_UID | ATTR_GID,
+ .ia_uid = current_fsuid(),
+ .ia_gid = current_fsgid(), };
+
+ if (uid_eq(iattr.ia_uid, GLOBAL_ROOT_UID) &&
+ gid_eq(iattr.ia_gid, GLOBAL_ROOT_GID))
+ return 0;
+
+ return kernfs_setattr(kn, &iattr);
+}
+
+#if 0 /* used at remove cpu*/
+/*
+ * Remove all subdirectories of mon_data of ctrl_mon groups
+ * and monitor groups with given domain id.
+ */
+void rmdir_mondata_subdir_allrdtgrp(struct resctrl_resource *r, unsigned int dom_id)
+{
+ struct resctrl_group *prgrp, *crgrp;
+ char name[32];
+
+ if (!r->mon_enabled)
+ return;
+
+ list_for_each_entry(prgrp, &resctrl_all_groups, resctrl_group_list) {
+ sprintf(name, "mon_%s_%02d", r->name, dom_id);
+ kernfs_remove_by_name(prgrp->mon.mon_data_kn, name);
+
+ list_for_each_entry(crgrp, &prgrp->mon.crdtgrp_list, mon.crdtgrp_list)
+ kernfs_remove_by_name(crgrp->mon.mon_data_kn, name);
+ }
+}
+#endif
+
+static int mkdir_mondata_subdir(struct kernfs_node *parent_kn,
+ struct rdt_domain *d,
+ struct resctrl_resource *r, struct resctrl_group *prgrp)
+{
+#if 1
+ struct kernfs_node *kn;
+ char name[32];
+ int ret;
+
+ sprintf(name, "mon_%s_%02d", r->name, d->id);
+
+ kn = __kernfs_create_file(parent_kn, name, 0444,
+ GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, 0,
+ &kf_mondata_ops, d, NULL, NULL);
+ if (IS_ERR(kn))
+ return PTR_ERR(kn);
+
+ ret = resctrl_group_kn_set_ugid(kn);
+ if (ret) {
+ kernfs_remove(kn);
+ return ret;
+ }
+
+ return ret;
+#if 0
+ /* create the directory */
+ kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp);
+ if (IS_ERR(kn))
+ return PTR_ERR(kn);
+
+ /*
+ * This extra ref will be put in kernfs_remove() and guarantees
+ * that kn is always accessible.
+ */
+ kernfs_get(kn);
+ ret = resctrl_group_kn_set_ugid(kn);
+ if (ret)
+ goto out_destroy;
+#endif
+
+
+#if 0
+ ret = mon_addfile(kn, mevt->name, d);
+ if (ret)
+ goto out_destroy;
+
+ kernfs_activate(kn);
+ return 0;
+
+out_destroy:
+ kernfs_remove(kn);
+ return ret;
+#endif
+#else
+ return 0;
+#endif
+}
+
+/*
+ * Add all subdirectories of mon_data for "ctrl_mon" groups
+ * and "monitor" groups with given domain id.
+ */
+void mkdir_mondata_subdir_allrdtgrp(struct resctrl_resource *r,
+ struct rdt_domain *d)
+{
+ struct kernfs_node *parent_kn;
+ struct resctrl_group *prgrp, *crgrp;
+ struct list_head *head;
+
+ if (!r->mon_enabled)
+ return;
+
+ list_for_each_entry(prgrp, &resctrl_all_groups, resctrl_group_list) {
+ parent_kn = prgrp->mon.mon_data_kn;
+ mkdir_mondata_subdir(parent_kn, d, r, prgrp);
+
+ head = &prgrp->mon.crdtgrp_list;
+ list_for_each_entry(crgrp, head, mon.crdtgrp_list) {
+ parent_kn = crgrp->mon.mon_data_kn;
+ mkdir_mondata_subdir(parent_kn, d, r, crgrp);
+ }
+ }
+}
+
+static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn,
+ struct resctrl_resource *r,
+ struct resctrl_group *prgrp)
+{
+ struct rdt_domain *dom;
+ int ret;
+
+ list_for_each_entry(dom, &r->domains, list) {
+ ret = mkdir_mondata_subdir(parent_kn, dom, r, prgrp);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int
+mongroup_create_dir(struct kernfs_node *parent_kn, struct resctrl_group *prgrp,
+ char *name, struct kernfs_node **dest_kn)
+{
+ struct kernfs_node *kn;
+ int ret;
+
+ /* create the directory */
+ kn = kernfs_create_dir(parent_kn, name, parent_kn->mode, prgrp);
+ if (IS_ERR(kn))
+ return PTR_ERR(kn);
+
+ if (dest_kn)
+ *dest_kn = kn;
+
+ /*
+ * This extra ref will be put in kernfs_remove() and guarantees
+ * that @rdtgrp->kn is always accessible.
+ */
+ kernfs_get(kn);
+
+ ret = resctrl_group_kn_set_ugid(kn);
+ if (ret)
+ goto out_destroy;
+
+ kernfs_activate(kn);
+
+ return 0;
+
+out_destroy:
+ kernfs_remove(kn);
+ return ret;
+}
+
+
+/*
+ * This creates a directory mon_data which contains the monitored data.
+ *
+ * mon_data has one directory for each domain whic are named
+ * in the format mon_<domain_name>_<domain_id>. For ex: A mon_data
+ * with L3 domain looks as below:
+ * ./mon_data:
+ * mon_L3_00
+ * mon_L3_01
+ * mon_L3_02
+ * ...
+ *
+ * Each domain directory has one file per event:
+ * ./mon_L3_00/:
+ * llc_occupancy
+ *
+ */
+int mkdir_mondata_all(struct kernfs_node *parent_kn,
+ struct resctrl_group *prgrp,
+ struct kernfs_node **dest_kn)
+{
+ struct resctrl_resource *r;
+ struct kernfs_node *kn;
+ int ret;
+
+ /*
+ * Create the mon_data directory first.
+ */
+ ret = mongroup_create_dir(parent_kn, NULL, "mon_data", &kn);
+ if (ret)
+ return ret;
+
+ if (dest_kn)
+ *dest_kn = kn;
+
+ /*
+ * Create the subdirectories for each domain. Note that all events
+ * in a domain like L3 are grouped into a resource whose domain is L3
+ */
+ for_each_resctrl_resource(r) {
+ if (r->mon_enabled) {
+ ret = mkdir_mondata_subdir_alldom(kn, r, prgrp);
+ if (ret)
+ goto out_destroy;
+ }
+ }
+
+ kernfs_activate(kn);
+
+ return 0;
+
+out_destroy:
+ kernfs_remove(kn);
+ return ret;
+}
diff --git a/fs/resctrlfs.c b/fs/resctrlfs.c
index 742e08eaa581..330862d40796 100644
--- a/fs/resctrlfs.c
+++ b/fs/resctrlfs.c
@@ -72,6 +72,7 @@ static int resctrl_group_add_file(struct kernfs_node *parent_kn, struct
rftype *
int ret;
kn = __kernfs_create_file(parent_kn, rft->name, rft->mode,
+ GLOBAL_ROOT_UID, GLOBAL_ROOT_GID,
0, rft->kf_ops, rft, NULL, NULL);
if (IS_ERR(kn))
return PTR_ERR(kn);
--
2.31.0