From: Wang ShaoBo bobo.shaobowang@huawei.com
hulk inclusion category: feature bugzilla: 34278 CVE: NA
-------------------------------------------------
We redesign monitoring process for user, as following illustrates:
e.g. before rewriting: mount /sys/fs/resctrl && cd /sys/fs/resctrl mkdir p1 && cd p1 echo 1 > ctrlmon # this allocates a monitor resource for this group ... # associating task/cpu with this group grep . mon_data/* # get monitor data from mon_data directory e.g. after rewriting: mount /sys/fs/resctrl && cd /sys/fs/resctrl mkdir p1 && cd p1 # automically allocating a monitoring resource ... # associate task/cpu with this group grep . mon_data/* # directly get monitor data
ctrlmon is used for manually allocating a monitor resource for monitoring a specified group (labeled by partid and pmg), we delete ctrlmon because this action is redundant.
User should know which group has been allocated a available monitor resource and only this monitor resource is released then this monitor resource can be reallocated to a new group after, this action is redundant and unnecessary, as monitor resource is used only when monitoring process happens, so a relax monitor resource can be allocated to multiple groups and take effect when monitoring process happened.
But should some restrictions be known, a monitor resource for monitoring Cache-occupancy might be kept for a long time until it doesn't need to be use anymore, or below a threshold as like intel-RDT limbo list works, otherwise you may see that the monitoring result is very small beyond exception when you force switch one mon resource from one group to another.
We deliver a simple LRU mon resource allocation mechanism, but so far it just assign a monitor according to the order in which groups was created, this is incomplete and needs subsequent improvement.
Signed-off-by: Wang ShaoBo bobo.shaobowang@huawei.com Reviewed-by: Xiongfeng Wang wangxiongfeng2@huawei.com Reviewed-by: Cheng Jian cj.chengjian@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com Signed-off-by: Cheng Jian cj.chengjian@huawei.com --- arch/arm64/include/asm/mpam.h | 13 +- arch/arm64/include/asm/resctrl.h | 63 +------ arch/arm64/kernel/mpam/mpam_ctrlmon.c | 240 +------------------------- arch/arm64/kernel/mpam/mpam_mon.c | 75 ++++---- arch/arm64/kernel/mpam/mpam_resctrl.c | 79 ++++----- fs/resctrlfs.c | 198 ++++++++++++++++----- 6 files changed, 250 insertions(+), 418 deletions(-)
diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h index 52a334cce91a..ec2fc0f2eadb 100644 --- a/arch/arm64/include/asm/mpam.h +++ b/arch/arm64/include/asm/mpam.h @@ -167,7 +167,7 @@ do { \
bool is_resctrl_cdp_enabled(void);
-#define hw_alloc_times_validate(__name, __times, __flag) \ +#define hw_alloc_times_validate(__times, __flag) \ do { \ __flag = is_resctrl_cdp_enabled(); \ __times = flag ? 2 : 1; \ @@ -309,7 +309,7 @@ struct raw_resctrl_resource {
u16 num_mon; u64 (*mon_read)(struct rdt_domain *d, void *md_priv); - int (*mon_write)(struct rdt_domain *d, void *md_priv, bool enable); + int (*mon_write)(struct rdt_domain *d, void *md_priv); };
/* 64bit arm64 specified */ @@ -333,14 +333,11 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of, struct rdt_domain *mpam_find_domain(struct resctrl_resource *r, int id, struct list_head **pos);
-ssize_t resctrl_group_ctrlmon_write(struct kernfs_open_file *of, - char *buf, size_t nbytes, loff_t off); - -int resctrl_group_ctrlmon_show(struct kernfs_open_file *of, - struct seq_file *s, void *v); - int resctrl_group_alloc_mon(struct rdtgroup *grp);
u16 mpam_resctrl_max_mon_num(void);
+void pmg_init(void); +void mon_init(void); + #endif /* _ASM_ARM64_MPAM_H */ diff --git a/arch/arm64/include/asm/resctrl.h b/arch/arm64/include/asm/resctrl.h index 90b7683dd4dd..68e515ea8779 100644 --- a/arch/arm64/include/asm/resctrl.h +++ b/arch/arm64/include/asm/resctrl.h @@ -78,48 +78,14 @@ int schemata_list_init(void);
void schemata_list_destroy(void);
-int alloc_rmid(void); -void free_rmid(u32 rmid); +int resctrl_lru_request_mon(void);
-static inline int alloc_mon_id(void) -{ - - return alloc_rmid(); -} - -static inline void free_mon_id(u32 id) -{ - free_rmid(id); -} +int alloc_mon_id(void); +void free_mon_id(u32 id);
-int closid_init(void); -int closid_alloc(void); -void closid_free(int closid); -void pmg_init(void); - -static inline int resctrl_id_init(void) -{ - int ret; - - ret = closid_init(); - if (ret) - goto out; - - pmg_init(); - -out: - return ret; -} - -static inline int resctrl_id_alloc(void) -{ - return closid_alloc(); -} - -static inline void resctrl_id_free(int id) -{ - closid_free(id); -} +int resctrl_id_init(void); +int resctrl_id_alloc(void); +void resctrl_id_free(int id);
void update_cpu_closid_rmid(void *info); void update_closid_rmid(const struct cpumask *cpu_mask, struct resctrl_group *r); @@ -131,7 +97,6 @@ extern bool rdt_mon_capable;
/* rdtgroup.flags */ #define RDT_DELETED BIT(0) -#define RDT_CTRLMON BIT(1)
void rdt_last_cmd_clear(void); void rdt_last_cmd_puts(const char *s); @@ -142,9 +107,6 @@ extern struct mutex resctrl_group_mutex; void release_rdtgroupfs_options(void); int parse_rdtgroupfs_options(char *data);
-int alloc_mon(void); -void free_mon(u32 mon); - void resctrl_resource_reset(void);
#define release_resctrl_group_fs_options release_rdtgroupfs_options @@ -152,14 +114,6 @@ void resctrl_resource_reset(void);
int mpam_get_mon_config(struct resctrl_resource *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); - int resctrl_group_init_alloc(struct rdtgroup *rdtgrp);
static inline int __resctrl_group_show_options(struct seq_file *seq) @@ -167,9 +121,8 @@ static inline int __resctrl_group_show_options(struct seq_file *seq) return 0; }
-int resctrl_mkdir_ctrlmon_mondata(struct kernfs_node *parent_kn, - struct rdtgroup *prgrp, - struct kernfs_node **dest_kn); +int resctrl_mkdir_mondata_all_subdir(struct kernfs_node *parent_kn, + struct resctrl_group *prgrp);
struct resctrl_resource * mpam_resctrl_get_resource(enum resctrl_resource_level level); diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c index a94a1f2c5847..0c324008d9ab 100644 --- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c +++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c @@ -450,7 +450,7 @@ static int resctrl_group_kn_set_ugid(struct kernfs_node *kn) return kernfs_setattr(kn, &iattr); }
-static int mkdir_mondata_subdir(struct kernfs_node *parent_kn, +static int resctrl_mkdir_mondata_dom(struct kernfs_node *parent_kn, struct rdt_domain *d, struct resctrl_schema *s, struct resctrl_group *prgrp)
@@ -490,121 +490,12 @@ static int mkdir_mondata_subdir(struct kernfs_node *parent_kn, }
/* Could we remove the MATCH_* param ? */ - rr->mon_write(d, md.priv, true); + rr->mon_write(d, md.priv);
return ret; }
-int resctrl_ctrlmon_enable(struct kernfs_node *parent_kn, - struct resctrl_group *prgrp, - struct kernfs_node **dest_kn) -{ - int ret; - - /* only for RDTCTRL_GROUP */ - if (prgrp->type == RDTMON_GROUP) - return 0; - - ret = alloc_mon(); - if (ret < 0) { - rdt_last_cmd_puts("out of monitors\n"); - pr_info("out of monitors: ret %d\n", ret); - return ret; - } - prgrp->mon.mon = ret; - prgrp->mon.rmid = 0; - - ret = mkdir_mondata_all(parent_kn, prgrp, dest_kn); - if (ret) { - rdt_last_cmd_puts("kernfs subdir error\n"); - free_mon(ret); - } - - return ret; -} - -void resctrl_ctrlmon_disable(struct kernfs_node *kn_mondata, - struct resctrl_group *prgrp) -{ - struct mpam_resctrl_res *r; - struct resctrl_resource *resctrl_res; - struct raw_resctrl_resource *rr; - struct rdt_domain *dom; - int mon = prgrp->mon.mon; - - /* only for RDTCTRL_GROUP */ - if (prgrp->type == RDTMON_GROUP) - return; - - for_each_resctrl_exports(r) { - resctrl_res = &r->resctrl_res; - - if (resctrl_res->mon_enabled) { - rr = (struct raw_resctrl_resource *)resctrl_res->res; - - list_for_each_entry(dom, &resctrl_res->domains, list) { - rr->mon_write(dom, prgrp, false); - } - } - } - - free_mon(mon); - kernfs_remove(kn_mondata); -} - -ssize_t resctrl_group_ctrlmon_write(struct kernfs_open_file *of, - char *buf, size_t nbytes, loff_t off) -{ - struct rdtgroup *rdtgrp; - int ret = 0; - int ctrlmon; - - if (kstrtoint(strstrip(buf), 0, &ctrlmon) || ctrlmon < 0) - return -EINVAL; - rdtgrp = resctrl_group_kn_lock_live(of->kn); - rdt_last_cmd_clear(); - - if (!rdtgrp) { - ret = -ENOENT; - goto unlock; - } - - if ((rdtgrp->flags & RDT_CTRLMON) && !ctrlmon) { - /* disable & remove mon_data dir */ - rdtgrp->flags &= ~RDT_CTRLMON; - resctrl_ctrlmon_disable(rdtgrp->mon.mon_data_kn, rdtgrp); - } else if (!(rdtgrp->flags & RDT_CTRLMON) && ctrlmon) { - ret = resctrl_ctrlmon_enable(rdtgrp->kn, rdtgrp, - &rdtgrp->mon.mon_data_kn); - if (!ret) - rdtgrp->flags |= RDT_CTRLMON; - } else { - ret = -ENOENT; - } - -unlock: - resctrl_group_kn_unlock(of->kn); - return ret ?: nbytes; -} - -int resctrl_group_ctrlmon_show(struct kernfs_open_file *of, - struct seq_file *s, void *v) -{ - struct rdtgroup *rdtgrp; - int ret = 0; - - rdtgrp = resctrl_group_kn_lock_live(of->kn); - if (rdtgrp) - seq_printf(s, "%d", !!(rdtgrp->flags & RDT_CTRLMON)); - else - ret = -ENOENT; - resctrl_group_kn_unlock(of->kn); - - return ret; -} - - -static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn, +static int resctrl_mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn, struct resctrl_schema *s, struct resctrl_group *prgrp) { struct resctrl_resource *r; @@ -613,7 +504,7 @@ static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn,
r = s->res; list_for_each_entry(dom, &r->domains, list) { - ret = mkdir_mondata_subdir(parent_kn, dom, s, prgrp); + ret = resctrl_mkdir_mondata_dom(parent_kn, dom, s, prgrp); if (ret) return ret; } @@ -621,79 +512,13 @@ static int mkdir_mondata_subdir_alldom(struct kernfs_node *parent_kn, 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)) { - pr_info("%s: create dir %s, error\n", __func__, name); - 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) +int resctrl_mkdir_mondata_all_subdir(struct kernfs_node *parent_kn, + struct resctrl_group *prgrp) { struct resctrl_schema *s; struct resctrl_resource *r; - struct kernfs_node *kn; int ret;
- /* - * Create the mon_data directory first. - */ - ret = mongroup_create_dir(parent_kn, prgrp, "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 @@ -705,61 +530,14 @@ int mkdir_mondata_all(struct kernfs_node *parent_kn, struct raw_resctrl_resource *rr;
rr = r->res; - /* - * num pmg of different resources varies, we just - * skip creating those unqualified ones. - */ - if ((prgrp->type == RDTMON_GROUP) && - (prgrp->mon.rmid >= rr->num_pmg)) - continue;
- ret = mkdir_mondata_subdir_alldom(kn, s, prgrp); + ret = resctrl_mkdir_mondata_subdir_alldom(parent_kn, + s, prgrp); if (ret) - goto out_destroy; + break; } }
- kernfs_activate(kn); - - return 0; - -out_destroy: - kernfs_remove(kn); - return ret; -} - -int resctrl_mkdir_ctrlmon_mondata(struct kernfs_node *parent_kn, - struct resctrl_group *prgrp, - struct kernfs_node **dest_kn) -{ - int ret; - - /* disalbe monitor by default for mpam. */ - if (prgrp->type == RDTCTRL_GROUP) - return 0; - - ret = alloc_mon(); - if (ret < 0) { - rdt_last_cmd_puts("out of monitors\n"); - return ret; - } - prgrp->mon.mon = ret; - - ret = alloc_mon_id(); - if (ret < 0) { - rdt_last_cmd_puts("out of PMGs\n"); - free_mon(prgrp->mon.mon); - return ret; - } - - prgrp->mon.rmid = ret; - - ret = mkdir_mondata_all(parent_kn, prgrp, dest_kn); - if (ret) { - rdt_last_cmd_puts("kernfs subdir error\n"); - free_mon(ret); - } - return ret; }
diff --git a/arch/arm64/kernel/mpam/mpam_mon.c b/arch/arm64/kernel/mpam/mpam_mon.c index bb681d1ab7ad..29f84e251b1e 100644 --- a/arch/arm64/kernel/mpam/mpam_mon.c +++ b/arch/arm64/kernel/mpam/mpam_mon.c @@ -38,7 +38,6 @@ bool rdt_mon_capable;
static int pmg_free_map; -void mon_init(void); void pmg_init(void) { u16 num_pmg = USHRT_MAX; @@ -53,15 +52,13 @@ void pmg_init(void) num_pmg = min(num_pmg, rr->num_pmg); }
- mon_init(); - pmg_free_map = BIT_MASK(num_pmg) - 1;
/* pmg 0 is always reserved for the default group */ pmg_free_map &= ~1; }
-int alloc_pmg(void) +static int alloc_pmg(void) { u32 pmg = ffs(pmg_free_map);
@@ -74,58 +71,66 @@ int alloc_pmg(void) return pmg; }
-void free_pmg(u32 pmg) +static void free_pmg(u32 pmg) { pmg_free_map |= 1 << pmg; }
-static int mon_free_map; +int alloc_mon_id(void) +{ + return alloc_pmg(); +} + +void free_mon_id(u32 id) +{ + free_pmg(id); +} + +/* + * A simple LRU monitor allocation machanism, each + * monitor free map occupies two section, one for + * allocation and another for recording. + */ +static int mon_free_map[2]; +static u8 alloc_idx, record_idx; + void mon_init(void) { int num_mon; + u32 times, flag;
num_mon = mpam_resctrl_max_mon_num();
- mon_free_map = BIT_MASK(num_mon) - 1; + hw_alloc_times_validate(times, flag); + /* for cdp on or off */ + num_mon = rounddown(num_mon, times); + + mon_free_map[0] = BIT_MASK(num_mon) - 1; + mon_free_map[1] = 0; + + alloc_idx = 0; + record_idx = 1; }
-int alloc_mon(void) +int resctrl_lru_request_mon(void) { u32 mon = 0; u32 times, flag;
- hw_alloc_times_validate(mon, times, flag); + hw_alloc_times_validate(times, flag);
- mon = ffs(mon_free_map); + mon = ffs(mon_free_map[alloc_idx]); if (mon == 0) return -ENOSPC;
mon--; - mon_free_map &= ~(GENMASK(mon, mon + times - 1)); + mon_free_map[alloc_idx] &= ~(GENMASK(mon + times - 1, mon)); + mon_free_map[record_idx] |= GENMASK(mon + times - 1, mon);
- return mon; -} - -void free_mon(u32 mon) -{ - u32 times, flag; - - hw_alloc_times_validate(mon, times, flag); - - mon_free_map |= GENMASK(mon, mon + times - 1); -} - -/* - * As of now the RMIDs allocation is global. - * However we keep track of which packages the RMIDs - * are used to optimize the limbo list management. - */ -int alloc_rmid(void) -{ - return alloc_pmg(); -} + if (!mon_free_map[alloc_idx]) { + alloc_idx = record_idx; + record_idx ^= 0x1; + }
-void free_rmid(u32 pmg) -{ - free_pmg(pmg); + return mon; } diff --git a/arch/arm64/kernel/mpam/mpam_resctrl.c b/arch/arm64/kernel/mpam/mpam_resctrl.c index aafe20473acf..ce05b8037a4d 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -124,16 +124,7 @@ static u64 mbw_rdmsr(struct rdt_domain *d, int partid); static u64 cache_rdmon(struct rdt_domain *d, void *md_priv); static u64 mbw_rdmon(struct rdt_domain *d, void *md_priv);
-static int common_wrmon(struct rdt_domain *d, void *md_priv, bool enable); - -static inline bool is_mon_dyn(u32 mon) -{ - /* - * if rdtgrp->mon.mon has been tagged with value (max_mon_num), - * allocating a monitor in dynamic when getting monitor data. - */ - return (mon == mpam_resctrl_max_mon_num()) ? true : false; -} +static int common_wrmon(struct rdt_domain *d, void *md_priv);
static int parse_cbm(char *buf, struct raw_resctrl_resource *r, struct resctrl_staged_config *cfg, hw_closid_t hw_closid); @@ -346,19 +337,12 @@ static u64 cache_rdmon(struct rdt_domain *d, void *md_priv) union mon_data_bits md; struct sync_args args; struct mpam_resctrl_dom *dom; - u32 mon; unsigned long timeout;
md.priv = md_priv;
- mon = md.u.mon; - - /* Indicates whether allocating a monitor dynamically*/ - if (is_mon_dyn(mon)) - mon = alloc_mon(); - args.partid = md.u.partid; - args.mon = mon; + args.mon = md.u.mon; args.pmg = md.u.pmg; args.match_pmg = true; args.eventid = QOS_L3_OCCUP_EVENT_ID; @@ -380,9 +364,6 @@ static u64 cache_rdmon(struct rdt_domain *d, void *md_priv) WARN_ON(err && (err != -EBUSY)); } while (err == -EBUSY);
- if (is_mon_dyn(mon)) - free_mon(mon); - return result; } /* @@ -396,18 +377,12 @@ static u64 mbw_rdmon(struct rdt_domain *d, void *md_priv) union mon_data_bits md; struct sync_args args; struct mpam_resctrl_dom *dom; - u32 mon; unsigned long timeout;
md.priv = md_priv;
- mon = md.u.mon; - - if (is_mon_dyn(mon)) - mon = alloc_mon(); - args.partid = md.u.partid; - args.mon = mon; + args.mon = md.u.mon; args.pmg = md.u.pmg; args.match_pmg = true; args.eventid = QOS_L3_MBM_LOCAL_EVENT_ID; @@ -429,22 +404,17 @@ static u64 mbw_rdmon(struct rdt_domain *d, void *md_priv) WARN_ON(err && (err != -EBUSY)); } while (err == -EBUSY);
- if (is_mon_dyn(mon)) - free_mon(mon); return result; }
static int -common_wrmon(struct rdt_domain *d, void *md_priv, bool enable) +common_wrmon(struct rdt_domain *d, void *md_priv) { u64 result; union mon_data_bits md; struct sync_args args; struct mpam_resctrl_dom *dom;
- if (!enable) - return -EINVAL; - md.priv = md_priv; args.partid = md.u.partid; args.mon = md.u.mon; @@ -493,7 +463,7 @@ int closid_init(void) num_closid = mpam_sysprops_num_partid(); num_closid = min(num_closid, RESCTRL_MAX_CLOSID);
- hw_alloc_times_validate(clos, times, flag); + hw_alloc_times_validate(times, flag);
if (flag) num_closid = rounddown(num_closid, 2); @@ -519,7 +489,7 @@ int closid_alloc(void) int pos; u32 times, flag;
- hw_alloc_times_validate(clos, times, flag); + hw_alloc_times_validate(times, flag);
pos = find_first_bit(closid_free_map, num_closid); if (pos == num_closid) @@ -534,7 +504,7 @@ void closid_free(int closid) { u32 times, flag;
- hw_alloc_times_validate(clos, times, flag); + hw_alloc_times_validate(times, flag); bitmap_set(closid_free_map, closid, times); }
@@ -1211,15 +1181,7 @@ static struct rftype res_specific_files[] = { .write = resctrl_group_schemata_write, .seq_show = resctrl_group_schemata_show, .fflags = RF_CTRL_BASE, - }, - { - .name = "ctrlmon", - .mode = 0644, - .kf_ops = &resctrl_group_kf_single_ops, - .write = resctrl_group_ctrlmon_write, - .seq_show = resctrl_group_ctrlmon_show, - .fflags = RF_CTRL_BASE, - }, + } };
struct rdt_domain *mpam_find_domain(struct resctrl_resource *r, int id, @@ -1479,3 +1441,28 @@ u16 mpam_resctrl_max_mon_num(void)
return mon_num; } + +int resctrl_id_init(void) +{ + int ret; + + ret = closid_init(); + if (ret) + goto out; + + pmg_init(); + mon_init(); + +out: + return ret; +} + +int resctrl_id_alloc(void) +{ + return closid_alloc(); +} + +void resctrl_id_free(int id) +{ + closid_free(id); +} diff --git a/fs/resctrlfs.c b/fs/resctrlfs.c index e4f4f2b35079..ebca3fb03e9a 100644 --- a/fs/resctrlfs.c +++ b/fs/resctrlfs.c @@ -313,6 +313,138 @@ void resctrl_group_kn_unlock(struct kernfs_node *kn) } }
+static 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)) { + pr_info("%s: create dir %s, error\n", __func__, name); + 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; +} + +static void mkdir_mondata_all_prepare_clean(struct resctrl_group *prgrp) +{ + if (prgrp->type == RDTCTRL_GROUP) + return; + + if (prgrp->closid) + resctrl_id_free(prgrp->closid); + if (prgrp->mon.rmid) + free_mon_id(prgrp->mon.rmid); +} + +static int mkdir_mondata_all_prepare(struct resctrl_group *rdtgrp) +{ + int ret = 0; + int mon, mon_id, closid; + + mon = resctrl_lru_request_mon(); + if (mon < 0) { + rdt_last_cmd_puts("out of monitors\n"); + ret = -EINVAL; + goto out; + } + rdtgrp->mon.mon = mon; + + if (rdtgrp->type == RDTMON_GROUP) { + mon_id = alloc_mon_id(); + if (mon_id < 0) { + closid = resctrl_id_alloc(); + if (closid < 0) { + rdt_last_cmd_puts("out of closID\n"); + free_mon_id(mon_id); + ret = -EINVAL; + goto out; + } + rdtgrp->closid = closid; + rdtgrp->mon.rmid = 0; + } else { + struct resctrl_group *prgrp; + + prgrp = rdtgrp->mon.parent; + rdtgrp->closid = prgrp->closid; + rdtgrp->mon.rmid = mon_id; + } + } + +out: + 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 + * + */ +static int mkdir_mondata_all(struct kernfs_node *parent_kn, + struct resctrl_group *prgrp, + struct kernfs_node **dest_kn) +{ + struct kernfs_node *kn; + int ret; + + /* + * Create the mon_data directory first. + */ + ret = mongroup_create_dir(parent_kn, prgrp, "mon_data", &kn); + if (ret) + return ret; + + if (dest_kn) + *dest_kn = kn; + + ret = resctrl_mkdir_mondata_all_subdir(kn, prgrp); + if (ret) + goto out_destroy; + + kernfs_activate(kn); + + return 0; + +out_destroy: + kernfs_remove(kn); + return ret; +} + static struct dentry *resctrl_mount(struct file_system_type *fs_type, int flags, const char *unused_dev_name, void *data) @@ -365,6 +497,11 @@ static struct dentry *resctrl_mount(struct file_system_type *fs_type, kernfs_get(kn_mongrp);
#ifndef CONFIG_ARM64 /* [FIXME] arch specific code */ + ret = mkdir_mondata_all_prepare(&resctrl_group_default); + if (ret < 0) { + dentry = ERR_PTR(ret); + goto out_mongrp; + } ret = mkdir_mondata_all(resctrl_group_default.kn, &resctrl_group_default, &kn_mondata); if (ret) { @@ -562,6 +699,17 @@ static int mkdir_resctrl_prepare(struct kernfs_node *parent_kn, *r = rdtgrp; rdtgrp->mon.parent = prdtgrp; rdtgrp->type = rtype; + + if (rdtgrp->type == RDTCTRL_GROUP) { + ret = resctrl_id_alloc(); + if (ret < 0) { + rdt_last_cmd_puts("out of CLOSIDs\n"); + goto out_unlock; + } + rdtgrp->closid = ret; + ret = 0; + } + INIT_LIST_HEAD(&rdtgrp->mon.crdtgrp_list);
/* kernfs creates the directory for rdtgrp */ @@ -595,27 +743,16 @@ static int mkdir_resctrl_prepare(struct kernfs_node *parent_kn, }
if (resctrl_mon_capable) { -#ifdef CONFIG_ARM64 - ret = resctrl_mkdir_ctrlmon_mondata(kn, rdtgrp, &rdtgrp->mon.mon_data_kn); - if (ret < 0) { - rdt_last_cmd_puts("out of monitors or PMGs\n"); - goto out_destroy; - } - -#else - ret = alloc_mon_id(); + ret = mkdir_mondata_all_prepare(rdtgrp); if (ret < 0) { - rdt_last_cmd_puts("out of RMIDs\n"); goto out_destroy; } - rdtgrp->mon.rmid = ret;
ret = mkdir_mondata_all(kn, rdtgrp, &rdtgrp->mon.mon_data_kn); if (ret) { rdt_last_cmd_puts("kernfs subdir error\n"); - goto out_idfree; + goto out_prepare_clean; } -#endif } kernfs_activate(kn);
@@ -624,10 +761,8 @@ static int mkdir_resctrl_prepare(struct kernfs_node *parent_kn, */ return 0;
-#ifndef CONFIG_ARM64 -out_idfree: - free_mon_id(rdtgrp->mon.rmid); -#endif +out_prepare_clean: + mkdir_mondata_all_prepare_clean(rdtgrp); out_destroy: kernfs_remove(rdtgrp->kn); out_free_rgrp: @@ -640,7 +775,6 @@ static int mkdir_resctrl_prepare(struct kernfs_node *parent_kn, static void mkdir_resctrl_prepare_clean(struct resctrl_group *rgrp) { kernfs_remove(rgrp->kn); - free_mon_id(rgrp->mon.rmid); kfree(rgrp); }
@@ -663,8 +797,6 @@ static int resctrl_group_mkdir_mon(struct kernfs_node *parent_kn, return ret;
prgrp = rdtgrp->mon.parent; - rdtgrp->closid = prgrp->closid; - /* * Add the rdtgrp to the list of rdtgrps the parent * ctrl_mon group has to track. @@ -685,7 +817,6 @@ static int resctrl_group_mkdir_ctrl_mon(struct kernfs_node *parent_kn, { struct resctrl_group *rdtgrp; struct kernfs_node *kn; - u32 closid; int ret;
ret = mkdir_resctrl_prepare(parent_kn, prgrp_kn, name, mode, RDTCTRL_GROUP, @@ -694,19 +825,10 @@ static int resctrl_group_mkdir_ctrl_mon(struct kernfs_node *parent_kn, return ret;
kn = rdtgrp->kn; - ret = resctrl_id_alloc(); - if (ret < 0) { - rdt_last_cmd_puts("out of CLOSIDs\n"); - goto out_common_fail; - } - closid = ret; - ret = 0; - - rdtgrp->closid = closid;
ret = resctrl_group_init_alloc(rdtgrp); if (ret < 0) - goto out_id_free; + goto out_common_fail;
list_add(&rdtgrp->resctrl_group_list, &resctrl_all_groups);
@@ -718,14 +840,13 @@ static int resctrl_group_mkdir_ctrl_mon(struct kernfs_node *parent_kn, ret = mongroup_create_dir(kn, NULL, "mon_groups", NULL); if (ret) { rdt_last_cmd_puts("kernfs subdir error\n"); - goto out_id_free; + goto out_list_del; } }
goto out_unlock;
-out_id_free: - resctrl_id_free(closid); +out_list_del: list_del(&rdtgrp->resctrl_group_list); out_common_fail: mkdir_resctrl_prepare_clean(rdtgrp); @@ -781,10 +902,6 @@ static void resctrl_group_rm_mon(struct resctrl_group *rdtgrp, struct resctrl_group *prdtgrp = rdtgrp->mon.parent; int cpu;
-#ifdef CONFIG_ARM64 /* [FIXME] arch specific code */ - free_mon(rdtgrp->mon.mon); -#endif - /* Give any tasks back to the parent group */ resctrl_move_group_tasks(rdtgrp, prdtgrp, tmpmask);
@@ -862,11 +979,6 @@ static void resctrl_group_rm_ctrl(struct resctrl_group *rdtgrp, cpumask_var_t tm static int resctrl_group_rmdir_ctrl(struct kernfs_node *kn, struct resctrl_group *rdtgrp, cpumask_var_t tmpmask) { -#ifdef CONFIG_ARM64 /* [FIXME] arch specific code */ - if (rdtgrp->flags & RDT_CTRLMON) - return -EPERM; -#endif - resctrl_group_rm_ctrl(rdtgrp, tmpmask);
/*