From: Wang ShaoBo bobo.shaobowang@huawei.com
hulk inclusion category: feature bugzilla: 34278 CVE: NA
-------------------------------------------------
We now bridge resctrl intermediate processing module and mpam devices module, a large block of code refer to configuration and monitoring process involved need to be modified.
We change the previous method where straightly writing MSCs' registers, this jobs are handed over to helpers offered by mpam devices module instead, when configuration or monitoring action happened, each domains' ctrlval array changed by resctrl sysfs input would be updated into mpam config structure live in each mpam component structure, relevant helpers provided by mpam devices module will soon accomplish the remaining jobs.
Comparasion: configuration or monitoring
old new + + | | | +---------+------------+ | | intermediate helpers | | +---------+------------+ | | | | +--+-----------------+----+ | [reading writing MMIO] | +-------------------------+
So far we nearly accomplish the mission that open up process between resctrl sysfs and mpam devices module but still incomplete currently, also some proper actions are needed after.
Also this moves relevant structures such as struct mongroup to suitable place,.
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 | 67 +--- arch/arm64/include/asm/resctrl.h | 56 ++- arch/arm64/kernel/mpam/mpam_ctrlmon.c | 38 +- arch/arm64/kernel/mpam/mpam_internal.h | 3 + arch/arm64/kernel/mpam/mpam_mon.c | 26 +- arch/arm64/kernel/mpam/mpam_resctrl.c | 459 ++++++++++++++++--------- arch/arm64/kernel/mpam/mpam_setup.c | 13 + fs/resctrlfs.c | 17 + 8 files changed, 433 insertions(+), 246 deletions(-)
diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h index a70133fff450..5aef534fb3df 100644 --- a/arch/arm64/include/asm/mpam.h +++ b/arch/arm64/include/asm/mpam.h @@ -118,54 +118,6 @@ DECLARE_STATIC_KEY_FALSE(resctrl_mon_enable_key); extern bool rdt_alloc_capable; extern bool rdt_mon_capable;
-enum rdt_group_type { - RDTCTRL_GROUP = 0, - RDTMON_GROUP, - RDT_NUM_GROUP, -}; - -/** - * struct mongroup - store mon group's data in resctrl fs. - * @mon_data_kn kernlfs node for the mon_data directory - * @parent: parent rdtgrp - * @crdtgrp_list: child rdtgroup node list - * @rmid: rmid for this rdtgroup - * @mon: monnitor id - */ -struct mongroup { - struct kernfs_node *mon_data_kn; - struct rdtgroup *parent; - struct list_head crdtgrp_list; - u32 rmid; - u32 mon; - int init; -}; - -/** - * struct rdtgroup - store rdtgroup's data in resctrl file system. - * @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 - * group when they acquire resctrl_group_mutex - * @type: indicates type of this rdtgroup - either - * monitor only or ctrl_mon group - * @mon: mongroup related data - */ -struct rdtgroup { - struct kernfs_node *kn; - struct list_head resctrl_group_list; - u32 closid; - struct cpumask cpu_mask; - int flags; - atomic_t waitcount; - enum rdt_group_type type; - struct mongroup mon; -}; - extern int max_name_width, max_data_width;
/* rdtgroup.flags */ @@ -284,15 +236,18 @@ struct raw_resctrl_resource { u16 pri_wd; u16 hdl_wd;
- void (*msr_update) (struct rdt_domain *d, int partid); - u64 (*msr_read) (struct rdt_domain *d, int partid); + void (*msr_update)(struct resctrl_resource *r, struct rdt_domain *d, + struct list_head *opt_list, int partid); + u64 (*msr_read)(struct rdt_domain *d, int partid); + int data_width; const char *format_str; - int (*parse_ctrlval) (char *buf, struct raw_resctrl_resource *r, - struct rdt_domain *d); - int num_mon; - u64 (*mon_read) (struct rdt_domain *d, struct rdtgroup *g); - int (*mon_write) (struct rdt_domain *d, struct rdtgroup *g, bool enable); + int (*parse_ctrlval)(char *buf, struct raw_resctrl_resource *r, + struct rdt_domain *d); + + u16 num_mon; + u64 (*mon_read)(struct rdt_domain *d, struct rdtgroup *g); + int (*mon_write)(struct rdt_domain *d, struct rdtgroup *g, bool enable); };
int parse_cbm(char *buf, struct raw_resctrl_resource *r, struct rdt_domain *d); @@ -321,4 +276,6 @@ int resctrl_mkdir_ctrlmon_mondata(struct kernfs_node *parent_kn, struct rdtgroup *prgrp, struct kernfs_node **dest_kn);
+u16 mpam_resctrl_max_mon_num(void); + #endif /* _ASM_ARM64_MPAM_H */ diff --git a/arch/arm64/include/asm/resctrl.h b/arch/arm64/include/asm/resctrl.h index d0d30a0fdc1d..2119204fa090 100644 --- a/arch/arm64/include/asm/resctrl.h +++ b/arch/arm64/include/asm/resctrl.h @@ -27,6 +27,54 @@ enum rdt_event_id { RESCTRL_NUM_EVENT_IDS, };
+enum rdt_group_type { + RDTCTRL_GROUP = 0, + RDTMON_GROUP, + RDT_NUM_GROUP, +}; + +/** + * struct mongroup - store mon group's data in resctrl fs. + * @mon_data_kn kernlfs node for the mon_data directory + * @parent: parent rdtgrp + * @crdtgrp_list: child rdtgroup node list + * @rmid: rmid for this rdtgroup + * @mon: monnitor id + */ +struct mongroup { + struct kernfs_node *mon_data_kn; + struct rdtgroup *parent; + struct list_head crdtgrp_list; + u32 rmid; + u32 mon; + int init; +}; + +/** + * struct rdtgroup - store rdtgroup's data in resctrl file system. + * @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 + * group when they acquire resctrl_group_mutex + * @type: indicates type of this rdtgroup - either + * monitor only or ctrl_mon group + * @mon: mongroup related data + */ +struct rdtgroup { + struct kernfs_node *kn; + struct list_head resctrl_group_list; + u32 closid; + struct cpumask cpu_mask; + int flags; + atomic_t waitcount; + enum rdt_group_type type; + struct mongroup mon; +}; + static inline int alloc_mon_id(void) {
@@ -69,11 +117,6 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of, #define release_resctrl_group_fs_options release_rdtgroupfs_options #define parse_resctrl_group_fs_options parse_rdtgroupfs_options
-#define for_each_resctrl_resource(r) \ - for (r = resctrl_resources_all; \ - r < resctrl_resources_all + RDT_NUM_RESOURCES; \ - r++) \ - int mpam_get_mon_config(struct resctrl_resource *r);
int mkdir_mondata_all(struct kernfs_node *parent_kn, @@ -86,4 +129,7 @@ mongroup_create_dir(struct kernfs_node *parent_kn, struct resctrl_group *prgrp,
int rdtgroup_init_alloc(struct rdtgroup *rdtgrp);
+struct resctrl_resource * +mpam_resctrl_get_resource(enum resctrl_resource_level level); + #endif /* _ASM_ARM64_RESCTRL_H */ diff --git a/arch/arm64/kernel/mpam/mpam_ctrlmon.c b/arch/arm64/kernel/mpam/mpam_ctrlmon.c index 0d4ba3afe419..39c5020cdfa6 100644 --- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c +++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c @@ -38,6 +38,7 @@ #include <asm/mpam.h> #include <asm/mpam_resource.h> #include <asm/resctrl.h> +#include "mpam_internal.h"
/* * Check whether a cache bit mask is valid. The SDM says: @@ -188,7 +189,7 @@ static int update_domains(struct resctrl_resource *r, struct rdtgroup *g) list_for_each_entry(d, &r->domains, list) { if (d->have_new_ctrl && d->new_ctrl != d->ctrl_val[partid]) { d->ctrl_val[partid] = d->new_ctrl; - rr->msr_update(d, partid); + rr->msr_update(r, d, NULL, partid); } }
@@ -197,13 +198,17 @@ static int update_domains(struct resctrl_resource *r, struct rdtgroup *g)
static int resctrl_group_parse_resource(char *resname, char *tok, int closid) { + struct mpam_resctrl_res *res; struct resctrl_resource *r; struct raw_resctrl_resource *rr;
- for_each_resctrl_resource(r) { + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; + if (r->alloc_enabled) { rr = (struct raw_resctrl_resource *)r->res; - if (!strcmp(resname, r->name) && closid < rr->num_partid) + if (!strcmp(resname, r->name) && closid < + mpam_sysprops_num_partid()) return parse_line(tok, r); } } @@ -216,6 +221,7 @@ ssize_t resctrl_group_schemata_write(struct kernfs_open_file *of, { struct rdtgroup *rdtgrp; struct rdt_domain *dom; + struct mpam_resctrl_res *res; struct resctrl_resource *r; char *tok, *resname; int closid, ret = 0; @@ -234,7 +240,9 @@ ssize_t resctrl_group_schemata_write(struct kernfs_open_file *of,
closid = rdtgrp->closid;
- for_each_resctrl_resource(r) { + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; + if (r->alloc_enabled) { list_for_each_entry(dom, &r->domains, list) dom->have_new_ctrl = false; @@ -258,7 +266,9 @@ ssize_t resctrl_group_schemata_write(struct kernfs_open_file *of, goto out; }
- for_each_resctrl_resource(r) { + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; + if (r->alloc_enabled) { ret = update_domains(r, rdtgrp); if (ret) @@ -292,6 +302,7 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of, struct seq_file *s, void *v) { struct rdtgroup *rdtgrp; + struct mpam_resctrl_res *res; struct resctrl_resource *r; struct raw_resctrl_resource *rr; int ret = 0; @@ -300,10 +311,11 @@ int resctrl_group_schemata_show(struct kernfs_open_file *of, rdtgrp = resctrl_group_kn_lock_live(of->kn); if (rdtgrp) { partid = rdtgrp->closid; - for_each_resctrl_resource(r) { + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; if (r->alloc_enabled) { rr = (struct raw_resctrl_resource *)r->res; - if (partid < rr->num_partid) + if (partid < mpam_sysprops_num_partid()) show_doms(s, r, partid); } } @@ -367,7 +379,7 @@ int resctrl_group_mondata_show(struct seq_file *m, void *arg)
md.priv = of->kn->priv;
- r = &resctrl_resources_all[md.u.rid]; + r = mpam_resctrl_get_resource(md.u.rid); rr = r->res;
/* show monitor data */ @@ -516,6 +528,7 @@ int mkdir_mondata_all(struct kernfs_node *parent_kn, struct resctrl_group *prgrp, struct kernfs_node **dest_kn) { + struct mpam_resctrl_res *res; struct resctrl_resource *r; struct kernfs_node *kn; int ret; @@ -534,7 +547,9 @@ int mkdir_mondata_all(struct kernfs_node *parent_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) { + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; + if (r->mon_enabled) { /* HHA does not support monitor by pmg */ if ((prgrp->type == RDTMON_GROUP) && @@ -593,11 +608,14 @@ int resctrl_mkdir_ctrlmon_mondata(struct kernfs_node *parent_kn, /* Initialize the RDT group's allocations. */ int rdtgroup_init_alloc(struct rdtgroup *rdtgrp) { + struct mpam_resctrl_res *res; struct resctrl_resource *r; struct rdt_domain *d; int ret;
- for_each_resctrl_resource(r) { + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; + if (!r->alloc_enabled) continue;
diff --git a/arch/arm64/kernel/mpam/mpam_internal.h b/arch/arm64/kernel/mpam/mpam_internal.h index ea8be8c861c0..8ab019fd8938 100644 --- a/arch/arm64/kernel/mpam/mpam_internal.h +++ b/arch/arm64/kernel/mpam/mpam_internal.h @@ -170,6 +170,9 @@ u16 mpam_sysprops_num_pmg(void);
void mpam_class_list_lock_held(void);
+extern struct mpam_resctrl_res mpam_resctrl_exports[RDT_NUM_RESOURCES]; +extern struct mpam_resctrl_res mpam_resctrl_events[RESCTRL_NUM_EVENT_IDS]; + int mpam_resctrl_cpu_online(unsigned int cpu);
int mpam_resctrl_cpu_offline(unsigned int cpu); diff --git a/arch/arm64/kernel/mpam/mpam_mon.c b/arch/arm64/kernel/mpam/mpam_mon.c index 81dddf5432b5..f952e9aa20c2 100644 --- a/arch/arm64/kernel/mpam/mpam_mon.c +++ b/arch/arm64/kernel/mpam/mpam_mon.c @@ -43,10 +43,17 @@ static int pmg_free_map; void mon_init(void); void pmg_init(void) { - /* use L3's num_pmg as system num_pmg */ - struct raw_resctrl_resource *rr = - resctrl_resources_all[RDT_RESOURCE_L3].res; - int num_pmg = rr->num_pmg; + u16 num_pmg = USHRT_MAX; + struct mpam_resctrl_res *res; + struct resctrl_resource *r; + struct raw_resctrl_resource *rr; + + /* Use the max num_pmg among all resources */ + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; + rr = r->res; + num_pmg = min(num_pmg, rr->num_pmg); + }
mon_init();
@@ -77,16 +84,9 @@ void free_pmg(u32 pmg) static int mon_free_map; void mon_init(void) { - struct resctrl_resource *r; - struct raw_resctrl_resource *rr; - int num_mon = INT_MAX; + int num_mon;
- for_each_resctrl_resource(r) { - if (r->mon_enabled) { - rr = r->res; - num_mon = min(num_mon, rr->num_mon); - } - } + num_mon = mpam_resctrl_max_mon_num();
mon_free_map = BIT_MASK(num_mon) - 1; } diff --git a/arch/arm64/kernel/mpam/mpam_resctrl.c b/arch/arm64/kernel/mpam/mpam_resctrl.c index d4870e33c3bd..8fd5c84f28bd 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -45,6 +45,7 @@ #include <asm/resctrl.h> #include <asm/io.h>
+#include "mpam_device.h" #include "mpam_internal.h"
/* Mutex to protect rdtgroup access. */ @@ -70,6 +71,10 @@ int max_name_width, max_data_width; */ bool rdt_alloc_capable;
+/* + * Indicate the max number of monitor supported. + */ +static u32 max_mon_num; /* * Hi1620 2P Base Address Map * @@ -97,72 +102,55 @@ void mpam_resctrl_clear_default_cpu(unsigned int cpu) }
static void -cat_wrmsr(struct rdt_domain *d, int partid); +mpam_resctrl_update_component_cfg(struct resctrl_resource *r, + struct rdt_domain *d, struct list_head *opt_list, u32 partid); + static void -bw_wrmsr(struct rdt_domain *d, int partid); +common_wrmsr(struct resctrl_resource *r, struct rdt_domain *d, + struct list_head *opt_list, int partid);
-u64 cat_rdmsr(struct rdt_domain *d, int partid); -u64 bw_rdmsr(struct rdt_domain *d, int partid); +static u64 cache_rdmsr(struct rdt_domain *d, int partid); +static u64 mbw_rdmsr(struct rdt_domain *d, int partid);
-static u64 mbwu_read(struct rdt_domain *d, struct rdtgroup *g); -static u64 csu_read(struct rdt_domain *d, struct rdtgroup *g); +static u64 cache_rdmon(struct rdt_domain *d, struct rdtgroup *g); +static u64 mbw_rdmon(struct rdt_domain *d, struct rdtgroup *g);
-static int mbwu_write(struct rdt_domain *d, struct rdtgroup *g, bool enable); -static int csu_write(struct rdt_domain *d, struct rdtgroup *g, bool enable); +static int common_wrmon(struct rdt_domain *d, struct rdtgroup *g, + bool enable);
-#define domain_init(id) LIST_HEAD_INIT(resctrl_resources_all[id].domains) +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; +}
struct raw_resctrl_resource raw_resctrl_resources_all[] = { [RDT_RESOURCE_L3] = { - .msr_update = cat_wrmsr, - .msr_read = cat_rdmsr, - .parse_ctrlval = parse_cbm, - .format_str = "%d=%0*x", - .mon_read = csu_read, - .mon_write = csu_write, + .msr_update = common_wrmsr, + .msr_read = cache_rdmsr, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", + .mon_read = cache_rdmon, + .mon_write = common_wrmon, }, [RDT_RESOURCE_L2] = { - .msr_update = cat_wrmsr, - .msr_read = cat_rdmsr, - .parse_ctrlval = parse_cbm, - .format_str = "%d=%0*x", - .mon_read = csu_read, - .mon_write = csu_write, + .msr_update = common_wrmsr, + .msr_read = cache_rdmsr, + .parse_ctrlval = parse_cbm, + .format_str = "%d=%0*x", + .mon_read = cache_rdmon, + .mon_write = common_wrmon, }, [RDT_RESOURCE_MC] = { - .msr_update = bw_wrmsr, - .msr_read = bw_rdmsr, - .parse_ctrlval = parse_bw, /* add parse_bw() helper */ - .format_str = "%d=%0*d", - .mon_read = mbwu_read, - .mon_write = mbwu_write, - }, -}; - -struct resctrl_resource resctrl_resources_all[] = { - [RDT_RESOURCE_L3] = { - .rid = RDT_RESOURCE_L3, - .name = "L3", - .domains = domain_init(RDT_RESOURCE_L3), - .res = &raw_resctrl_resources_all[RDT_RESOURCE_L3], - .fflags = RFTYPE_RES_CACHE, - .alloc_enabled = 1, - }, - [RDT_RESOURCE_L2] = { - .rid = RDT_RESOURCE_L2, - .name = "L2", - .domains = domain_init(RDT_RESOURCE_L2), - .res = &raw_resctrl_resources_all[RDT_RESOURCE_L2], - .fflags = RFTYPE_RES_CACHE, - .alloc_enabled = 1, - }, - [RDT_RESOURCE_MC] = { - .rid = RDT_RESOURCE_MC, - .name = "MB", - .domains = domain_init(RDT_RESOURCE_MC), - .res = &raw_resctrl_resources_all[RDT_RESOURCE_MC], - .fflags = RFTYPE_RES_MC, - .alloc_enabled = 1, + .msr_update = common_wrmsr, + .msr_read = mbw_rdmsr, + .parse_ctrlval = parse_bw, + .format_str = "%d=%0*d", + .mon_read = mbw_rdmon, + .mon_write = common_wrmon, }, };
@@ -176,35 +164,51 @@ mpam_get_raw_resctrl_resource(enum resctrl_resource_level level) }
static void -cat_wrmsr(struct rdt_domain *d, int partid) +common_wrmsr(struct resctrl_resource *r, struct rdt_domain *d, + struct list_head *opt_list, int partid) { - mpam_writel(partid, d->base + MPAMCFG_PART_SEL); - mpam_writel(d->ctrl_val[partid], d->base + MPAMCFG_CPBM); -} + struct sync_args args; + struct mpam_resctrl_dom *dom;
-static void -bw_wrmsr(struct rdt_domain *d, int partid) -{ - u64 val = MBW_MAX_SET(d->ctrl_val[partid]); + args.partid = partid;
- mpam_writel(partid, d->base + MPAMCFG_PART_SEL); - mpam_writel(val, d->base + MPAMCFG_MBW_MAX); + dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); + + mpam_resctrl_update_component_cfg(r, d, opt_list, partid); + + mpam_component_config(dom->comp, &args); }
-u64 cat_rdmsr(struct rdt_domain *d, int partid) +static u64 cache_rdmsr(struct rdt_domain *d, int partid) { - mpam_writel(partid, d->base + MPAMCFG_PART_SEL); - return mpam_readl(d->base + MPAMCFG_CPBM); -} + u32 result; + struct sync_args args; + struct mpam_resctrl_dom *dom;
-u64 bw_rdmsr(struct rdt_domain *d, int partid) + args.partid = partid; + args.reg = MPAMCFG_CPBM; + + dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); + + mpam_component_get_config(dom->comp, &args, &result); + + return result; +} +static u64 mbw_rdmsr(struct rdt_domain *d, int partid) { u64 max; + u32 result; + struct sync_args args; + struct mpam_resctrl_dom *dom; + + args.partid = partid; + args.reg = MPAMCFG_MBW_MAX; + + dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom);
- mpam_writel(partid, d->base + MPAMCFG_PART_SEL); - max = mpam_readl(d->base + MPAMCFG_MBW_MAX); + mpam_component_get_config(dom->comp, &args, &result);
- max = MBW_MAX_GET(max); + max = MBW_MAX_GET(result); return roundup((max * 100) / 64, 5); }
@@ -212,81 +216,116 @@ u64 bw_rdmsr(struct rdt_domain *d, int partid) * use pmg as monitor id * just use match_pardid only. */ -static u64 mbwu_read(struct rdt_domain *d, struct rdtgroup *g) +static u64 cache_rdmon(struct rdt_domain *d, struct rdtgroup *g) { + int err; + u64 result; + struct sync_args args; + struct mpam_resctrl_dom *dom; u32 mon = g->mon.mon; + unsigned long timeout;
- mpam_writel(mon, d->base + MSMON_CFG_MON_SEL); - return mpam_readl(d->base + MSMON_MBWU); -} + /* Indicates whether allocating a monitor dynamically*/ + if (is_mon_dyn(mon)) + mon = alloc_mon(); + + args.partid = g->closid; + args.mon = mon; + args.pmg = g->mon.rmid; + args.match_pmg = true; + args.eventid = QOS_L3_OCCUP_EVENT_ID; + + dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); + + /** + * We should judge if return is OK, it is possible affected + * by NRDY bit. + */ + timeout = READ_ONCE(jiffies) + (1*SEC_CONVERSION); + do { + if (time_after(READ_ONCE(jiffies), timeout)) { + err = -ETIMEDOUT; + break; + } + err = mpam_component_mon(dom->comp, &args, &result); + /* Currently just report it */ + WARN_ON(err && (err != -EBUSY)); + } while (err == -EBUSY);
-static u64 csu_read(struct rdt_domain *d, struct rdtgroup *g) + if (is_mon_dyn(mon)) + free_mon(mon); + + return result; +} +/* + * use pmg as monitor id + * just use match_pardid only. + */ +static u64 mbw_rdmon(struct rdt_domain *d, struct rdtgroup *g) { + int err; + u64 result; + struct sync_args args; + struct mpam_resctrl_dom *dom; u32 mon = g->mon.mon; + unsigned long timeout;
- mpam_writel(mon, d->base + MSMON_CFG_MON_SEL); - return mpam_readl(d->base + MSMON_CSU); -} + if (is_mon_dyn(mon)) + mon = alloc_mon();
-static int mbwu_write(struct rdt_domain *d, struct rdtgroup *g, bool enable) -{ - u32 mon, partid, pmg, ctl, flt, cur_ctl, cur_flt; - - mon = g->mon.mon; - mpam_writel(mon, d->base + MSMON_CFG_MON_SEL); - if (enable) { - partid = g->closid; - pmg = g->mon.rmid; - ctl = MSMON_MATCH_PARTID|MSMON_MATCH_PMG; - flt = MSMON_CFG_FLT_SET(pmg, partid); - cur_flt = mpam_readl(d->base + MSMON_CFG_MBWU_FLT); - cur_ctl = mpam_readl(d->base + MSMON_CFG_MBWU_CTL); - - if (cur_ctl != (ctl | MSMON_CFG_CTL_EN | MSMON_CFG_MBWU_TYPE) || - cur_flt != flt) { - mpam_writel(flt, d->base + MSMON_CFG_MBWU_FLT); - mpam_writel(ctl, d->base + MSMON_CFG_MBWU_CTL); - mpam_writel(0, d->base + MSMON_MBWU); - ctl |= MSMON_CFG_CTL_EN; - mpam_writel(ctl, d->base + MSMON_CFG_MBWU_CTL); - } - } else { - ctl = 0; - mpam_writel(ctl, d->base + MSMON_CFG_MBWU_CTL); - } + args.partid = g->closid; + args.mon = mon; + args.pmg = g->mon.rmid; + args.match_pmg = true; + args.eventid = QOS_L3_MBM_LOCAL_EVENT_ID;
- return 0; + dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); + + /** + * We should judge if return is OK, it is possible affected + * by NRDY bit. + */ + timeout = READ_ONCE(jiffies) + (1*SEC_CONVERSION); + do { + if (time_after(READ_ONCE(jiffies), timeout)) { + err = -ETIMEDOUT; + break; + } + err = mpam_component_mon(dom->comp, &args, &result); + /* Currently just report it */ + WARN_ON(err && (err != -EBUSY)); + } while (err == -EBUSY); + + if (is_mon_dyn(mon)) + free_mon(mon); + return result; }
-static int csu_write(struct rdt_domain *d, struct rdtgroup *g, bool enable) +static int common_wrmon(struct rdt_domain *d, struct rdtgroup *g, bool enable) { - u32 mon, partid, pmg, ctl, flt, cur_ctl, cur_flt; - - mon = g->mon.mon; - mpam_writel(mon, d->base + MSMON_CFG_MON_SEL); - if (enable) { - partid = g->closid; - pmg = g->mon.rmid; - ctl = MSMON_MATCH_PARTID|MSMON_MATCH_PMG; - flt = MSMON_CFG_FLT_SET(pmg, partid); - cur_flt = mpam_readl(d->base + MSMON_CFG_CSU_FLT); - cur_ctl = mpam_readl(d->base + MSMON_CFG_CSU_CTL); - - if (cur_ctl != (ctl | MSMON_CFG_CTL_EN | MSMON_CFG_CSU_TYPE) || - cur_flt != flt) { - mpam_writel(flt, d->base + MSMON_CFG_CSU_FLT); - mpam_writel(ctl, d->base + MSMON_CFG_CSU_CTL); - mpam_writel(0, d->base + MSMON_CSU); - ctl |= MSMON_CFG_CTL_EN; - mpam_writel(ctl, d->base + MSMON_CFG_CSU_CTL); - } - } else { - ctl = 0; - mpam_writel(ctl, d->base + MSMON_CFG_CSU_CTL); - } + u64 result; + struct sync_args args; + struct mpam_resctrl_dom *dom; + + if (!enable) + return -EINVAL; + + args.partid = g->closid; + args.mon = g->mon.mon; + args.pmg = g->mon.rmid; + args.match_pmg = true; + + dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); + + /** + * We needn't judge if return is OK, we just want to configure + * monitor info. + */ + mpam_component_mon(dom->comp, &args, &result);
return 0; } + /* * Trivial allocator for CLOSIDs. Since h/w only supports a small number, * we can keep a bitmap of free CLOSIDs in a single integer. @@ -306,16 +345,10 @@ static int closid_free_map;
void closid_init(void) { - struct resctrl_resource *r; - struct raw_resctrl_resource *rr; int num_closid = INT_MAX;
- for_each_resctrl_resource(r) { - if (r->alloc_enabled) { - rr = r->res; - num_closid = min(num_closid, (int)rr->num_partid); - } - } + num_closid = mpam_sysprops_num_partid(); + closid_free_map = BIT_MASK(num_closid) - 1;
/* CLOSID 0 is always reserved for the default group */ @@ -345,20 +378,24 @@ void closid_free(int closid) */ static __init void mpam_init_padding(void) { + int cl; + struct mpam_resctrl_res *res; struct resctrl_resource *r; struct raw_resctrl_resource *rr; - int cl;
- for_each_resctrl_resource(r) { - if (r->alloc_enabled) { - rr = (struct raw_resctrl_resource *)r->res; - cl = strlen(r->name); - if (cl > max_name_width) - max_name_width = cl; + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res;
- if (rr->data_width > max_data_width) - max_data_width = rr->data_width; - } + cl = strlen(r->name); + if (cl > max_name_width) + max_name_width = cl; + + rr = r->res; + if (!rr) + continue; + cl = rr->data_width; + if (cl > max_data_width) + max_data_width = cl; } }
@@ -380,10 +417,13 @@ static int reset_all_ctrls(struct resctrl_resource *r)
void resctrl_resource_reset(void) { + struct mpam_resctrl_res *res; struct resctrl_resource *r;
/*Put everything back to default values. */ - for_each_resctrl_resource(r) { + for_each_supported_resctrl_exports(res) { + r = &res->resctrl_res; + if (r->alloc_enabled) reset_all_ctrls(r); } @@ -640,9 +680,12 @@ static int resctrl_num_partid_show(struct kernfs_open_file *of, struct seq_file *seq, void *v) { struct resctrl_resource *r = of->kn->parent->priv; - struct raw_resctrl_resource *rr = (struct raw_resctrl_resource *)r->res; + struct raw_resctrl_resource *rr = r->res; + u16 num_partid;
- seq_printf(seq, "%d\n", rr->num_partid); + num_partid = rr->num_partid; + + seq_printf(seq, "%d\n", num_partid);
return 0; } @@ -651,9 +694,12 @@ static int resctrl_num_pmg_show(struct kernfs_open_file *of, struct seq_file *seq, void *v) { struct resctrl_resource *r = of->kn->parent->priv; - struct raw_resctrl_resource *rr = (struct raw_resctrl_resource *)r->res; + struct raw_resctrl_resource *rr = r->res; + u16 num_pmg; + + num_pmg = rr->num_pmg;
- seq_printf(seq, "%d\n", rr->num_pmg); + seq_printf(seq, "%d\n", num_pmg);
return 0; } @@ -662,9 +708,12 @@ static int resctrl_num_mon_show(struct kernfs_open_file *of, struct seq_file *seq, void *v) { struct resctrl_resource *r = of->kn->parent->priv; - struct raw_resctrl_resource *rr = (struct raw_resctrl_resource *)r->res; + struct raw_resctrl_resource *rr = r->res; + u16 num_mon;
- seq_printf(seq, "%d\n", rr->num_mon); + num_mon = rr->num_mon; + + seq_printf(seq, "%d\n", num_mon);
return 0; } @@ -917,7 +966,8 @@ int resctrl_ctrlmon_enable(struct kernfs_node *parent_kn, void resctrl_ctrlmon_disable(struct kernfs_node *kn_mondata, struct resctrl_group *prgrp) { - struct resctrl_resource *r; + struct mpam_resctrl_res *r; + struct resctrl_resource *resctrl_res; struct raw_resctrl_resource *rr; struct rdt_domain *dom; int mon = prgrp->mon.mon; @@ -926,12 +976,13 @@ void resctrl_ctrlmon_disable(struct kernfs_node *kn_mondata, if (prgrp->type == RDTMON_GROUP) return;
- /* disable monitor before free mon */ - for_each_resctrl_resource(r) { - if (r->mon_enabled) { - rr = (struct raw_resctrl_resource *)r->res; + for_each_supported_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, &r->domains, list) { + list_for_each_entry(dom, &resctrl_res->domains, list) { rr->mon_write(dom, prgrp, false); } } @@ -1167,3 +1218,85 @@ void __mpam_sched_in(void) mpam_write_sysreg_s(reg, SYS_MPAM1_EL1, "SYS_MPAM1_EL1"); } } + +static void +mpam_update_from_resctrl_cfg(struct mpam_resctrl_res *res, + u32 resctrl_cfg, struct mpam_config *mpam_cfg) +{ + if (res == &mpam_resctrl_exports[RDT_RESOURCE_MC]) { + u64 range; + + /* For MBA cfg is a percentage of .. */ + if (res->resctrl_mba_uses_mbw_part) { + /* .. the number of bits we can set */ + range = res->class->mbw_pbm_bits; + mpam_cfg->mbw_pbm = (resctrl_cfg * range) / MAX_MBA_BW; + mpam_set_feature(mpam_feat_mbw_part, &mpam_cfg->valid); + } else { + /* .. the number of fractions we can represent */ + mpam_cfg->mbw_max = resctrl_cfg; + + mpam_set_feature(mpam_feat_mbw_max, &mpam_cfg->valid); + } + } else { + /* + * Nothing clever here as mpam_resctrl_pick_caches() + * capped the size at RESCTRL_MAX_CBM. + */ + mpam_cfg->cpbm = resctrl_cfg; + mpam_set_feature(mpam_feat_cpor_part, &mpam_cfg->valid); + } +} + +static void +mpam_resctrl_update_component_cfg(struct resctrl_resource *r, + struct rdt_domain *d, struct list_head *opt_list, u32 partid) +{ + struct mpam_resctrl_dom *dom; + struct mpam_resctrl_res *res; + struct mpam_config *mpam_cfg; + u32 resctrl_cfg = d->ctrl_val[partid]; + + lockdep_assert_held(&resctrl_group_mutex); + + /* Out of range */ + if (partid >= mpam_sysprops_num_partid()) + return; + + res = container_of(r, struct mpam_resctrl_res, resctrl_res); + dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); + + mpam_cfg = &dom->comp->cfg[partid]; + if (WARN_ON_ONCE(!mpam_cfg)) + return; + + mpam_cfg->valid = 0; + if (partid != mpam_cfg->intpartid) { + mpam_cfg->intpartid = partid; + mpam_set_feature(mpam_feat_part_nrw, &mpam_cfg->valid); + } + + mpam_update_from_resctrl_cfg(res, resctrl_cfg, mpam_cfg); +} + +u16 mpam_resctrl_max_mon_num(void) +{ + struct mpam_resctrl_res *res; + u16 mon_num = USHRT_MAX; + struct raw_resctrl_resource *rr; + + if (max_mon_num) + return max_mon_num; + + for_each_supported_resctrl_exports(res) { + rr = res->resctrl_res.res; + mon_num = min(mon_num, rr->num_mon); + } + + if (mon_num == USHRT_MAX) + mon_num = 0; + + max_mon_num = mon_num; + + return mon_num; +} diff --git a/arch/arm64/kernel/mpam/mpam_setup.c b/arch/arm64/kernel/mpam/mpam_setup.c index 265e700cd7c0..4ad178c083ea 100644 --- a/arch/arm64/kernel/mpam/mpam_setup.c +++ b/arch/arm64/kernel/mpam/mpam_setup.c @@ -341,6 +341,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) r->fflags = RFTYPE_RES_MC; r->mbw.delay_linear = true; rr = mpam_get_raw_resctrl_resource(RDT_RESOURCE_MC); + rr->num_mon = class->num_mbwu_mon; r->res = rr;
if (mpam_has_feature(mpam_feat_mbw_part, class->features)) { @@ -385,6 +386,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) } else if (class == mpam_resctrl_exports[RDT_RESOURCE_L3].class) { r->rid = RDT_RESOURCE_L3; rr = mpam_get_raw_resctrl_resource(RDT_RESOURCE_L3); + rr->num_mon = class->num_csu_mon; r->res = rr; r->fflags = RFTYPE_RES_CACHE; r->name = "L3"; @@ -417,6 +419,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) } else if (class == mpam_resctrl_exports[RDT_RESOURCE_L2].class) { r->rid = RDT_RESOURCE_L2; rr = mpam_get_raw_resctrl_resource(RDT_RESOURCE_L2); + rr->num_mon = class->num_csu_mon; r->res = rr; r->fflags = RFTYPE_RES_CACHE; r->name = "L2"; @@ -489,3 +492,13 @@ int mpam_resctrl_setup(void)
return 0; } + +struct resctrl_resource * +mpam_resctrl_get_resource(enum resctrl_resource_level level) +{ + if (level >= RDT_NUM_RESOURCES || + !mpam_resctrl_exports[level].class) + return NULL; + + return &mpam_resctrl_exports[level].resctrl_res; +} diff --git a/fs/resctrlfs.c b/fs/resctrlfs.c index 9c48cd165ea4..7bd1f519d4b1 100644 --- a/fs/resctrlfs.c +++ b/fs/resctrlfs.c @@ -183,6 +183,9 @@ static int resctrl_group_create_info_dir(struct kernfs_node *parent_kn) unsigned long fflags; char name[32]; int ret; +#ifdef CONFIG_ARM64 + enum resctrl_resource_level level; +#endif
/* create the directory */ kn_info = kernfs_create_dir(parent_kn, "info", parent_kn->mode, NULL); @@ -194,7 +197,14 @@ static int resctrl_group_create_info_dir(struct kernfs_node *parent_kn) if (ret) goto out_destroy;
+#ifdef CONFIG_ARM64 + for (level = RDT_RESOURCE_SMMU; level < RDT_NUM_RESOURCES; level++) { + r = mpam_resctrl_get_resource(level); + if (!r) + continue; +#else for_each_resctrl_resource(r) { +#endif if (r->alloc_enabled) { fflags = r->fflags | RF_CTRL_INFO; ret = resctrl_group_mkdir_info_resdir(r, r->name, fflags); @@ -203,7 +213,14 @@ static int resctrl_group_create_info_dir(struct kernfs_node *parent_kn) } }
+#ifdef CONFIG_ARM64 + for (level = RDT_RESOURCE_SMMU; level < RDT_NUM_RESOURCES; level++) { + r = mpam_resctrl_get_resource(level); + if (!r) + continue; +#else for_each_resctrl_resource(r) { +#endif if (r->mon_enabled) { fflags = r->fflags | RF_MON_INFO; snprintf(name, sizeof(name), "%s_MON", r->name);