diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h index a70133fff4505df9c1a3628b1252340853ad8cde..5aef534fb3df8f6a3dcf83275ecdbd3a088374df 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 d0d30a0fdc1dd2284fb199e2e4c6960be8fede9f..2119204fa090e761f59de6f46cbd7021d7da8e53 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 0d4ba3afe419611b0e276c9775df2525016ed458..39c5020cdfa6f6ff4449ae74f4773bd145d6eb75 100644 --- a/arch/arm64/kernel/mpam/mpam_ctrlmon.c +++ b/arch/arm64/kernel/mpam/mpam_ctrlmon.c @@ -38,6 +38,7 @@ #include #include #include +#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 ea8be8c861c0a7c6865cbae7895eeb64969559aa..8ab019fd8938dfe11b2bfc3f2462937059a2b260 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 81dddf5432b5ea82fb2e512143d1ee493ec4b4ed..f952e9aa20c2eeec5eeec18f5173ef83255a39b5 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 d4870e33c3bdb07c73062f14701345a31af1d59d..8fd5c84f28bd6245b6b77964eee3efbba1b2c06b 100644 --- a/arch/arm64/kernel/mpam/mpam_resctrl.c +++ b/arch/arm64/kernel/mpam/mpam_resctrl.c @@ -45,6 +45,7 @@ #include #include +#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 265e700cd7c05970c5391910f62ca955cff66c61..4ad178c083eaa5067ed0a45d55c9503f003a7cdd 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 9c48cd165ea45b97a6b19188687c70f983c5b686..7bd1f519d4b1859cba173adcb7ef2626c6d599a2 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);