hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/9840 ------------------ 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 << shift | 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> --- arch/arm64/include/asm/mpam.h | 17 +-- drivers/platform/mpam/mpam_resctrl.c | 160 ++++++++++++++++----------- include/linux/arm_mpam.h | 2 +- 3 files changed, 105 insertions(+), 74 deletions(-) diff --git a/arch/arm64/include/asm/mpam.h b/arch/arm64/include/asm/mpam.h index 5f1ac30ea4702..4d0a66013e3ff 100644 --- a/arch/arm64/include/asm/mpam.h +++ b/arch/arm64/include/asm/mpam.h @@ -129,18 +129,13 @@ static inline u64 mpam_get_regval(struct task_struct *tsk) #endif } -static inline void resctrl_arch_set_rmid(struct task_struct *tsk, u32 rmid) -{ -#ifdef CONFIG_ARM64_MPAM - u64 regval = mpam_get_regval(tsk); +u32 req2intpartid(u32 reqpartid); - regval &= ~MPAM_SYSREG_PMG_D; - regval &= ~MPAM_SYSREG_PMG_I; - regval |= FIELD_PREP(MPAM_SYSREG_PMG_D, rmid); - regval |= FIELD_PREP(MPAM_SYSREG_PMG_I, rmid); +static inline u32 mpam_get_regval_partid(u64 regval) +{ + u32 reqpartid = (regval & MPAM_SYSREG_PARTID_D) >> 16; - WRITE_ONCE(task_thread_info(tsk)->mpam_partid_pmg, regval); -#endif + return req2intpartid(reqpartid); } static inline void mpam_thread_switch(struct task_struct *tsk) @@ -153,7 +148,7 @@ static inline void mpam_thread_switch(struct task_struct *tsk) !static_branch_likely(&mpam_enabled)) return; - if (!regval) + if (!regval || !mpam_get_regval_partid(regval)) regval = READ_ONCE(per_cpu(arm64_mpam_default, cpu)); oldregval = READ_ONCE(per_cpu(arm64_mpam_current, cpu)); diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 6d6f328a7f716..a2b0267502ef9 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -164,24 +164,73 @@ u32 resctrl_arch_system_num_rmid_idx(void) return num_reqpartid << closid_shift; } +static u32 rmid2reqpartid(u32 rmid) +{ + u8 pmg_shift = fls(mpam_pmg_max); + u32 reqpartid; + + WARN_ON_ONCE(pmg_shift > 8); + + rmid >>= pmg_shift; + + if (cdp_enabled) + reqpartid = resctrl_get_config_index(rmid, CDP_DATA); + else + reqpartid = resctrl_get_config_index(rmid, CDP_NONE); + + return reqpartid; +} + +static u8 rmid2pmg(u32 rmid) +{ + u8 pmg_shift = fls(mpam_pmg_max); + u32 pmg_mask = ~(~0 << pmg_shift); + + return rmid & pmg_mask; +} + +u32 req2intpartid(u32 reqpartid) +{ + u8 intpartid_shift = fls(mpam_intpartid_max); + u32 intpartid_mask = ~(~0 << intpartid_shift); + + return reqpartid & intpartid_mask; +} + +/* + * 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) { - u8 closid_shift = fls(mpam_pmg_max); + u32 reqpartid = rmid2reqpartid(rmid); + u32 intpartid = req2intpartid(reqpartid); + + if (cdp_enabled) + intpartid >>= 1; - BUG_ON(closid_shift > 8); + if (closid != intpartid) + return U32_MAX; - return (closid << closid_shift) | rmid; + return rmid; } void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid) { - u8 closid_shift = fls(mpam_pmg_max); - u32 pmg_mask = ~(~0 << closid_shift); - - BUG_ON(closid_shift > 8); + u32 reqpartid = rmid2reqpartid(idx); + u32 intpartid = req2intpartid(reqpartid); - *closid = idx >> closid_shift; - *rmid = idx & pmg_mask; + if (rmid) + *rmid = idx; + if (closid) { + if (cdp_enabled) + intpartid >>= 1; + *closid = intpartid; + } } void resctrl_sched_in(struct task_struct *tsk) @@ -191,23 +240,22 @@ void resctrl_sched_in(struct task_struct *tsk) mpam_thread_switch(tsk); } -void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 pmg) +void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid) { - BUG_ON(closid > U16_MAX); - BUG_ON(pmg > U8_MAX); + u32 reqpartid = rmid2reqpartid(rmid); + u8 pmg = rmid2pmg(rmid); - if (!cdp_enabled) { - mpam_set_cpu_defaults(cpu, closid, closid, pmg, pmg); - } else { + WARN_ON_ONCE(reqpartid > U16_MAX); + WARN_ON_ONCE(pmg > U8_MAX); + + 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, pmg, pmg); - } + mpam_set_cpu_defaults(cpu, reqpartid, reqpartid + 1, pmg, pmg); } void resctrl_arch_sync_cpu_defaults(void *info) @@ -226,43 +274,40 @@ void resctrl_arch_sync_cpu_defaults(void *info) void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid) { + u32 reqpartid = rmid2reqpartid(rmid); + u8 pmg = rmid2pmg(rmid); + WARN_ON_ONCE(reqpartid > U16_MAX); + WARN_ON_ONCE(pmg > U8_MAX); - BUG_ON(closid > U16_MAX); - BUG_ON(rmid > U8_MAX); - - 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); - - 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) { u64 regval = mpam_get_regval(tsk); - u32 tsk_closid = FIELD_GET(MPAM_SYSREG_PARTID_D, regval); + u32 tsk_partid = FIELD_GET(MPAM1_EL1_PARTID_D, regval); + + tsk_partid = req2intpartid(tsk_partid); if (cdp_enabled) - tsk_closid >>= 1; + tsk_partid >>= 1; - return tsk_closid == closid; + return tsk_partid == closid; } /* The task's pmg is not unique, the partid must be considered too */ bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid) { u64 regval = mpam_get_regval(tsk); - u32 tsk_closid = FIELD_GET(MPAM_SYSREG_PARTID_D, regval); - u32 tsk_rmid = FIELD_GET(MPAM_SYSREG_PMG_D, regval); - - if (cdp_enabled) - tsk_closid >>= 1; + u32 tsk_partid = FIELD_GET(MPAM1_EL1_PARTID_D, regval); + u32 tsk_pmg = FIELD_GET(MPAM1_EL1_PMG_D, regval); - return (tsk_closid == closid) && (tsk_rmid == rmid); + return (tsk_partid == rmid2reqpartid(rmid)) && + (tsk_pmg == rmid2pmg(rmid)); } #ifdef CONFIG_RESCTRL_IOMMU @@ -389,29 +434,24 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d, num_mon = res->class->props.num_csu_mon; cfg.match_pmg = true; - cfg.pmg = rmid; + cfg.pmg = rmid2pmg(rmid); cfg.opts = resctrl_evt_config_to_mpam(dom->mbm_local_evt_cfg); + cfg.partid = rmid2reqpartid(rmid); - if (cdp_enabled) { - cfg.partid = resctrl_get_config_index(closid, CDP_DATA); - cfg.mon = cfg.partid % num_mon; - err = mpam_msmon_read(dom->comp, &cfg, type, val); - if (err) - return err; + cfg.mon = cfg.partid % num_mon; + err = mpam_msmon_read(dom->comp, &cfg, type, val); + if (err) + return err; - cfg.partid = resctrl_get_config_index(closid, CDP_CODE); + if (cdp_enabled) { + cfg.partid += 1; cfg.mon = cfg.partid % num_mon; err = mpam_msmon_read(dom->comp, &cfg, type, &cdp_val); if (!err) { - pr_debug("read monitor rmid %u %s:%u CODE/DATA: %lld/%lld\n", - resctrl_arch_rmid_idx_encode(closid, rmid), - r->name, dom->comp->comp_id, cdp_val, *val); + pr_debug("read monitor closid %u rmid %u %s:%u CODE/DATA: %lld/%lld\n", + closid, rmid, r->name, dom->comp->comp_id, cdp_val, *val); *val += cdp_val; } - } else { - cfg.partid = closid; - cfg.mon = cfg.partid % num_mon; - err = mpam_msmon_read(dom->comp, &cfg, type, val); } return err; @@ -433,19 +473,15 @@ void resctrl_arch_reset_rmid(struct rdt_resource *r, struct rdt_domain *d, num_mbwu_mon = res->class->props.num_mbwu_mon; cfg.mon = resctrl_arch_rmid_idx_encode(closid, rmid) % num_mbwu_mon; cfg.match_pmg = true; - cfg.pmg = rmid; + cfg.pmg = rmid2pmg(rmid); + cfg.partid = rmid2reqpartid(rmid); dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); + mpam_msmon_reset_mbwu(dom->comp, &cfg); if (cdp_enabled) { - cfg.partid = closid << 1; - mpam_msmon_reset_mbwu(dom->comp, &cfg); - cfg.partid += 1; mpam_msmon_reset_mbwu(dom->comp, &cfg); - } else { - cfg.partid = closid; - mpam_msmon_reset_mbwu(dom->comp, &cfg); } } diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index 5d60e1c6ca6c5..541c2f1bf6f4c 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -79,7 +79,7 @@ bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid); bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid); void resctrl_arch_set_cpu_default_closid(int cpu, u32 closid); void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid); -void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 pmg); +void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid); void resctrl_sched_in(struct task_struct *tsk); u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid); void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid); -- 2.43.0