Replace static reqPARTID allocation with dynamic binding to maximize monitoring group utilization. Static allocation wastes resources when control groups create fewer sub-groups than the pre-allocated limit. Add a lookup table (reqpartid_map) to dynamically bind reqPARTIDs to control groups needing extended monitoring capacity: - resctrl_arch_rmid_expand(): Find and bind a free reqPARTID to the specified closid when creating monitoring groups. - resctrl_arch_rmid_reclaim(): Unbind reqPARTID when all monitoring groups associated with pmg are freed, making it available for reuse. Update conversion helpers for dynamic mapping: - req2intpartid(): Use lookup table for dynamic entries - Add partid2closid() and req_pmg2rmid() helpers Refactor __write_config() to iterate over all reqPARTIDs that match by intPARTID, removing fixed per-closid slot assumption. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/resctrl/mpam_devices.c | 21 ++--- drivers/resctrl/mpam_internal.h | 1 + drivers/resctrl/mpam_resctrl.c | 141 +++++++++++++++++++++++++++++--- include/linux/arm_mpam.h | 17 ++++ 4 files changed, 156 insertions(+), 24 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index 52533ee0e6ce..b05900f15f4f 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -1768,27 +1768,24 @@ struct mpam_write_config_arg { u16 partid; }; -static u32 get_num_reqpartid_per_intpartid(void) -{ - return (mpam_partid_max + 1) / (mpam_intpartid_max + 1); -} - static int __write_config(void *arg) { int closid_num = resctrl_arch_get_num_closid(NULL); struct mpam_write_config_arg *c = arg; - u32 reqpartid, req_idx; + u32 reqpartid; /* c->partid should be within the range of intPARTIDs */ WARN_ON_ONCE(c->partid >= closid_num); - /* Synchronize the configuration to each sub-monitoring group. */ - for (req_idx = 0; req_idx < get_num_reqpartid_per_intpartid(); - req_idx++) { - reqpartid = req_idx * closid_num + c->partid; + mpam_reprogram_ris_partid(c->ris, c->partid, + &c->comp->cfg[c->partid]); - mpam_reprogram_ris_partid(c->ris, reqpartid, - &c->comp->cfg[c->partid]); + /* Synchronize the configuration to each sub-monitoring group. */ + for (reqpartid = closid_num; + reqpartid < get_num_reqpartid(); reqpartid++) { + if (req2intpartid(reqpartid) == c->partid) + mpam_reprogram_ris_partid(c->ris, reqpartid, + &c->comp->cfg[c->partid]); } return 0; diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h index 013162faf37f..d03630e28be8 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -479,6 +479,7 @@ int mpam_get_cpumask_from_cache_id(unsigned long cache_id, u32 cache_level, cpumask_t *affinity); u16 req2intpartid(u16 reqpartid); +u32 get_num_reqpartid(void); #ifdef CONFIG_RESCTRL_FS int mpam_resctrl_setup(void); diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c index bb2fdfc03b75..a3f027ad322c 100644 --- a/drivers/resctrl/mpam_resctrl.c +++ b/drivers/resctrl/mpam_resctrl.c @@ -251,7 +251,7 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored) * The first call occurs in mpam_resctrl_pick_counters(), ensuring the * prerequisite initialization is complete. */ -static u32 get_num_reqpartid(void) +u32 get_num_reqpartid(void) { struct mpam_resctrl_res *res; struct rdt_resource *r_mba; @@ -296,9 +296,36 @@ static u8 rmid2pmg(u32 rmid) return rmid % (mpam_pmg_max + 1); } +static u32 req_pmg2rmid(u32 reqpartid, u8 pmg) +{ + if (cdp_enabled) + reqpartid >>= 1; + + return reqpartid * (mpam_pmg_max + 1) + pmg; +} + +static u32 *reqpartid_map; + u16 req2intpartid(u16 reqpartid) { - return reqpartid % (mpam_intpartid_max + 1); + WARN_ON_ONCE(reqpartid >= get_num_reqpartid()); + + /* + * Directly return intPartid in case that mpam_reset_ris() access + * NULL pointer. + */ + if (reqpartid < (mpam_intpartid_max + 1)) + return reqpartid; + + return reqpartid_map[reqpartid]; +} + +static u32 partid2closid(u32 partid) +{ + if (cdp_enabled) + partid >>= 1; + + return partid; } /* @@ -312,12 +339,12 @@ u16 req2intpartid(u16 reqpartid) u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid) { u32 reqpartid = rmid2reqpartid(rmid); - u32 intpartid = req2intpartid(reqpartid); - if (cdp_enabled) - intpartid >>= 1; + /* When enable CDP mode, needs to filter invalid rmid entry out */ + if (reqpartid >= get_num_reqpartid()) + return U32_MAX; - if (closid != intpartid) + if (closid != partid2closid(req2intpartid(reqpartid))) return U32_MAX; return rmid; @@ -330,11 +357,9 @@ void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid) if (rmid) *rmid = idx; - if (closid) { - if (cdp_enabled) - intpartid >>= 1; - *closid = intpartid; - } + + if (closid) + *closid = partid2closid(intpartid); } void resctrl_arch_sched_in(struct task_struct *tsk) @@ -1822,6 +1847,91 @@ void mpam_resctrl_offline_cpu(unsigned int cpu) } } +static int reqpartid_init(void) +{ + int req_num, idx; + + req_num = get_num_reqpartid(); + reqpartid_map = kcalloc(req_num, sizeof(u32), GFP_KERNEL); + if (!reqpartid_map) + return -ENOMEM; + + for (idx = 0; idx < req_num; idx++) + reqpartid_map[idx] = idx; + + return 0; +} + +static void reqpartid_exit(void) +{ + kfree(reqpartid_map); +} + +static void update_rmid_entries_for_reqpartid(u32 reqpartid) +{ + int pmg; + u32 intpartid = reqpartid_map[reqpartid]; + u32 closid = partid2closid(intpartid); + + for (pmg = 0; pmg <= mpam_pmg_max; pmg++) + rmid_entry_reassign_closid(closid, req_pmg2rmid(reqpartid, pmg)); +} + +int resctrl_arch_rmid_expand(u32 closid) +{ + int i; + + for (i = resctrl_arch_get_num_closid(NULL); + i < get_num_reqpartid(); i++) { + /* + * If reqpartid_map[i] > mpam_intpartid_max, + * it means the reqpartid 'i' is free. + */ + if (reqpartid_map[i] >= resctrl_arch_get_num_closid(NULL)) { + if (cdp_enabled) { + reqpartid_map[i] = resctrl_get_config_index(closid, CDP_DATA); + reqpartid_map[i + 1] = resctrl_get_config_index(closid, CDP_CODE); + } else { + reqpartid_map[i] = resctrl_get_config_index(closid, CDP_NONE); + } + update_rmid_entries_for_reqpartid(i); + return i; + } + } + + return -ENOSPC; +} + +void resctrl_arch_rmid_reclaim(u32 closid, u32 rmid) +{ + int pmg; + u32 intpartid; + int reqpartid = rmid2reqpartid(rmid); + + if (reqpartid < resctrl_arch_get_num_closid(NULL)) + return; + + if (cdp_enabled) + intpartid = resctrl_get_config_index(closid, CDP_DATA); + else + intpartid = resctrl_get_config_index(closid, CDP_NONE); + + WARN_ON_ONCE(intpartid != req2intpartid(reqpartid)); + + for (pmg = 0; pmg <= mpam_pmg_max; pmg++) { + if (rmid_is_occupied(closid, req_pmg2rmid(reqpartid, pmg))) + break; + } + + if (pmg > mpam_pmg_max) { + reqpartid_map[reqpartid] = reqpartid; + if (cdp_enabled) + reqpartid_map[reqpartid + 1] = reqpartid + 1; + + update_rmid_entries_for_reqpartid(reqpartid); + } +} + int mpam_resctrl_setup(void) { int err = 0; @@ -1877,10 +1987,16 @@ int mpam_resctrl_setup(void) return -EOPNOTSUPP; } - err = resctrl_init(); + err = reqpartid_init(); if (err) return err; + err = resctrl_init(); + if (err) { + reqpartid_exit(); + return err; + } + WRITE_ONCE(resctrl_enabled, true); return 0; @@ -1898,6 +2014,7 @@ void mpam_resctrl_exit(void) WRITE_ONCE(resctrl_enabled, false); resctrl_exit(); + reqpartid_exit(); } static void mpam_resctrl_teardown_mon(struct mpam_resctrl_mon *mon, struct mpam_class *class) diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index f92a36187a52..d45422965907 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -59,6 +59,23 @@ void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid); void resctrl_arch_sched_in(struct task_struct *tsk); bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid); bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid); + +/** + * resctrl_arch_rmid_expand() - Expand the RMID resources for the specified closid. + * @closid: closid that matches the rmid. + * + * Return: + * 0 on success, or -ENOSPC etc on error. + */ +int resctrl_arch_rmid_expand(u32 closid); + +/** + * resctrl_arch_rmid_reclaim() - Reclaim the rmid resources for the specified closid. + * @closid: closid that matches the rmid. + * @rmid: Reclaim the rmid specified. + */ +void resctrl_arch_rmid_reclaim(u32 closid, u32 rmid); + u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid); void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid); u32 resctrl_arch_system_num_rmid_idx(void); -- 2.25.1