hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9840 ------------------ MPAM supports heterogeneous systems where some type of MSCs may implement Narrow-PARTID while others do not. However, when an MSC uses percentage-based throttling (non-bitmap partition control) and lacks Narrow-PARTID support, resctrl cannot correctly apply control group configurations across multiple PARTIDs. To enable free assignment of multiple reqPARTIDs to resource control groups, all MSCs used by resctrl must either: Implement Narrow-PARTID, allowing explicit PARTID remapping, or only have stateless resource controls (non-percentage-based), such that splitting a control group across multiple PARTIDs does not affect behavior. The detection occurs at initialization time on the first call to get_num_reqpartid() from update_rmid_limits(). This call is guaranteed to occur after mpam_resctrl_pick_{mba,caches}() have set up the resource classes, ensuring the necessary properties are available for the Narrow-PARTID capability check. When an MSC with percentage-based control lacks Narrow-PARTID support, get_num_reqpartid() falls back to returning the number of intPARTIDs, effectively disabling the reqPARTID expansion for monitoring groups. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 75 +++++++++++++++++++++------- 1 file changed, 56 insertions(+), 19 deletions(-) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index ad8ed64af4153..e3fd8361c22d9 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -151,17 +151,46 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored) return mpam_intpartid_max + 1; } +/* + * Determine the effective number of PARTIDs available for resctrl. + * + * This function performs a one-time check to determine if Narrow-PARTID + * can be used. It must be called after mpam_resctrl_pick_{mba,caches}() + * have initialized the resource classes, as class properties are used + * to detect Narrow-PARTID support. + * + * The first call occurs in update_rmid_limits(), ensuring the + * prerequisite initialization is complete. + */ u32 get_num_reqpartid(void) { + struct mpam_props *cprops; + struct mpam_class *class; + static bool first = true; + + if (first) { + list_for_each_entry_rcu(class, &mpam_classes, classes_list) { + cprops = &class->props; + if (mpam_has_feature(mpam_feat_partid_nrw, cprops)) + continue; + + if (mpam_has_feature(mpam_feat_mbw_max, cprops) || + mpam_has_feature(mpam_feat_mbw_min, cprops) || + mpam_has_feature(mpam_feat_ccap_part, cprops) || + mpam_has_feature(mpam_feat_cmin, cprops)) { + mpam_partid_max = mpam_intpartid_max; + break; + } + } + } + + first = false; return mpam_partid_max + 1; } u32 resctrl_arch_system_num_rmid_idx(void) { - u8 closid_shift = fls(mpam_pmg_max); - u32 num_reqpartid = get_num_reqpartid(); - - return num_reqpartid << closid_shift; + return (mpam_pmg_max + 1) * get_num_reqpartid(); } static u32 rmid2reqpartid(u32 rmid) @@ -512,9 +541,13 @@ void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_domain *d, * The rmid realloc threshold should be for the smallest cache exposed to * resctrl. */ -static void update_rmid_limits(unsigned int size) +static void update_rmid_limits(struct mpam_class *class) { u32 num_unique_pmg = resctrl_arch_system_num_rmid_idx(); + unsigned int size; + + /* Assume cache levels are the same size for all CPUs... */ + size = get_cpu_cacheinfo_size(smp_processor_id(), class->level); if (WARN_ON_ONCE(!size)) return; @@ -773,7 +806,6 @@ static u16 ca_max_to_percent(u16 ca_max, u8 wd) static void mpam_resctrl_pick_caches(void) { int idx; - unsigned int cache_size; struct mpam_class *class; struct mpam_resctrl_res *res; bool has_cpor, has_cmax, has_cmin, has_intpri; @@ -813,18 +845,6 @@ static void mpam_resctrl_pick_caches(void) continue; } - /* Assume cache levels are the same size for all CPUs... */ - cache_size = get_cpu_cacheinfo_size(smp_processor_id(), class->level); - if (!cache_size) { - pr_debug("pick_caches: Could not read cache size\n"); - continue; - } - - if (mpam_has_feature(mpam_feat_msmon_csu, cprops)) { - if (class->level == 3) - update_rmid_limits(cache_size); - } - if (has_cpor) { if (class->level == 2) { res = &mpam_resctrl_exports[RDT_RESOURCE_L2]; @@ -923,6 +943,23 @@ static void mpam_resctrl_pick_mba(void) srcu_read_unlock(&mpam_srcu, idx); } +static void mpam_resctrl_pick_counters(void) +{ + struct mpam_class *class; + int idx; + + idx = srcu_read_lock(&mpam_srcu); + + list_for_each_entry_rcu(class, &mpam_classes, classes_list) { + if (mpam_has_feature(mpam_feat_msmon_csu, &class->props)) { + if (class->level == 3) + update_rmid_limits(class); + } + } + + srcu_read_unlock(&mpam_srcu, idx); +} + bool resctrl_arch_is_evt_configurable(enum resctrl_event_id evt) { struct mpam_props *cprops; @@ -1331,7 +1368,7 @@ int mpam_resctrl_setup(void) mpam_resctrl_pick_caches(); mpam_resctrl_pick_mba(); - /* TODO: mpam_resctrl_pick_counters(); */ + mpam_resctrl_pick_counters(); for (i = 0; i < RDT_NUM_RESOURCES; i++) { res = &mpam_resctrl_exports[i]; -- 2.43.0