The Narrow PARTID feature allows the MPAM driver to statically or dynamically allocate request PARTIDs (reqPARTIDs) to internal PARTIDs (intPARTIDs). This enables expanding the number of monitoring groups beyond the hardware PMG limit. For systems with mixed MSCs (Memory System Components), MSCs that do not support narrow PARTID use PARTIDs exceeding the minimum number of intPARTIDs as reqPARTIDs to expand monitoring groups. Expand RMID to include reqPARTID information: rmid = reqPARTID * NUM_PMG + PMG To maintain compatibility with the existing resctrl layer, reqPARTIDs are allocated statically with a linear mapping to intPARTIDs via req2intpartid(). Mapping relationships (n = intPARTID count, m = reqPARTIDs per intPARTID): P - Partition group M - Monitoring group Group closid rmid.reqPARTID MSCs w/ narrow-PARTID MSCs w/o narrow-PARTID P1 0 intPARTID_1 PARTID_1 M1_1 0 0 ├── reqPARTID_1_1 ├── PARTID_1 M1_2 0 0+n ├── reqPARTID_1_2 ├── PARTID_1_2 M1_3 0 0+n*2 ├── reqPARTID_1_3 ├── PARTID_1_3 ... ├── ... ├── ... M1_m 0 0+n*(m-1) └── reqPARTID_1_m └── PARTID_1_m P2 1 intPARTID_2 PARTID_2 M2_1 1 1 ├── reqPARTID_2_1 ├── PARTID_2 M2_2 1 1+n ├── reqPARTID_2_2 ├── PARTID_2_2 M2_3 1 1+n*2 ├── reqPARTID_2_3 ├── PARTID_2_3 ... ├── ... ├── ... M2_m 1 1+n*(m-1) └── reqPARTID_2_m └── PARTID_2_m Pn n-1 intPARTID_n PARTID_n Mn_1 n-1 n-1 ├── reqPARTID_n_1 ├── PARTID_n Mn_2 n-1 n-1+n ├── reqPARTID_n_2 ├── PARTID_n_2 Mn_3 n-1 n-1+n*2 ├── reqPARTID_n_3 ├── PARTID_n_3 ... ├── ... ├── ... Mn_m n-1 n*m-1 └── reqPARTID_n_m └── PARTID_n_m Refactor the glue layer between resctrl abstractions (rmid) and MPAM hardware registers (reqPARTID/PMG) to support narrow PARTID. The resctrl layer uses rmid2reqpartid() and rmid2pmg() to extract components from rmid. The closid-to-intPARTID translation remains unchanged via resctrl_get_config_index(). Since narrow PARTID is a monitoring enhancement, reqPARTID is only used in monitoring paths while configuration paths maintain original semantics of closid. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/resctrl/mpam_resctrl.c | 101 +++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 30 deletions(-) diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c index 0245b16c4531..6cbca21096f7 100644 --- a/drivers/resctrl/mpam_resctrl.c +++ b/drivers/resctrl/mpam_resctrl.c @@ -281,15 +281,60 @@ u32 resctrl_arch_system_num_rmid_idx(void) return (mpam_pmg_max + 1) * get_num_reqpartid(); } +static u16 rmid2reqpartid(u32 rmid) +{ + rmid /= (mpam_pmg_max + 1); + + if (cdp_enabled) + return resctrl_get_config_index(rmid, CDP_DATA); + + return resctrl_get_config_index(rmid, CDP_NONE); +} + +static u8 rmid2pmg(u32 rmid) +{ + return rmid % (mpam_pmg_max + 1); +} + +static u16 req2intpartid(u16 reqpartid) +{ + return reqpartid % (mpam_intpartid_max + 1); +} + +/* + * To avoid the reuse of rmid across multiple control groups, check + * the incoming closid to prevent rmid from being reallocated by + * resctrl_find_free_rmid(). + * + * If the closid and rmid do not match upon inspection, immediately + * returns an invalid rmid. A valid rmid must not exceed 24 bits. + */ u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid) { - return closid * (mpam_pmg_max + 1) + rmid; + u32 reqpartid = rmid2reqpartid(rmid); + u32 intpartid = req2intpartid(reqpartid); + + if (cdp_enabled) + intpartid >>= 1; + + if (closid != intpartid) + return U32_MAX; + + return rmid; } void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid) { - *closid = idx / (mpam_pmg_max + 1); - *rmid = idx % (mpam_pmg_max + 1); + u32 reqpartid = rmid2reqpartid(idx); + u32 intpartid = req2intpartid(reqpartid); + + if (rmid) + *rmid = idx; + if (closid) { + if (cdp_enabled) + intpartid >>= 1; + *closid = intpartid; + } } void resctrl_arch_sched_in(struct task_struct *tsk) @@ -301,21 +346,17 @@ void resctrl_arch_sched_in(struct task_struct *tsk) void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid) { - WARN_ON_ONCE(closid > U16_MAX); - WARN_ON_ONCE(rmid > U8_MAX); + u32 reqpartid = rmid2reqpartid(rmid); + u8 pmg = rmid2pmg(rmid); - if (!cdp_enabled) { - mpam_set_cpu_defaults(cpu, closid, closid, rmid, rmid); - } else { + if (!cdp_enabled) + mpam_set_cpu_defaults(cpu, reqpartid, reqpartid, pmg, pmg); + else /* * When CDP is enabled, resctrl halves the closid range and we * use odd/even partid for one closid. */ - u32 partid_d = resctrl_get_config_index(closid, CDP_DATA); - u32 partid_i = resctrl_get_config_index(closid, CDP_CODE); - - mpam_set_cpu_defaults(cpu, partid_d, partid_i, rmid, rmid); - } + mpam_set_cpu_defaults(cpu, reqpartid, reqpartid + 1, pmg, pmg); } void resctrl_arch_sync_cpu_closid_rmid(void *info) @@ -334,17 +375,16 @@ void resctrl_arch_sync_cpu_closid_rmid(void *info) void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid) { - WARN_ON_ONCE(closid > U16_MAX); - WARN_ON_ONCE(rmid > U8_MAX); + u32 reqpartid = rmid2reqpartid(rmid); + u8 pmg = rmid2pmg(rmid); - if (!cdp_enabled) { - mpam_set_task_partid_pmg(tsk, closid, closid, rmid, rmid); - } else { - u32 partid_d = resctrl_get_config_index(closid, CDP_DATA); - u32 partid_i = resctrl_get_config_index(closid, CDP_CODE); + WARN_ON_ONCE(reqpartid > U16_MAX); + WARN_ON_ONCE(pmg > U8_MAX); - mpam_set_task_partid_pmg(tsk, partid_d, partid_i, rmid, rmid); - } + if (!cdp_enabled) + mpam_set_task_partid_pmg(tsk, reqpartid, reqpartid, pmg, pmg); + else + mpam_set_task_partid_pmg(tsk, reqpartid, reqpartid + 1, pmg, pmg); } bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid) @@ -352,6 +392,8 @@ bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid) u64 regval = mpam_get_regval(tsk); u32 tsk_closid = FIELD_GET(MPAM0_EL1_PARTID_D, regval); + tsk_closid = req2intpartid(tsk_closid); + if (cdp_enabled) tsk_closid >>= 1; @@ -362,13 +404,11 @@ bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid) bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid) { u64 regval = mpam_get_regval(tsk); - u32 tsk_closid = FIELD_GET(MPAM0_EL1_PARTID_D, regval); - u32 tsk_rmid = FIELD_GET(MPAM0_EL1_PMG_D, regval); - - if (cdp_enabled) - tsk_closid >>= 1; + u32 tsk_partid = FIELD_GET(MPAM0_EL1_PARTID_D, regval); + u32 tsk_pmg = FIELD_GET(MPAM0_EL1_PMG_D, regval); - return (tsk_closid == closid) && (tsk_rmid == rmid); + return (tsk_partid == rmid2reqpartid(rmid)) && + (tsk_pmg == rmid2pmg(rmid)); } struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l) @@ -456,6 +496,7 @@ static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_c enum resctrl_conf_type cdp_type, u32 closid, u32 rmid, u64 *val) { struct mon_cfg cfg; + u32 reqpartid = rmid2reqpartid(rmid); if (!mpam_is_enabled()) return -EINVAL; @@ -479,8 +520,8 @@ static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_c cfg = (struct mon_cfg) { .mon = mon_idx, .match_pmg = true, - .partid = closid, - .pmg = rmid, + .partid = (cdp_type == CDP_CODE) ? reqpartid + 1 : reqpartid, + .pmg = rmid2pmg(rmid), }; return mpam_msmon_read(mon_comp, &cfg, mon_type, val); -- 2.25.1