From 4bf3a2e1921fe7fe3e3a6b4928d5df8822eb03f6 Mon Sep 17 00:00:00 2001 From: Xie XiuQi Date: Tue, 29 Jan 2019 17:38:24 +0800 Subject: [PATCH 2819/2944] openEuler: arm64/mpam: support mondata fields commit b4617397605d3b8842d9e39bb8921223eccc2f92 openEuler-1.0 hulk inclusion category: feature bugzilla: 5510 CVE: NA Signed-off-by: Xie XiuQi Reviewed-by: Hanjun Guo Signed-off-by: Yang Yingliang Signed-off-by: Xin Hao Reviewed-by: Baolin Wang --- 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 4f09280..4bb583b 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 cb02aae..ffebafa 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 b7af781..78bc262 100644 --- a/arch/arm64/kernel/mpam_ctrlmon.c +++ b/arch/arm64/kernel/mpam_ctrlmon.c @@ -28,6 +28,8 @@ #include #include +#include +#include #include /* @@ -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__. 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 742e08e..330862d 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); -- 1.8.3.1