[PATCH OLK-6.6 00/12] arm_mpam: Introduce the Narrow-PARTID feature for MPAM driver
The narrow-partid feature in MPAM allows for a more efficient use of PARTIDs by enabling a many-to-one mapping of reqpartids (requested PARTIDs) to intpartids (internal PARTIDs). This mapping reduces the number of unique PARTIDs needed, thus allowing more tasks or processes to be monitored and managed with the available resources. For a mixture of MSCs system, for MSCs that do not support narrow-partid, we use the PARTIDs exceeding the number of closids as reqPARTIDs for expanding the monitoring groups. Therefore, we will expand the information contained in the RMID, so that it includes not only PMG, but also reqPARTIDs information. The new RMID would be like: RMID = (reqPARTID << shift | PMG). Each control group has m (req)PARTIDs, which are used to expand the number of monitoring groups under one control group. Therefore, the number of monitoring groups is no longer limited by the range of MPAM's PMG, which enhances the extensibility of the system's monitoring capabilities. Dave Martin (1): arm_mpam: Set INTERNAL as needed when setting MSC controls Zeng Heng (11): arm_mpam: Introduce the definitions of intPARTID and reqPARTID arm_mpam: Expand the composition of RMID arm_mpam: Automatically synchronize the configuration of all sub-monitoring groups fs/resctrl: Implementing the dynamic allocation of reqPARTIDs fs/resctrl: Deploy resctrl_arch_expand_rmid() arm64/mpam: Add limitation for the Narrow-PARTID feature fs/resctrl: Fix limit of root group Revert "fs/resctrl: Fix configuration to wrong control group when CDP is enabled" arm64/mpam: Fix rdtgroup_init_res() arm64/mpam: Add mpam_sync_config() fs/resctrl: rdt_destroy_limbo() after umount arch/x86/include/asm/resctrl.h | 11 +- drivers/platform/mpam/mpam_devices.c | 86 ++++- drivers/platform/mpam/mpam_internal.h | 7 +- drivers/platform/mpam/mpam_resctrl.c | 454 +++++++++++++++++++++----- fs/resctrl/ctrlmondata.c | 28 +- fs/resctrl/monitor.c | 50 ++- fs/resctrl/rdtgroup.c | 38 ++- include/linux/arm_mpam.h | 17 +- include/linux/resctrl.h | 18 + 9 files changed, 569 insertions(+), 140 deletions(-) -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ The narrow-partid feature in MPAM allows for a more efficient use of PARTIDs by enabling a many-to-one mapping of reqpartids (requested PARTIDs) to intpartids (internal PARTIDs). This mapping reduces the number of unique PARTIDs needed, thus allowing more tasks or processes to be monitored and managed with the available resources. Regarding intPARTID, MPAM uses it as the unit for control group configuration delivery. MPAM will synchronize the delivered configuration to all reqPARTIDs mapped to the same intPARTIDs. The number of intPARTIDs is indicated by MPAMF_PARTID_NRW_IDR.INTPARTID_MAX if implemented, or directly use the number of PARTID as intpartid_max if narrow-partid feature is not supported. reqPARTIDs can be used to expand the number of monitors, for each control group is no longer simply restricted by the range of PMG. By mapping between intPARTID and reqPARTID, the number of monitors would be greatly expanded and more fine-grained monitoring under a control group will be achieved. As a MPAM driver applicable to general scenarios, it needs to be compatible with systems not supporting narrow-partid and mixed MSCs (some MSCs support narrow-partid and some do not) systems. We determine the number of closids in the following manner: reqPARTID-np -- The number of reqPARTIDs supported by MSCs that support narrow-partid. intPARTID-np -- The number of intPARTIDs supported by MSCs that support narrow partid. PARTID -- The number of PARTIDs supported by MSCs that do not support narrow partid. n - Indicates the maximum number of control groups l - Represents the total number of reqpartids m - Indicates the number of reqpartids per control group n = min(intPARTID-np, PARTID) l = min(reqPARTID-np, PARTID) m = l // n To illustrate how to determine n, l, and m through examples, we can assume a specific example: l3 - Does not support the narrow PARTID feature, supports a range of 256 PARTIDs. mata - Supports the narrow-partid feature, supports 32 intPARTIDs, and supports 256 reqPARTIDs. Then, n = min(PARTID-l3, intPARTID-mata) = min(256, 32) = 32 l = min(PARTID-l3, reqPARTID-mata) = min(256,256) = 256 m = 256 / 32 = 8 After initialization, the driver determines the 'n' parameter returned by resctrl_arch_get_num_closid() and the 'l' parameter returned by get_num_reqpartid(). Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 12 +++++++++++- drivers/platform/mpam/mpam_internal.h | 2 ++ drivers/platform/mpam/mpam_resctrl.c | 9 +++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index 6c1c82f79ec0..42d1e5bbe810 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -56,6 +56,7 @@ static DEFINE_MUTEX(mpam_cpuhp_state_lock); * Generating traffic outside this range will result in screaming interrupts. */ u16 mpam_partid_max; +u16 mpam_intpartid_max; u8 mpam_pmg_max; static bool partid_max_init, partid_max_published; static DEFINE_SPINLOCK(partid_max_lock); @@ -201,10 +202,16 @@ int mpam_register_requestor(u16 partid_max, u8 pmg_max) spin_lock(&partid_max_lock); if (!partid_max_init) { mpam_partid_max = partid_max; + /* + * Update mpam_intpartid_max here, in case the + * system doesn't have narrow-partid feature. + */ + mpam_intpartid_max = partid_max; mpam_pmg_max = pmg_max; partid_max_init = true; } else if (!partid_max_published) { mpam_partid_max = min(mpam_partid_max, partid_max); + mpam_intpartid_max = min(mpam_intpartid_max, partid_max); mpam_pmg_max = min(mpam_pmg_max, pmg_max); } else { /* New requestors can't lower the values */ @@ -741,7 +748,9 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) u16 partid_max = FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr); mpam_set_feature(mpam_feat_partid_nrw, props); - msc->partid_max = min(msc->partid_max, partid_max); + msc->intpartid_max = min(msc->partid_max, partid_max); + } else { + msc->intpartid_max = msc->partid_max; } } @@ -806,6 +815,7 @@ static int mpam_msc_hw_probe(struct mpam_msc *msc) spin_lock(&partid_max_lock); mpam_partid_max = min(mpam_partid_max, msc->partid_max); + mpam_intpartid_max = min(mpam_intpartid_max, msc->intpartid_max); mpam_pmg_max = min(mpam_pmg_max, msc->pmg_max); spin_unlock(&partid_max_lock); diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index 5f60e0cc4eeb..e4809f2242ec 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -58,6 +58,7 @@ struct mpam_msc bool error_irq_requested; bool error_irq_hw_enabled; u16 partid_max; + u16 intpartid_max; u8 pmg_max; unsigned long ris_idxs[128 / BITS_PER_LONG]; u32 ris_max; @@ -303,6 +304,7 @@ extern struct srcu_struct mpam_srcu; /* System wide partid/pmg values */ extern u16 mpam_partid_max; +extern u16 mpam_intpartid_max; extern u8 mpam_pmg_max; /* Scheduled work callback to enable mpam once all MSC have been probed */ diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 8ee0857f9a93..ae0bb95aa97a 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -147,6 +147,11 @@ bool resctrl_arch_hide_cdp(enum resctrl_res_level rid) * only the system wide safe value is safe to use. */ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored) +{ + return mpam_intpartid_max + 1; +} + +static u32 get_num_reqpartid(void) { return mpam_partid_max + 1; } @@ -154,9 +159,9 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored) u32 resctrl_arch_system_num_rmid_idx(void) { u8 closid_shift = fls(mpam_pmg_max); - u32 num_partid = resctrl_arch_get_num_closid(NULL); + u32 num_reqpartid = get_num_reqpartid(); - return num_partid << closid_shift; + return num_reqpartid << closid_shift; } u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid) -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ The Narrow Partid feature supports for the MPAM driver statically or dynamically allocates all reqPARTIDs to various intPARTIDs. The new RMID allocation strategy will check whether there are available reqPARTIDs for the incoming closid, rather than simply checking for available PMGs. For a mixture of MSCs system, for MSCs that do not support narrow-partid, we use the PARTIDs exceeding the number of closids as reqPARTIDs for expanding the monitoring groups. Therefore, we will expand the information contained in the RMID, so that it includes not only PMG, but also reqPARTIDs information. The new RMID would be like: RMID = (reqPARTID << shift | PMG). In order to keep the existing resctrl layer interfaces, the reqPARTIDs are allocated statically. Here req2intpartid() linearly binds each reqPARTID to the corresponding intPARTID. If reqPARTID needs to support dynamic allocation in the future, then simply rewrite req2intpartid() and can be replaced with a table-lookup approach. The static mapping relationships between each group's closid/rmid and the respective MSCs' intPARTID/reqPARTID/PARTID are illustrated: n - Indicates the total number of intPARTIDs m - Indicates the number of reqPARTIDs per intPARTID P - Partition group M - Monitoring group Group closid rmid.reqPARTID MSCs with narrow-partid MSCs without 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-1)+n*(m-1) = n*m-1 └── reqPARTID_n_m └── PARTID_n_m The resctrl layer uses the new conversion functions rmid2reqpartid() and rmid2pmg() respectively to gain the new reqPARTID/PMG pair by RMID. And still, the translation between closid and intPARTID follows the original conversion logic of closid: intPARTID = resctrl_get_config_index(closid, resctrl_conf_type). It can be noted that the approach of allocating the first n IDs to intPARTIDs keeps the existing conversion between closid and intPARTID. We still use the resctrl_get_config_index() for conversion, maintaining the original semantics during the MPAM configuration updating. Essentially, the narrowing feature is an enhanced monitoring feature, we only expand the definition of rmid, while reqPARTID is only used in monitoring-related processes. Now each control group has m (req)PARTIDs, which are used to expand the number of monitoring groups under one control group. Therefore, the number of monitoring groups is no longer limited by the range of MPAM's PMG, which enhances the extensibility of the system's monitoring capabilities. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 152 ++++++++++++++++----------- 1 file changed, 90 insertions(+), 62 deletions(-) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index ae0bb95aa97a..7abbb6fa8850 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -164,24 +164,65 @@ 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); + + WARN_ON_ONCE(pmg_shift > 8); + + return rmid >> pmg_shift; +} + +static u32 rmid2pmg(u32 rmid) +{ + u8 pmg_shift = fls(mpam_pmg_max); + u32 pmg_mask = ~(~0 << pmg_shift); + + return rmid & pmg_mask; +} + +static 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 +232,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); + u32 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 +266,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); + u32 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); + u32 tsk_partid = FIELD_GET(MPAM1_EL1_PARTID_D, regval); + u32 tsk_pmg = FIELD_GET(MPAM1_EL1_PMG_D, regval); - if (cdp_enabled) - tsk_closid >>= 1; - - return (tsk_closid == closid) && (tsk_rmid == rmid); + return (tsk_partid == rmid2reqpartid(rmid)) && + (tsk_pmg == rmid2pmg(rmid)); } #ifdef CONFIG_RESCTRL_IOMMU @@ -408,29 +445,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; @@ -452,19 +484,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); } } -- 2.25.1
From: Dave Martin <Dave.Martin@arm.com> hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ Currently, when an MSC implements PARTID narrowing, MPAMCFG_PART_SEL is left set to the reqPARTID while programming resource controls in an MSC. The MPAM architecture does not guarantee that any particular resource controls will be updated correctly in this scenario. Instead, MPAMCFG_PART_SEL must be written with the corresponding intPARTID and with the INTERNAL bit set before attempting to program resource controls. Only the PARTID->intPARTID mappings can be written without the INTERNAL bit set in MPAMCFG_PART_SEL. Fix it, by rewriting MPAMCFG_PART_SEL appropriately after setting the intPARTID mapping. The MPAMCFG_INTPARTID_INTERNAL flag is not currently accepted as input to the __mpam_part_sel() helper. In the interest of keeping the code clean, break this helper up. Signed-off-by: Dave Martin <Dave.Martin@arm.com> Signed-off-by: James Morse <james.morse@arm.com> --- drivers/platform/mpam/mpam_devices.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index 42d1e5bbe810..a190be18fff8 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -184,15 +184,27 @@ static u64 mpam_msc_read_esr(struct mpam_msc *msc) return (esr_high << 32) | esr_low; } +static void __mpam_part_sel_raw(u32 partsel, struct mpam_msc *msc) +{ + lockdep_assert_held(&msc->part_sel_lock); + mpam_write_partsel_reg(msc, PART_SEL, partsel); +} + static void __mpam_part_sel(u8 ris_idx, u16 partid, struct mpam_msc *msc) { - u32 partsel; + u32 partsel = FIELD_PREP(MPAMCFG_PART_SEL_RIS, ris_idx) | + FIELD_PREP(MPAMCFG_PART_SEL_PARTID_SEL, partid); - lockdep_assert_held(&msc->part_sel_lock); + __mpam_part_sel_raw(partsel, msc); +} - partsel = FIELD_PREP(MPAMCFG_PART_SEL_RIS, ris_idx) | - FIELD_PREP(MPAMCFG_PART_SEL_PARTID_SEL, partid); - mpam_write_partsel_reg(msc, PART_SEL, partsel); +static void __mpam_intpart_sel(u8 ris_idx, u16 intpartid, struct mpam_msc *msc) +{ + u32 partsel = FIELD_PREP(MPAMCFG_PART_SEL_RIS, ris_idx) | + FIELD_PREP(MPAMCFG_PART_SEL_PARTID_SEL, intpartid) | + MPAMCFG_PART_SEL_INTERNAL; + + __mpam_part_sel_raw(partsel, msc); } int mpam_register_requestor(u16 partid_max, u8 pmg_max) @@ -1364,9 +1376,11 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, spin_lock(&msc->part_sel_lock); __mpam_part_sel(ris->ris_idx, partid, msc); - if(mpam_has_feature(mpam_feat_partid_nrw, rprops)) + if (mpam_has_feature(mpam_feat_partid_nrw, rprops)) { mpam_write_partsel_reg(msc, INTPARTID, (MPAMCFG_PART_SEL_INTERNAL | partid)); + __mpam_intpart_sel(ris->ris_idx, partid, msc); + } if (mpam_has_feature(mpam_feat_cpor_part, rprops)) { if (mpam_has_feature(mpam_feat_cpor_part, cfg)) -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ After the system expands the narrow-partid feature and statically assigns all (req)PARTIDs to each control group, the following scenarios require configuration synchronization operations: 1. MSCs that support narrow-partid need to establish a mapping between reqPARTID and intPARTID after creating a new monitoring group. 2. MSCs that do not support narrow-partid need to synchronize the configuration of sub-monitoring groups after users update the control group configuration. In __write_config(), we synchronize a control group's configuration to each sub-monitoring group. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 26 +++++++++++++++++++++++--- drivers/platform/mpam/mpam_internal.h | 3 +++ drivers/platform/mpam/mpam_resctrl.c | 7 ++++++- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index a190be18fff8..a38f398de112 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -1371,6 +1371,7 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, u16 cmax = MPAMCFG_CMAX_CMAX; struct mpam_msc *msc = ris->msc; u16 bwa_fract = MPAMCFG_MBW_MAX_MAX; + u16 intpartid = req2intpartid(partid); struct mpam_props *rprops = &ris->props; spin_lock(&msc->part_sel_lock); @@ -1378,8 +1379,14 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, if (mpam_has_feature(mpam_feat_partid_nrw, rprops)) { mpam_write_partsel_reg(msc, INTPARTID, - (MPAMCFG_PART_SEL_INTERNAL | partid)); - __mpam_intpart_sel(ris->ris_idx, partid, msc); + MPAMCFG_INTPARTID_INTERNAL | + intpartid); + + /* Already finish mapping reqPARTID to intPARTID */ + if (partid != intpartid) + goto out; + + __mpam_intpart_sel(ris->ris_idx, intpartid, msc); } if (mpam_has_feature(mpam_feat_cpor_part, rprops)) { @@ -1463,6 +1470,7 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, mpam_has_feature(mpam_feat_dspri_part, rprops)) mpam_write_partsel_reg(msc, PRI, pri_val); +out: spin_unlock(&msc->part_sel_lock); } @@ -2570,9 +2578,21 @@ struct mpam_write_config_arg { 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; + + /* This partid should be in the range of intPARTIDs */ + WARN_ON_ONCE(c->partid >= closid_num); - mpam_reprogram_ris_partid(c->ris, c->partid, &c->comp->cfg[c->partid]); + /* Synchronize the configuration to each sub-monitoring group. */ + for (req_idx = 0; req_idx < get_num_reqpartid_per_closid(); + req_idx++) { + reqpartid = req_idx * closid_num + c->partid; + + mpam_reprogram_ris_partid(c->ris, reqpartid, + &c->comp->cfg[c->partid]); + } return 0; } diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index e4809f2242ec..11564ee44025 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -594,4 +594,7 @@ bool mpam_cpbm_hisi_check_invalid(struct rdt_resource *r, unsigned long val); int mpam_resctrl_prepare_offline(void); +u32 req2intpartid(u32 reqpartid); +u32 get_num_reqpartid_per_closid(void); + #endif /* MPAM_INTERNAL_H */ diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 7abbb6fa8850..3b53eccda018 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -156,6 +156,11 @@ static u32 get_num_reqpartid(void) return mpam_partid_max + 1; } +u32 get_num_reqpartid_per_closid(void) +{ + return get_num_reqpartid() / resctrl_arch_get_num_closid(NULL); +} + u32 resctrl_arch_system_num_rmid_idx(void) { u8 closid_shift = fls(mpam_pmg_max); @@ -181,7 +186,7 @@ static u32 rmid2pmg(u32 rmid) return rmid & pmg_mask; } -static u32 req2intpartid(u32 reqpartid) +u32 req2intpartid(u32 reqpartid) { u8 intpartid_shift = fls(mpam_intpartid_max); u32 intpartid_mask = ~(~0 << intpartid_shift); -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ Earlier, static allocation of reqPartid is already completed without modifying the resctrl layer. However, static allocation of reqPartid in practice prevents creating more monitoring sub-groups than the statically allocated reqPartid resources, while unused reqPartids are wasted. Binding reqPartids to partids that need to extend monitoring sub-groups through dynamic allocation can maximize the upper limit on the number of monitoring groups that a control group can create. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 13 +- drivers/platform/mpam/mpam_internal.h | 2 +- drivers/platform/mpam/mpam_resctrl.c | 189 +++++++++++++++++++++----- fs/resctrl/monitor.c | 23 +++- include/linux/resctrl.h | 18 +++ 5 files changed, 201 insertions(+), 44 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index a38f398de112..283a947720dd 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -2580,18 +2580,17 @@ 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; /* This partid should be in 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_closid(); - req_idx++) { - reqpartid = req_idx * closid_num + c->partid; - - mpam_reprogram_ris_partid(c->ris, reqpartid, - &c->comp->cfg[c->partid]); + 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/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index 11564ee44025..3e9f150e358a 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -595,6 +595,6 @@ bool mpam_cpbm_hisi_check_invalid(struct rdt_resource *r, unsigned long val); int mpam_resctrl_prepare_offline(void); u32 req2intpartid(u32 reqpartid); -u32 get_num_reqpartid_per_closid(void); +u32 get_num_reqpartid(void); #endif /* MPAM_INTERNAL_H */ diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 3b53eccda018..8b5ca4ec99ee 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -151,16 +151,11 @@ u32 resctrl_arch_get_num_closid(struct rdt_resource *ignored) return mpam_intpartid_max + 1; } -static u32 get_num_reqpartid(void) +u32 get_num_reqpartid(void) { return mpam_partid_max + 1; } -u32 get_num_reqpartid_per_closid(void) -{ - return get_num_reqpartid() / resctrl_arch_get_num_closid(NULL); -} - u32 resctrl_arch_system_num_rmid_idx(void) { u8 closid_shift = fls(mpam_pmg_max); @@ -172,10 +167,18 @@ u32 resctrl_arch_system_num_rmid_idx(void) static u32 rmid2reqpartid(u32 rmid) { u8 pmg_shift = fls(mpam_pmg_max); + u32 reqpartid; WARN_ON_ONCE(pmg_shift > 8); - return rmid >> pmg_shift; + 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 u32 rmid2pmg(u32 rmid) @@ -186,12 +189,39 @@ static u32 rmid2pmg(u32 rmid) return rmid & pmg_mask; } +static u32 partid2closid(u32 partid) +{ + if (cdp_enabled) + partid >>= 1; + + return partid; +} + +static u32 req_pmg2rmid(u32 reqpartid, u32 pmg) +{ + u32 rmid; + u8 pmg_shift = fls(mpam_pmg_max); + u32 pmg_mask = ~(~0 << pmg_shift); + + rmid = partid2closid(reqpartid); + + return (rmid << pmg_shift) | (pmg & pmg_mask); +} + +static u32 *reqpartid_map; + u32 req2intpartid(u32 reqpartid) { - u8 intpartid_shift = fls(mpam_intpartid_max); - u32 intpartid_mask = ~(~0 << intpartid_shift); + WARN_ON_ONCE(reqpartid >= get_num_reqpartid()); - return reqpartid & intpartid_mask; + /* + * Directly return intPartid in case that mpam_reset_ris() access + * NULL pointer. + */ + if (reqpartid < resctrl_arch_get_num_closid(NULL)) + return reqpartid; + + return reqpartid_map[reqpartid]; } /* @@ -205,12 +235,12 @@ u32 req2intpartid(u32 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; @@ -223,11 +253,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_sched_in(struct task_struct *tsk) @@ -1202,6 +1230,87 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) return 0; } +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; +} + +void reqpartid_exit(void) +{ + kfree(reqpartid_map); +} + +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++) + update_rmid_entry(closid, req_pmg2rmid(reqpartid, pmg)); +} + +int resctrl_arch_expand_rmid(u32 closid) +{ + int i; + + for (i = resctrl_arch_get_num_closid(NULL); + i < get_num_reqpartid(); i++) { + 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_shrink_rmid(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; @@ -1233,24 +1342,35 @@ int mpam_resctrl_setup(void) } cpus_read_unlock(); - if (!err && !exposed_alloc_capable && !exposed_mon_capable) - err = -EOPNOTSUPP; - - if (!err) { - if (!is_power_of_2(mpam_pmg_max + 1)) { - /* - * If not all the partid*pmg values are valid indexes, - * resctrl may allocate pmg that don't exist. This - * should cause an error interrupt. - */ - pr_warn("Number of PMG is not a power of 2! resctrl may misbehave"); - } + if (err) + return err; + + if (!exposed_alloc_capable && !exposed_mon_capable) + return -EOPNOTSUPP; - err = resctrl_init(); - if (!err) - WRITE_ONCE(resctrl_enabled, true); + err = reqpartid_init(); + if (err) + return err; + + if (!is_power_of_2(mpam_pmg_max + 1)) { + /* + * If not all the partid*pmg values are valid indexes, + * resctrl may allocate pmg that don't exist. This + * should cause an error interrupt. + */ + pr_warn("Number of PMG is not a power of 2! resctrl may misbehave"); } + err = resctrl_init(); + if (err) + goto err; + + WRITE_ONCE(resctrl_enabled, true); + + return 0; + +err: + reqpartid_exit(); return err; } @@ -1261,6 +1381,7 @@ void mpam_resctrl_exit(void) WRITE_ONCE(resctrl_enabled, false); resctrl_exit(); + reqpartid_exit(); } u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c index b651b37e7e65..de7ba429972a 100644 --- a/fs/resctrl/monitor.c +++ b/fs/resctrl/monitor.c @@ -195,7 +195,12 @@ struct rmid_entry *resctrl_find_free_rmid(u32 closid) * very first entry will be returned. */ itr_idx = resctrl_arch_rmid_idx_encode(itr->closid, itr->rmid); + if (itr_idx == U32_MAX) + continue; + cmp_idx = resctrl_arch_rmid_idx_encode(closid, itr->rmid); + if (cmp_idx == U32_MAX) + continue; if (itr_idx == cmp_idx) return itr; @@ -265,7 +270,7 @@ int alloc_rmid(u32 closid) if (IS_ERR(entry)) return PTR_ERR(entry); - list_del(&entry->list); + list_del_init(&entry->list); return entry->rmid; } @@ -324,6 +329,13 @@ void free_rmid(u32 closid, u32 rmid) list_add_tail(&entry->list, &rmid_free_lru); } +bool rmid_is_occupied(u32 closid, u32 rmid) +{ + u32 idx = resctrl_arch_rmid_idx_encode(closid, rmid); + + return list_empty(&rmid_ptrs[idx].list); +} + static struct mbm_state *get_mbm_state(struct rdt_domain *d, u32 closid, u32 rmid, enum resctrl_event_id evtid) { @@ -733,6 +745,13 @@ void mbm_setup_overflow_handler(struct rdt_domain *dom, unsigned long delay_ms, schedule_delayed_work_on(cpu, &dom->mbm_over, delay); } +void update_rmid_entry(u32 closid, u32 rmid) +{ + u32 idx = resctrl_arch_rmid_idx_encode(closid, rmid); + + rmid_ptrs[idx].closid = closid; +} + static int dom_data_init(struct rdt_resource *r) { u32 idx_limit = resctrl_arch_system_num_rmid_idx(); @@ -780,7 +799,7 @@ static int dom_data_init(struct rdt_resource *r) idx = resctrl_arch_rmid_idx_encode(RESCTRL_RESERVED_CLOSID, RESCTRL_RESERVED_RMID); entry = __rmid_entry(idx); - list_del(&entry->list); + list_del_init(&entry->list); out_unlock: mutex_unlock(&rdtgroup_mutex); diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h index 958b1f39d016..cb13d8a57ff0 100644 --- a/include/linux/resctrl.h +++ b/include/linux/resctrl.h @@ -438,6 +438,24 @@ void resctrl_arch_reset_rmid_all(struct rdt_resource *r, struct rdt_domain *d); extern unsigned int resctrl_rmid_realloc_threshold; extern unsigned int resctrl_rmid_realloc_limit; +/** + * rmid_is_occupied() - Check whether the specified rmid has been allocated + * and is in use. + * @closid: Specify the closid that matches the rmid. + * @rmid: Specify the rmid entry to check status. + * + * Return: + * True if the specified rmid is still in use. + */ +bool rmid_is_occupied(u32 closid, u32 rmid); + +/** + * update_rmid_entry() - Update rmid entry content. + * @closid: Specify the closid that matches the rmid. + * @rmid: Specify the rmid entry to update content. + */ +void update_rmid_entry(u32 closid, u32 rmid); + extern bool resctrl_mounted; int resctrl_init(void); -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- arch/x86/include/asm/resctrl.h | 7 +++++++ fs/resctrl/monitor.c | 27 +++++++++++++++++++++++++-- include/linux/arm_mpam.h | 16 ++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 406b4cf301bb..4a65eb19b2cf 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -181,6 +181,13 @@ static inline bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 ignored, return READ_ONCE(tsk->rmid) == rmid; } +static inline int resctrl_arch_expand_rmid(u32 closid) +{ + return -ENOSPC; +} + +static inline void resctrl_arch_shrink_rmid(u32 closid, u32 rmid) {} + static inline void resctrl_sched_in(struct task_struct *tsk) { if (static_branch_likely(&rdt_enable_key)) diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c index de7ba429972a..97e7acf54e38 100644 --- a/fs/resctrl/monitor.c +++ b/fs/resctrl/monitor.c @@ -115,6 +115,8 @@ static void limbo_release_entry(struct rmid_entry *entry) if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID)) closid_num_dirty_rmid[entry->closid]--; + + resctrl_arch_shrink_rmid(entry->closid, entry->rmid); } /* @@ -178,7 +180,7 @@ bool has_busy_rmid(struct rdt_domain *d) return find_first_bit(d->rmid_busy_llc, idx_limit) != idx_limit; } -struct rmid_entry *resctrl_find_free_rmid(u32 closid) +struct rmid_entry *__resctrl_find_free_rmid(u32 closid) { struct rmid_entry *itr; u32 itr_idx, cmp_idx; @@ -209,6 +211,25 @@ struct rmid_entry *resctrl_find_free_rmid(u32 closid) return ERR_PTR(-ENOSPC); } +struct rmid_entry *resctrl_find_free_rmid(u32 closid) +{ + struct rmid_entry *err; + int ret; + + err = __resctrl_find_free_rmid(closid); + if (err == ERR_PTR(-ENOSPC)) { + ret = resctrl_arch_expand_rmid(closid); + if (ret < 0) + /* Out of rmid */ + goto out; + + /* Try it again */ + return __resctrl_find_free_rmid(closid); + } +out: + return err; +} + /** * resctrl_find_cleanest_closid() - Find a CLOSID where all the associated * RMID are clean, or the CLOSID that has @@ -325,8 +346,10 @@ void free_rmid(u32 closid, u32 rmid) if (resctrl_arch_is_llc_occupancy_enabled()) add_rmid_to_limbo(entry); - else + else { list_add_tail(&entry->list, &rmid_free_lru); + resctrl_arch_shrink_rmid(closid, rmid); + } } bool rmid_is_occupied(u32 closid, u32 rmid) diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index 3a06a8afad7c..6e6b960cea46 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -78,6 +78,22 @@ int resctrl_arch_set_cdp_enabled(enum resctrl_res_level ignored, bool enable); bool resctrl_arch_hide_cdp(enum resctrl_res_level rid); 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_expand_rmid() - 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_expand_rmid(u32 closid); +/** + * resctrl_arch_shrink_rmid() - Release the rmid resources for the specified closid. + * @closid: closid that matches the rmid. + * @rmid: Release the rmid specified. + */ +void resctrl_arch_shrink_rmid(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); -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ Because it needs to support mixed systems that include MSCs with and without Narrow-PARTID support, there are the following incompatible control issues. If an MSC does not support Narrow-PARTID and its control method is not of the "partition bitmap" type, then delivering the resctrl control group configuration across multiple PARTIDs will change the user's expected behavior. Currently, the original semantics of MBMAX (and MBMIN) cannot be guaranteed through simple configuration of different control values. So here decide to restrict the usage scenarios of this feature. When we find that the MSC does not support the Narrow-PARTID feature: 1. And if a control group modifies its MBMAX/MBMIN configuration, it cannot be allowed to create monitoring sub-groups by reqPartids. 2. And If a control group has created monitoring sub-groups by reqPartids, it cannot be allowed to modify MBMAX/MBMIN configuration. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 97 +++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 8b5ca4ec99ee..196c48fe1805 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -1260,9 +1260,71 @@ void update_rmid_entries_for_reqpartid(u32 reqpartid) update_rmid_entry(closid, req_pmg2rmid(reqpartid, pmg)); } +static int check_narrow_mkdir_limit(u32 closid) +{ + u32 intpartid; + struct rdt_domain *d; + struct mpam_props *cprops; + struct mpam_resctrl_res *res; + struct mpam_resctrl_dom *dom; + struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_MBA); + struct rdt_resource *r_min = resctrl_arch_get_resource(RDT_RESOURCE_MB_MIN); + + if (cdp_enabled) + intpartid = resctrl_get_config_index(closid, CDP_DATA); + else + intpartid = resctrl_get_config_index(closid, CDP_NONE); + + res = container_of(r, struct mpam_resctrl_res, resctrl_res); + cprops = &res->class->props; + + if (mpam_has_feature(mpam_feat_partid_nrw, cprops)) + return 0; + + if (get_num_reqpartid() == resctrl_arch_get_num_closid(NULL)) + return 0; + + /* Config has changed */ + list_for_each_entry(d, &r->domains, list) { + dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); + + if (dom->comp->cfg[intpartid].mbw_max != + percent_to_mbw_max(r->default_ctrl, cprops->bwa_wd)) + return -ENOSPC; + + if (dom->comp->cfg[intpartid].mbw_min != + percent_to_mbw_max(r_min->default_ctrl, cprops->bwa_wd)) + return -ENOSPC; + } + + return 0; +} + +static int mpam_sync_config(u32 intpartid) +{ + struct mpam_component *comp; + struct mpam_class *class; + int err; + + list_for_each_entry(class, &mpam_classes, classes_list) { + list_for_each_entry(comp, &class->components, class_list) { + err = mpam_apply_config(comp, intpartid, + &comp->cfg[intpartid], true); + if (err) + return err; + } + } + + return 0; +} + int resctrl_arch_expand_rmid(u32 closid) { - int i; + int i, err; + + err = check_narrow_mkdir_limit(closid); + if (err) + return err; for (i = resctrl_arch_get_num_closid(NULL); i < get_num_reqpartid(); i++) { @@ -1484,6 +1546,31 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, } } +static int check_narrow_config_limit(struct rdt_resource *r, u32 intpartid, + struct mpam_props *cprops, u32 cfg_val) +{ + int reqpartid; + int req_num = get_num_reqpartid(); + int closid_num = resctrl_arch_get_num_closid(NULL); + + if (mpam_has_feature(mpam_feat_partid_nrw, cprops)) + return 0; + + if (req_num == closid_num) + return 0; + + if (cfg_val == r->default_ctrl) + return 0; + + /* Already deploys reqPartid */ + for (reqpartid = closid_num; reqpartid < req_num; reqpartid++) { + if (req2intpartid(reqpartid) == intpartid) + return -EPERM; + } + + return 0; +} + int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 closid, enum resctrl_conf_type t, u32 cfg_val) { @@ -1540,12 +1627,20 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, mpam_set_feature(mpam_feat_mbw_part, &cfg); break; } else if (mpam_has_feature(mpam_feat_mbw_max, cprops)) { + err = check_narrow_config_limit(r, partid, cprops, cfg_val); + if (err) + return err; + cfg.mbw_max = percent_to_mbw_max(cfg_val, cprops->bwa_wd); mpam_set_feature(mpam_feat_mbw_max, &cfg); break; } return -EINVAL; case RDT_RESOURCE_MB_MIN: + err = check_narrow_config_limit(r, partid, cprops, cfg_val); + if (err) + return err; + cfg.mbw_min = percent_to_mbw_max(cfg_val, cprops->bwa_wd); mpam_set_feature(mpam_feat_mbw_min, &cfg); break; -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- fs/resctrl/rdtgroup.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index cb139678fef0..60c63a52ac9a 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -2693,10 +2693,6 @@ static int rdt_get_tree(struct fs_context *fc) goto out; } - ret = rdtgroup_setup_root(ctx); - if (ret) - goto out; - ret = rdt_enable_ctx(ctx); if (ret) goto out_root; @@ -2709,6 +2705,14 @@ static int rdt_get_tree(struct fs_context *fc) if (ret) goto out_schemata_free; + /* + * Should be called after schemata_list_create() and + * closid_init(). + */ + ret = rdtgroup_setup_root(ctx); + if (ret) + goto out; + if (resctrl_arch_mon_capable()) flags |= RFTYPE_MON; @@ -3981,7 +3985,7 @@ static int rdtgroup_setup_root(struct rdt_fs_context *ctx) ctx->kfc.root = rdt_root; rdtgroup_default.kn = kernfs_root_to_node(rdt_root); - return 0; + return rdtgroup_init_alloc(&rdtgroup_default); } static void rdtgroup_destroy_root(void) -- 2.25.1
hulk inclusion category: cleanup bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 -------------------------------- This reverts commit 5e0e3aa64e83dff9703e3f887a2be3271801ed22. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- arch/x86/include/asm/resctrl.h | 4 ---- drivers/platform/mpam/mpam_resctrl.c | 31 +++++++++++++++++----------- fs/resctrl/ctrlmondata.c | 28 +++---------------------- include/linux/arm_mpam.h | 1 - 4 files changed, 22 insertions(+), 42 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 4a65eb19b2cf..184bc1ed8455 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -231,10 +231,6 @@ void resctrl_cpu_detect(struct cpuinfo_x86 *c); bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level l); int resctrl_arch_set_cdp_enabled(enum resctrl_res_level l, bool enable); -static inline bool resctrl_arch_hide_cdp(enum resctrl_res_level rid) -{ - return false; -}; #else diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 196c48fe1805..18f9bc54dbd1 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -136,7 +136,7 @@ int resctrl_arch_set_cdp_enabled(enum resctrl_res_level ignored, bool enable) return 0; } -bool resctrl_arch_hide_cdp(enum resctrl_res_level rid) +static bool mpam_resctrl_hide_cdp(enum resctrl_res_level rid) { return cdp_enabled && !resctrl_arch_get_cdp_enabled(rid); } @@ -1465,16 +1465,7 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); cprops = &res->class->props; - /* - * When CDP is enabled, but the resource doesn't support it, we - * need to get the configuration from the CDP_CODE resctrl_conf_type - * which is same as the CDP_DATA one. - */ - if (resctrl_arch_hide_cdp(r->rid)) - partid = resctrl_get_config_index(closid, CDP_CODE); - else - partid = resctrl_get_config_index(closid, type); - + partid = resctrl_get_config_index(closid, type); cfg = &dom->comp->cfg[partid]; switch (r->rid) { @@ -1574,6 +1565,7 @@ static int check_narrow_config_limit(struct rdt_resource *r, u32 intpartid, int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 closid, enum resctrl_conf_type t, u32 cfg_val) { + int err; u32 partid; struct mpam_config cfg; struct mpam_props *cprops; @@ -1652,7 +1644,22 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, return -EINVAL; } - return mpam_apply_config(dom->comp, partid, &cfg); + /* + * When CDP is enabled, but the resource doesn't support it, we need to + * apply the same configuration to the other partid. + */ + if (mpam_resctrl_hide_cdp(r->rid)) { + partid = resctrl_get_config_index(closid, CDP_CODE); + err = mpam_apply_config(dom->comp, partid, &cfg); + if (err) + return err; + + partid = resctrl_get_config_index(closid, CDP_DATA); + return mpam_apply_config(dom->comp, partid, &cfg); + + } else { + return mpam_apply_config(dom->comp, partid, &cfg); + } } /* TODO: this is IPI heavy */ diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index 547048f7bee7..cf4895b41fc4 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -73,15 +73,15 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r) return true; } -static int parse_bw_conf_type(struct rdt_parse_data *data, struct resctrl_schema *s, - struct rdt_domain *d, enum resctrl_conf_type conf_type) +static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, + struct rdt_domain *d) { struct resctrl_staged_config *cfg; u32 closid = data->rdtgrp->closid; struct rdt_resource *r = s->res; unsigned long bw_val; - cfg = &d->staged_config[conf_type]; + cfg = &d->staged_config[s->conf_type]; if (cfg->have_new_ctrl) { rdt_last_cmd_printf("Duplicate domain %d\n", d->id); return -EINVAL; @@ -101,28 +101,6 @@ static int parse_bw_conf_type(struct rdt_parse_data *data, struct resctrl_schema return 0; } -static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, - struct rdt_domain *d) -{ - struct rdt_resource *r = s->res; - int err; - - /* - * When CDP is enabled, but the resource doesn't support it, we - * need to apply the same configuration to both of the CDP_CODE - * and CDP_DATA resctrl_conf_type. - */ - if (resctrl_arch_hide_cdp(r->rid)) { - err = parse_bw_conf_type(data, s, d, CDP_CODE); - if (err) - return err; - - return parse_bw_conf_type(data, s, d, CDP_DATA); - } - - return parse_bw_conf_type(data, s, d, s->conf_type); -} - /* * Check whether a cache bit mask is valid. * On Intel CPUs, non-contiguous 1s value support is indicated by CPUID: diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index 6e6b960cea46..38753c78ec50 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -75,7 +75,6 @@ void resctrl_arch_reset_resources(void); bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level ignored); int resctrl_arch_set_cdp_enabled(enum resctrl_res_level ignored, bool enable); -bool resctrl_arch_hide_cdp(enum resctrl_res_level rid); bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid); bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid); -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 18f9bc54dbd1..16c1a036d51c 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -1465,7 +1465,16 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); cprops = &res->class->props; - partid = resctrl_get_config_index(closid, type); + /* + * When CDP is enabled, but the resource doesn't support it, we + * need to get the configuration from the CDP_DATA resctrl_conf_type + * which is same as the CDP_CODE one. + */ + if (mpam_resctrl_hide_cdp(r->rid)) + partid = resctrl_get_config_index(closid, CDP_DATA); + else + partid = resctrl_get_config_index(closid, type); + cfg = &dom->comp->cfg[partid]; switch (r->rid) { @@ -1581,7 +1590,16 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, dom = container_of(d, struct mpam_resctrl_dom, resctrl_dom); cprops = &res->class->props; - partid = resctrl_get_config_index(closid, t); + /* + * When CDP is enabled, but the resource doesn't support it, we + * need to get the configuration from the CDP_DATA resctrl_conf_type + * which is same as the CDP_CODE one. + */ + if (mpam_resctrl_hide_cdp(r->rid)) + partid = resctrl_get_config_index(closid, CDP_DATA); + else + partid = resctrl_get_config_index(closid, t); + if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r)) return -EINVAL; -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 25 +++++++++++++++++++++---- drivers/platform/mpam/mpam_internal.h | 2 +- drivers/platform/mpam/mpam_resctrl.c | 17 +++++++++++------ 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index 283a947720dd..fb52e3104006 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -2574,6 +2574,7 @@ struct mpam_write_config_arg { struct mpam_msc_ris *ris; struct mpam_component *comp; u16 partid; + bool sync; }; static int __write_config(void *arg) @@ -2582,9 +2583,21 @@ static int __write_config(void *arg) struct mpam_write_config_arg *c = arg; u32 reqpartid; + if (c->sync) { + /* This partid should be in the range of reqPARTIDs */ + WARN_ON_ONCE(c->partid < closid_num); + + mpam_reprogram_ris_partid(c->ris, c->partid, + &c->comp->cfg[req2intpartid(c->partid)]); + return 0; + } + /* This partid should be in the range of intPARTIDs */ WARN_ON_ONCE(c->partid >= closid_num); + mpam_reprogram_ris_partid(c->ris, c->partid, + &c->comp->cfg[c->partid]); + /* Synchronize the configuration to each sub-monitoring group. */ for (reqpartid = closid_num; reqpartid < get_num_reqpartid(); reqpartid++) { @@ -2599,7 +2612,7 @@ static int __write_config(void *arg) /* TODO: split into write_config/sync_config */ /* TODO: add config_dirty bitmap to drive sync_config */ int mpam_apply_config(struct mpam_component *comp, u16 partid, - struct mpam_config *cfg) + struct mpam_config *cfg, bool sync) { struct mpam_write_config_arg arg; struct mpam_msc_ris *ris; @@ -2607,12 +2620,16 @@ int mpam_apply_config(struct mpam_component *comp, u16 partid, lockdep_assert_cpus_held(); - if (!memcmp(&comp->cfg[partid], cfg, sizeof(*cfg))) - return 0; + if (!sync) { + if (!memcmp(&comp->cfg[partid], cfg, sizeof(*cfg))) + return 0; + + comp->cfg[partid] = *cfg; + } - comp->cfg[partid] = *cfg; arg.comp = comp; arg.partid = partid; + arg.sync = sync; idx = srcu_read_lock(&mpam_srcu); list_for_each_entry_rcu(ris, &comp->ris, comp_list) { diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index 3e9f150e358a..717b0b240582 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -314,7 +314,7 @@ void mpam_disable(struct work_struct *work); void mpam_reset_class(struct mpam_class *class); int mpam_apply_config(struct mpam_component *comp, u16 partid, - struct mpam_config *cfg); + struct mpam_config *cfg, bool force); int mpam_msmon_read(struct mpam_component *comp, struct mon_cfg *ctx, enum mpam_device_features, u64 *val); diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 16c1a036d51c..661d5f26e6c1 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -1300,7 +1300,7 @@ static int check_narrow_mkdir_limit(u32 closid) return 0; } -static int mpam_sync_config(u32 intpartid) +static int mpam_sync_config(u32 reqpartid) { struct mpam_component *comp; struct mpam_class *class; @@ -1308,8 +1308,7 @@ static int mpam_sync_config(u32 intpartid) list_for_each_entry(class, &mpam_classes, classes_list) { list_for_each_entry(comp, &class->components, class_list) { - err = mpam_apply_config(comp, intpartid, - &comp->cfg[intpartid], true); + err = mpam_apply_config(comp, reqpartid, NULL, true); if (err) return err; } @@ -1331,10 +1330,16 @@ int resctrl_arch_expand_rmid(u32 closid) if (reqpartid_map[i] >= resctrl_arch_get_num_closid(NULL)) { if (cdp_enabled) { reqpartid_map[i] = resctrl_get_config_index(closid, CDP_DATA); + mpam_sync_config(i); + reqpartid_map[i + 1] = resctrl_get_config_index(closid, CDP_CODE); + mpam_sync_config(i + 1); + } else { reqpartid_map[i] = resctrl_get_config_index(closid, CDP_NONE); + mpam_sync_config(i); } + update_rmid_entries_for_reqpartid(i); return i; } @@ -1668,15 +1673,15 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, */ if (mpam_resctrl_hide_cdp(r->rid)) { partid = resctrl_get_config_index(closid, CDP_CODE); - err = mpam_apply_config(dom->comp, partid, &cfg); + err = mpam_apply_config(dom->comp, partid, &cfg, false); if (err) return err; partid = resctrl_get_config_index(closid, CDP_DATA); - return mpam_apply_config(dom->comp, partid, &cfg); + return mpam_apply_config(dom->comp, partid, &cfg, false); } else { - return mpam_apply_config(dom->comp, partid, &cfg); + return mpam_apply_config(dom->comp, partid, &cfg, false); } } -- 2.25.1
hulk inclusion category: feature bugzilla: https://atomgit.com/openeuler/kernel/issues/8420 ------------------ Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- fs/resctrl/rdtgroup.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 60c63a52ac9a..e29699ebc0e6 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -2993,17 +2993,37 @@ static void rmdir_all_sub(void) kernfs_remove(kn_mondata); } +static void rdt_destroy_limbo(void) +{ + struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3); + struct rdt_domain *d; + + if (!IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID)) + return; + + if (!resctrl_arch_is_llc_occupancy_enabled()) + return; + + list_for_each_entry(d, &r->domains, list) { + if (has_busy_rmid(d)) { + __check_limbo(d, true); + cancel_delayed_work(&d->cqm_limbo); + } + } +} + static void rdt_kill_sb(struct super_block *sb) { cpus_read_lock(); mutex_lock(&rdtgroup_mutex); - rdt_disable_ctx(); - /* Put everything back to default values. */ resctrl_arch_reset_resources(); rmdir_all_sub(); + rdt_destroy_limbo(); + rdt_disable_ctx(); + if (IS_ENABLED(CONFIG_RESCTRL_FS_PSEUDO_LOCK)) rdt_pseudo_lock_release(); rdtgroup_default.mode = RDT_MODE_SHAREABLE; -- 2.25.1
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/20720 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/BAI... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/20720 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/BAI...
participants (2)
-
patchwork bot -
Zeng Heng