[PATCH v4 OLK-6.6 00/18] fs/resctrl: Introduce the resctrl_feat_type

Compare to v3: Patch 09: Add comments for the enum resctrl_feat_type and make modifications based on community feedback. Compare to v2: Patch 09: Merge the changes related to the impact on the common layer in Patch 10. Patch 18: New patch added. Compare to v1: Patch 5: Update the condition for MPAM to determine whether to perform MBM overflow checking. Patch 15: Split the original patch and merge part of the fix content into Patch 9. Zeng Heng (18): arm64/mpam: fix memleak in resctrl_arch_mon_ctx_alloc_no_wait() arm64/mpam: fix impossible condition in get_cpumask_from_cache_id() arm64/mpam: fix impossible condition in resctrl_arch_rmid_read() arm64/mpam: Optimize CSU/MBWU monitor multiplexing fs/resctrl: Determine whether the MBM monitors require overflow checking arm64/mpam: Set the cpbm width of msc class with the minimum arm64/mpam: Correct the judgment condition of the CMAX feature fs/resctrl: Fix kmemleak caused by closid_init() fs/resctrl: Introduce the resctrl_feat_type arm64/mpam: Add mbw_min and cmin features arm64/mpam: Add PRIO feature arm64/mpam: Add CMAX feature arm64/mpam: Add PBM feature arm64/mpam: Add limit feature arm64/mpam: Fix allocated cache size information fs/resctrl: Fix configuration to wrong control group when CDP is enabled arm64/mpam: Add debugging information about CDP monitor value fs/resctrl: Support arch specific struct resctrl_arch_staged_config arch/x86/include/asm/resctrl.h | 33 ++ arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 16 +- drivers/platform/mpam/mpam_devices.c | 111 +++++-- drivers/platform/mpam/mpam_internal.h | 23 +- drivers/platform/mpam/mpam_resctrl.c | 355 +++++++++++++++++----- fs/resctrl/ctrlmondata.c | 138 ++++++++- fs/resctrl/monitor.c | 5 +- fs/resctrl/rdtgroup.c | 146 ++++++--- include/linux/arm_mpam.h | 11 + include/linux/resctrl.h | 36 ++- include/linux/resctrl_types.h | 30 ++ 11 files changed, 716 insertions(+), 188 deletions(-) -- 2.25.1

反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/15972 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/7HL... 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://gitee.com/openeuler/kernel/pulls/15972 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/7HL...

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAJUN4 -------------------------------- The smatch tool complains about possible memory leak warning shown below: drivers/platform/mpam/mpam_resctrl.c:323 resctrl_arch_mon_ctx_alloc_no_wait() warn: possible memory leak of 'ret' drivers/platform/mpam/mpam_resctrl.c:326 resctrl_arch_mon_ctx_alloc_no_wait() warn: possible memory leak of 'ret' Only the QOS_L3_OCCUP_EVENT_ID path will return the allocated object, and other case paths will cause memory leaks. In the QOS_L3_MBM_LOCAL_EVENT_ID and QOS_L3_MBM_TOTAL_EVENT_ID cases, resctrl_arch_mon_ctx_alloc_no_wait() should return a pointer to the allocated object, not an invalid pointer. Fixes: 9119da143939 ("arm_mpam: resctrl: Allow resctrl to allocate monitors") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 609dcb21c7ac..c42d8d4b89e6 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -58,7 +58,6 @@ static DECLARE_WAIT_QUEUE_HEAD(wait_cacheinfo_ready); /* A dummy mon context to use when the monitors were allocated up front */ u32 __mon_is_rmid_idx = USE_RMID_IDX; -void *mon_is_rmid_idx = &__mon_is_rmid_idx; bool resctrl_arch_alloc_capable(void) { @@ -311,12 +310,16 @@ static void *resctrl_arch_mon_ctx_alloc_no_wait(struct rdt_resource *r, *ret = mpam_alloc_csu_mon(res->class); return ret; + case QOS_L3_MBM_LOCAL_EVENT_ID: case QOS_L3_MBM_TOTAL_EVENT_ID: - return mon_is_rmid_idx; - } + *ret = __mon_is_rmid_idx; + return ret; - return ERR_PTR(-EOPNOTSUPP); + default: + kfree(ret); + return ERR_PTR(-EOPNOTSUPP); + } } void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r, int evtid) @@ -344,15 +347,11 @@ void resctrl_arch_mon_ctx_free(struct rdt_resource *r, int evtid, struct mpam_resctrl_res *res; u32 mon = *(u32 *)arch_mon_ctx; - if (mon == USE_RMID_IDX) - return; kfree(arch_mon_ctx); - arch_mon_ctx = NULL; - - res = container_of(r, struct mpam_resctrl_res, resctrl_res); switch (evtid) { case QOS_L3_OCCUP_EVENT_ID: + res = container_of(r, struct mpam_resctrl_res, resctrl_res); mpam_free_csu_mon(res->class, mon); wake_up(&resctrl_mon_ctx_waiters); return; -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAJUN4 -------------------------------- The smatch tool complains about impossible condition warning shown below: drivers/platform/mpam/mpam_devices.c:391 get_cpumask_from_cache_id() warn: impossible condition '(cache_id == ~0) => (0-u32max == u64max)' cache_id is an unsigned 32-bit object, so when comparing conditions, keep the data types consistent. Fixes: 848cefee5a21 ("arm_mpam: Add the class and component structures for ris firmware described") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index 56bbd7290cd9..e99f6b0b3d59 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -388,7 +388,7 @@ static int get_cpumask_from_cache_id(u32 cache_id, u32 cache_level, * during device_initcall(). Use cache_of_get_id(). */ iter_cache_id = cache_of_get_id(iter); - if (cache_id == ~0UL) { + if (cache_id == (~0)) { of_node_put(iter); continue; } -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAJUN4 -------------------------------- The smatch tool complains about impossible condition warning shown below: drivers/platform/mpam/mpam_resctrl.c:414 resctrl_arch_rmid_read() warn: impossible condition '(cfg.mon == ((~0) + 1)) => (0-u16max == 65536)' The USE_RMID_IDX macro is a 32-bit data type, as the assignment object, cfg.mon should also be a 32-bit unsigned variable. Fixes: 21ac9fc8f275 ("arm_mpam: Track bandwidth counter state for overflow and power management") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index 119660a53e16..a613e5a77a85 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -194,7 +194,7 @@ enum mon_filter_options { }; struct mon_cfg { - u16 mon; + u32 mon; u8 pmg; bool match_pmg; u32 partid; -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- When MBM is implemented according to the *DDI0598* protocol, that is, mbm_total_bytes interface returns the statistical results of instantaneous bandwidth traffic, there is no need to create a delay_work to handle MBM statistical overflow. No matter it is MBWU or CSU monitors, using per-CLOSID monitoring instances avoids inaccurate statistical results caused by monitor multiplexing, which can occur when multiple control groups are monitored simultaneously. Fixes: 9119da143939 ("arm_mpam: resctrl: Allow resctrl to allocate monitors") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 33 +++++++--------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index c42d8d4b89e6..0d0d0e555b71 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -298,7 +298,6 @@ struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l) static void *resctrl_arch_mon_ctx_alloc_no_wait(struct rdt_resource *r, int evtid) { - struct mpam_resctrl_res *res; u32 *ret = kmalloc(sizeof(*ret), GFP_KERNEL); if (!ret) @@ -306,11 +305,6 @@ static void *resctrl_arch_mon_ctx_alloc_no_wait(struct rdt_resource *r, switch (evtid) { case QOS_L3_OCCUP_EVENT_ID: - res = container_of(r, struct mpam_resctrl_res, resctrl_res); - - *ret = mpam_alloc_csu_mon(res->class); - return ret; - case QOS_L3_MBM_LOCAL_EVENT_ID: case QOS_L3_MBM_TOTAL_EVENT_ID: *ret = __mon_is_rmid_idx; @@ -344,21 +338,7 @@ void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r, int evtid) void resctrl_arch_mon_ctx_free(struct rdt_resource *r, int evtid, void *arch_mon_ctx) { - struct mpam_resctrl_res *res; - u32 mon = *(u32 *)arch_mon_ctx; - kfree(arch_mon_ctx); - - switch (evtid) { - case QOS_L3_OCCUP_EVENT_ID: - res = container_of(r, struct mpam_resctrl_res, resctrl_res); - mpam_free_csu_mon(res->class, mon); - wake_up(&resctrl_mon_ctx_waiters); - return; - case QOS_L3_MBM_TOTAL_EVENT_ID: - case QOS_L3_MBM_LOCAL_EVENT_ID: - return; - } } static enum mon_filter_options resctrl_evt_config_to_mpam(u32 local_evt_cfg) @@ -379,7 +359,7 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d, { int err; u64 cdp_val; - u16 num_mbwu_mon; + u16 num_mon; struct mon_cfg cfg; struct mpam_resctrl_dom *dom; struct mpam_resctrl_res *res; @@ -406,12 +386,15 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d, if (cfg.mon == USE_RMID_IDX) { /* * The number of mbwu monitors can't support free run mode, - * adapt the remainder of rmid to the num_mbwu_mon as a - * compromise. + * adapt the remainder of rmid to the num_mon as compromise. */ res = container_of(r, struct mpam_resctrl_res, resctrl_res); - num_mbwu_mon = res->class->props.num_mbwu_mon; - cfg.mon = resctrl_arch_rmid_idx_encode(closid, rmid) % num_mbwu_mon; + if (type == mpam_feat_msmon_mbwu) + num_mon = res->class->props.num_mbwu_mon; + else + num_mon = res->class->props.num_csu_mon; + + cfg.mon = closid % num_mon; } cfg.match_pmg = true; -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- When MBM is implemented according to the *DDI0598* protocol, that is, mbm_total_bytes interface returns the statistical results of instantaneous bandwidth traffic, there is no need to create a delay_work to handle MBM statistical overflow. Fixes: 9119da143939 ("arm_mpam: resctrl: Allow resctrl to allocate monitors") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- arch/x86/include/asm/resctrl.h | 2 ++ drivers/platform/mpam/mpam_devices.c | 10 +++++++++- fs/resctrl/rdtgroup.c | 9 +++++---- include/linux/arm_mpam.h | 1 + 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 37b8d7dfcfed..c5f90edc3e20 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -94,6 +94,8 @@ static inline bool resctrl_arch_is_mbm_total_enabled(void) return (rdt_mon_features & (1 << QOS_L3_MBM_TOTAL_EVENT_ID)); } +static inline bool resctrl_arch_would_mbm_overflow(void) { return true; } + static inline bool resctrl_arch_is_mbm_local_enabled(void) { return (rdt_mon_features & (1 << QOS_L3_MBM_LOCAL_EVENT_ID)); diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index e99f6b0b3d59..c148ecd47613 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -921,6 +921,14 @@ static const struct midr_range mbwu_flowrate_list[] = { { /* sentinel */ } }; +bool resctrl_arch_would_mbm_overflow(void) +{ + if (is_midr_in_range_list(read_cpuid_id(), mbwu_flowrate_list)) + return false; + + return true; +} + static void __ris_msmon_read(void *arg) { bool nrdy = false; @@ -1009,7 +1017,7 @@ static void __ris_msmon_read(void *arg) * was last reset in the latest version (DDI0598D_b). */ if (ris->comp->class->type == MPAM_CLASS_MEMORY) { - if (is_midr_in_range_list(read_cpuid_id(), mbwu_flowrate_list)) + if (!resctrl_arch_would_mbm_overflow()) break; } diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 13c64231c82d..a631dcecdeaa 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -2714,7 +2714,7 @@ static int rdt_get_tree(struct fs_context *fc) if (resctrl_arch_alloc_capable() || resctrl_arch_mon_capable()) resctrl_mounted = true; - if (resctrl_is_mbm_enabled()) { + if (resctrl_is_mbm_enabled() && resctrl_arch_would_mbm_overflow()) { list_for_each_entry(dom, &l3->domains, list) mbm_setup_overflow_handler(dom, MBM_OVERFLOW_INTERVAL, RESCTRL_PICK_ANY_CPU); @@ -3943,7 +3943,7 @@ void resctrl_offline_domain(struct rdt_resource *r, struct rdt_domain *d) if (resctrl_mounted && resctrl_arch_mon_capable()) rmdir_mondata_subdir_allrdtgrp(r, d->id); - if (resctrl_is_mbm_enabled()) + if (resctrl_is_mbm_enabled() && resctrl_arch_would_mbm_overflow()) cancel_delayed_work(&d->mbm_over); if (resctrl_arch_is_llc_occupancy_enabled() && has_busy_rmid(d)) { /* @@ -4014,7 +4014,7 @@ int resctrl_online_domain(struct rdt_resource *r, struct rdt_domain *d) if (err) goto out_unlock; - if (resctrl_is_mbm_enabled()) { + if (resctrl_is_mbm_enabled() && resctrl_arch_would_mbm_overflow()) { INIT_DELAYED_WORK(&d->mbm_over, mbm_handle_overflow); mbm_setup_overflow_handler(d, MBM_OVERFLOW_INTERVAL, RESCTRL_PICK_ANY_CPU); @@ -4075,7 +4075,8 @@ void resctrl_offline_cpu(unsigned int cpu) d = resctrl_get_domain_from_cpu(cpu, l3); if (d) { - if (resctrl_is_mbm_enabled() && cpu == d->mbm_work_cpu) { + if (resctrl_is_mbm_enabled() && cpu == d->mbm_work_cpu && + resctrl_arch_would_mbm_overflow()) { cancel_delayed_work(&d->mbm_over); mbm_setup_overflow_handler(d, 0, cpu); } diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index d70e4e726fe6..c80f220d98d6 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -66,6 +66,7 @@ bool resctrl_arch_mon_capable(void); bool resctrl_arch_is_llc_occupancy_enabled(void); bool resctrl_arch_is_mbm_local_enabled(void); bool resctrl_arch_is_mbm_total_enabled(void); +bool resctrl_arch_would_mbm_overflow(void); /* reset cached configurations, then all devices */ void resctrl_arch_reset_resources(void); -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV --------------------------------------------------- Be compatible with the hardware platform which has different CPBM bandwidth of cache MSCs within the same class, and prevent the CPBM feature from being cleared. Fixes: 931c09722546 ("arm_mpam: Merge supported features during mpam_enable() into mpam_class") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index c148ecd47613..6876aa5873e2 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -1858,9 +1858,10 @@ __resource_props_mismatch(struct mpam_msc_ris *ris, struct mpam_class *class) /* Clear missing features */ cprops->features &= rprops->features; - /* Clear incompatible features */ + /* Set cpbm_wd with the min cpbm_wd among all cache msc */ if (cprops->cpbm_wd != rprops->cpbm_wd) - mpam_clear_feature(mpam_feat_cpor_part, &cprops->features); + cprops->cpbm_wd = min(cprops->cpbm_wd, rprops->cpbm_wd); + if (cprops->mbw_pbm_bits != rprops->mbw_pbm_bits) mpam_clear_feature(mpam_feat_mbw_part, &cprops->features); -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV --------------------------------------------------- To check whether hardware supports the CMAX feature or not, not only needs to check the CMAX_WD field of the MPAMF_CCAP_IDR register, but also needs to check the NO_CMAX field. Fixes: b1576ca4ed95 ("arm_mpam: Probe and reset the rest of the features") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 3 ++- drivers/platform/mpam/mpam_internal.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index 6876aa5873e2..0bc8393541f1 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -577,7 +577,8 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) u32 ccap_features = mpam_read_partsel_reg(msc, CCAP_IDR); props->cmax_wd = FIELD_GET(MPAMF_CCAP_IDR_CMAX_WD, ccap_features); - if (props->cmax_wd) + if (props->cmax_wd && + !FIELD_GET(MPAMF_CCAP_IDR_NO_CMAX, ccap_features)) mpam_set_feature(mpam_feat_ccap_part, props); } diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index a613e5a77a85..d8854cc6f78e 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -391,6 +391,9 @@ void mpam_resctrl_exit(void); /* MPAMF_CCAP_IDR - MPAM features cache capacity partitioning ID register */ #define MPAMF_CCAP_IDR_CMAX_WD GENMASK(5, 0) +#define MPAMF_CCAP_IDR_HAS_CMIN BIT(29) +#define MPAMF_CCAP_IDR_NO_CMAX BIT(30) +#define MPAMF_CCAP_IDR_HAS_CMAX_SOFTLIM BIT(31) /* MPAMF_MBW_IDR - MPAM features memory bandwidth partitioning ID register */ #define MPAMF_MBW_IDR_BWA_WD GENMASK(5, 0) -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- When the resctrl fs is mounted, closid_init() will allocate memory of closid_free_map, but when the fs is unmounted, it is never released, which will cause a memory leak. Add release of closid_free_map in rdt_kill_sb() to ensure no leaks when the fs is unmounted. Fixes: 1e7284b7981c ("fs/resctrl: Remove the limit on the number of CLOSID") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- fs/resctrl/rdtgroup.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index a631dcecdeaa..4b38a68cc0f3 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -163,6 +163,11 @@ static void closid_init(void) closid_free_map_len = rdt_min_closid; } +static void closid_exit(void) +{ + bitmap_free(closid_free_map); +} + static int closid_alloc(void) { int cleanest_closid; @@ -2662,10 +2667,8 @@ static int rdt_get_tree(struct fs_context *fc) goto out_root; ret = schemata_list_create(); - if (ret) { - schemata_list_destroy(); - goto out_ctx; - } + if (ret) + goto out_schemata_free; closid_init(); @@ -2674,13 +2677,13 @@ static int rdt_get_tree(struct fs_context *fc) ret = rdtgroup_add_files(rdtgroup_default.kn, flags); if (ret) - goto out_schemata_free; + goto out_closid; kernfs_activate(rdtgroup_default.kn); ret = rdtgroup_create_info_dir(rdtgroup_default.kn); if (ret < 0) - goto out_schemata_free; + goto out_closid; if (resctrl_arch_mon_capable()) { ret = mongroup_create_dir(rdtgroup_default.kn, @@ -2733,9 +2736,10 @@ static int rdt_get_tree(struct fs_context *fc) kernfs_remove(kn_mongrp); out_info: kernfs_remove(kn_info); +out_closid: + closid_exit(); out_schemata_free: schemata_list_destroy(); -out_ctx: rdt_disable_ctx(); out_root: rdtgroup_destroy_root(); @@ -2947,6 +2951,7 @@ static void rdt_kill_sb(struct super_block *sb) if (IS_ENABLED(CONFIG_RESCTRL_FS_PSEUDO_LOCK)) rdt_pseudo_lock_release(); rdtgroup_default.mode = RDT_MODE_SHAREABLE; + closid_exit(); schemata_list_destroy(); rdtgroup_destroy_root(); if (resctrl_arch_alloc_capable()) -- 2.25.1

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- In order to expand the new features of MPAM in the following patches, enum resctrl_feat_type is newly added. When the configuration is updated, the CDP type and configuration feature will be traversed and updated, so the staged_config array used to deliver the configuration is expanded into a two-dimensional array. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- arch/x86/include/asm/resctrl.h | 23 +++++ arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 39 +++---- drivers/platform/mpam/mpam_resctrl.c | 81 +++++++++++---- fs/resctrl/ctrlmondata.c | 23 +++-- fs/resctrl/monitor.c | 5 +- fs/resctrl/rdtgroup.c | 118 +++++++++++++++------- include/linux/arm_mpam.h | 5 + include/linux/resctrl.h | 15 +-- include/linux/resctrl_types.h | 12 +++ 9 files changed, 228 insertions(+), 93 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index c5f90edc3e20..d83f7c9b244e 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -223,6 +223,29 @@ 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_feat_capable(enum resctrl_res_level level, + enum resctrl_feat_type feat) +{ + if (feat == FEAT_PBM) { + if (level == RDT_RESOURCE_L3 || + level == RDT_RESOURCE_L2) + return true; + + } else if (feat == FEAT_MAX) { + if (level == RDT_RESOURCE_MBA || + level == RDT_RESOURCE_SMBA) + return true; + } + + return false; +} + +static inline const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, + unsigned long fflags) +{ + return ""; +} + #else static inline void resctrl_sched_in(struct task_struct *tsk) {} diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c index c5c3eaea27b6..30b57c88e3bf 100644 --- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c +++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c @@ -40,7 +40,8 @@ static bool apply_config(struct rdt_hw_domain *hw_dom, } int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, - u32 closid, enum resctrl_conf_type t, u32 cfg_val) + u32 closid, enum resctrl_conf_type t, + enum resctrl_feat_type f, u32 cfg_val) { struct rdt_hw_resource *hw_res = resctrl_to_arch_res(r); struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d); @@ -66,6 +67,7 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) struct rdt_hw_domain *hw_dom; struct msr_param msr_param; enum resctrl_conf_type t; + enum resctrl_feat_type f; cpumask_var_t cpu_mask; struct rdt_domain *d; u32 idx; @@ -80,21 +82,23 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) list_for_each_entry(d, &r->domains, list) { hw_dom = resctrl_to_arch_dom(d); for (t = 0; t < CDP_NUM_TYPES; t++) { - cfg = &hw_dom->d_resctrl.staged_config[t]; - if (!cfg->have_new_ctrl) - continue; - - idx = resctrl_get_config_index(closid, t); - if (!apply_config(hw_dom, cfg, idx, cpu_mask)) - continue; - - if (!msr_param.res) { - msr_param.low = idx; - msr_param.high = msr_param.low + 1; - msr_param.res = r; - } else { - msr_param.low = min(msr_param.low, idx); - msr_param.high = max(msr_param.high, idx + 1); + for (f = 0; f < FEAT_NUM_TYPES; f++) { + cfg = &hw_dom->d_resctrl.staged_config[t][f]; + if (!cfg->have_new_ctrl) + continue; + + idx = resctrl_get_config_index(closid, t); + if (!apply_config(hw_dom, cfg, idx, cpu_mask)) + continue; + + if (!msr_param.res) { + msr_param.low = idx; + msr_param.high = msr_param.low + 1; + msr_param.res = r; + } else { + msr_param.low = min(msr_param.low, idx); + msr_param.high = max(msr_param.high, idx + 1); + } } } } @@ -112,7 +116,8 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) } u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, - u32 closid, enum resctrl_conf_type type) + u32 closid, enum resctrl_conf_type type, + enum resctrl_feat_type feat) { struct rdt_hw_domain *hw_dom = resctrl_to_arch_dom(d); u32 idx = resctrl_get_config_index(closid, type); diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 0d0d0e555b71..826acc6183bb 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -69,6 +69,27 @@ bool resctrl_arch_mon_capable(void) return exposed_mon_capable; } +bool resctrl_arch_feat_capable(enum resctrl_res_level level, + enum resctrl_feat_type feat) +{ + if (feat == FEAT_PBM) { + if (level == RDT_RESOURCE_L3) + return true; + + } else if (feat == FEAT_MAX) { + if (level == RDT_RESOURCE_MBA) + return true; + } + + return false; +} + +const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, + unsigned long fflags) +{ + return ""; +} + bool resctrl_arch_is_mbm_local_enabled(void) { return mbm_local_class; @@ -934,7 +955,8 @@ void mpam_resctrl_exit(void) } u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, - u32 closid, enum resctrl_conf_type type) + u32 closid, enum resctrl_conf_type type, + enum resctrl_feat_type feat) { u32 partid; struct mpam_config *cfg; @@ -958,13 +980,20 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, switch (r->rid) { case RDT_RESOURCE_L2: case RDT_RESOURCE_L3: - configured_by = mpam_feat_cpor_part; - break; + if (mpam_has_feature(mpam_feat_cpor_part, cprops) && + (feat == FEAT_PBM)) { + configured_by = mpam_feat_cpor_part; + break; + } + return -EINVAL; + case RDT_RESOURCE_MBA: - if (mba_class_use_mbw_part(cprops)) { + if (mba_class_use_mbw_part(cprops) && + (feat == FEAT_PBM)) { configured_by = mpam_feat_mbw_part; break; - } else if (mpam_has_feature(mpam_feat_mbw_max, cprops)) { + } else if (mpam_has_feature(mpam_feat_mbw_max, cprops) && + (feat == FEAT_MAX)) { configured_by = mpam_feat_mbw_max; break; } @@ -991,8 +1020,9 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, } } -int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, - u32 closid, enum resctrl_conf_type t, u32 cfg_val) +int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 closid, + enum resctrl_conf_type t, enum resctrl_feat_type f, + u32 cfg_val) { int err; u32 partid; @@ -1017,16 +1047,22 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, switch (r->rid) { case RDT_RESOURCE_L2: case RDT_RESOURCE_L3: - /* TODO: Scaling is not yet supported */ - cfg.cpbm = cfg_val; - mpam_set_feature(mpam_feat_cpor_part, &cfg); - break; + if (mpam_has_feature(mpam_feat_cpor_part, cprops) && + (f == FEAT_PBM)) { + /* TODO: Scaling is not yet supported */ + cfg.cpbm = cfg_val; + mpam_set_feature(mpam_feat_cpor_part, &cfg); + break; + } + return -EINVAL; + case RDT_RESOURCE_MBA: - if (mba_class_use_mbw_part(cprops)) { + if (mba_class_use_mbw_part(cprops) && (f == FEAT_PBM)) { cfg.mbw_pbm = percent_to_mbw_pbm(cfg_val, cprops); mpam_set_feature(mpam_feat_mbw_part, &cfg); break; - } else if (mpam_has_feature(mpam_feat_mbw_max, cprops)) { + } else if (mpam_has_feature(mpam_feat_mbw_max, cprops) && + (f == FEAT_MAX)) { cfg.mbw_max = percent_to_mbw_max(cfg_val, cprops->bwa_wd); mpam_set_feature(mpam_feat_mbw_max, &cfg); break; @@ -1060,6 +1096,7 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) int err = 0; struct rdt_domain *d; enum resctrl_conf_type t; + enum resctrl_feat_type f; struct resctrl_staged_config *cfg; lockdep_assert_cpus_held(); @@ -1067,14 +1104,16 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) list_for_each_entry(d, &r->domains, list) { for (t = 0; t < CDP_NUM_TYPES; t++) { - cfg = &d->staged_config[t]; - if (!cfg->have_new_ctrl) - continue; - - err = resctrl_arch_update_one(r, d, closid, t, - cfg->new_ctrl); - if (err) - return err; + for (f = 0; f < FEAT_NUM_TYPES; f++) { + cfg = &d->staged_config[t][f]; + if (!cfg->have_new_ctrl) + continue; + + err = resctrl_arch_update_one( + r, d, closid, t, f, cfg->new_ctrl); + if (err) + return err; + } } } diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index 62a6a67f1192..0cdedb7f3c3a 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -74,7 +74,7 @@ static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, struct rdt_resource *r = s->res; unsigned long bw_val; - cfg = &d->staged_config[s->conf_type]; + cfg = &d->staged_config[s->conf_type][s->feat_type]; if (cfg->have_new_ctrl) { rdt_last_cmd_printf("Duplicate domain %d\n", d->id); return -EINVAL; @@ -153,7 +153,7 @@ static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s, struct rdt_resource *r = s->res; u32 cbm_val; - cfg = &d->staged_config[s->conf_type]; + cfg = &d->staged_config[s->conf_type][s->feat_type]; if (cfg->have_new_ctrl) { rdt_last_cmd_printf("Duplicate domain %d\n", d->id); return -EINVAL; @@ -203,9 +203,10 @@ static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s, return 0; } -static ctrlval_parser_t *get_parser(struct rdt_resource *res) +static ctrlval_parser_t *get_parser(struct resctrl_schema *s) { - if (res->fflags & RFTYPE_RES_CACHE) + if ((s->res->fflags & RFTYPE_RES_CACHE) && + (s->feat_type == FEAT_PBM)) return &parse_cbm; else return &parse_bw; @@ -220,8 +221,9 @@ static ctrlval_parser_t *get_parser(struct rdt_resource *res) static int parse_line(char *line, struct resctrl_schema *s, struct rdtgroup *rdtgrp) { - ctrlval_parser_t *parse_ctrlval = get_parser(s->res); + ctrlval_parser_t *parse_ctrlval = get_parser(s); enum resctrl_conf_type t = s->conf_type; + enum resctrl_feat_type f = s->feat_type; struct resctrl_staged_config *cfg; struct rdt_resource *r = s->res; struct rdt_parse_data data; @@ -255,7 +257,7 @@ static int parse_line(char *line, struct resctrl_schema *s, if (parse_ctrlval(&data, s, d)) return -EINVAL; if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) { - cfg = &d->staged_config[t]; + cfg = &d->staged_config[t][f]; /* * In pseudo-locking setup mode and just * parsed a valid CBM that should be @@ -373,10 +375,14 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of, static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int closid) { struct rdt_resource *r = schema->res; + const char *format_str; struct rdt_domain *dom; bool sep = false; u32 ctrl_val; + format_str = (schema->feat_type == FEAT_PBM) ? + "%d=%0*x" : "%d=%0*u"; + /* Walking r->domains, ensure it can't race with cpuhp */ lockdep_assert_cpus_held(); @@ -389,9 +395,10 @@ static void show_doms(struct seq_file *s, struct resctrl_schema *schema, int clo ctrl_val = dom->mbps_val[closid]; else ctrl_val = resctrl_arch_get_config(r, dom, closid, - schema->conf_type); + schema->conf_type, + schema->feat_type); - seq_printf(s, r->format_str, dom->id, max_data_width, + seq_printf(s, format_str, dom->id, max_data_width, ctrl_val); sep = true; } diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c index 7d824dc8fa90..77f4818e03af 100644 --- a/fs/resctrl/monitor.c +++ b/fs/resctrl/monitor.c @@ -494,7 +494,7 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm) delta_bw = pmbm_data->delta_bw; /* MBA resource doesn't support CDP */ - cur_msr_val = resctrl_arch_get_config(r_mba, dom_mba, closid, CDP_NONE); + cur_msr_val = resctrl_arch_get_config(r_mba, dom_mba, closid, CDP_NONE, FEAT_MAX); /* * For Ctrl groups read data from child monitor groups. @@ -529,7 +529,8 @@ static void update_mba_bw(struct rdtgroup *rgrp, struct rdt_domain *dom_mbm) return; } - resctrl_arch_update_one(r_mba, dom_mba, closid, CDP_NONE, new_msr_val); + resctrl_arch_update_one(r_mba, dom_mba, closid, CDP_NONE, + FEAT_MAX, new_msr_val); /* * Delta values are updated dynamically package wise for each diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 4b38a68cc0f3..21ddd5abab49 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -1182,7 +1182,8 @@ static int rdt_bit_usage_show(struct kernfs_open_file *of, if (!closid_allocated(i)) continue; ctrl_val = resctrl_arch_get_config(r, dom, i, - s->conf_type); + s->conf_type, + s->feat_type); mode = rdtgroup_mode_by_closid(i); switch (mode) { case RDT_MODE_SHAREABLE: @@ -1411,7 +1412,7 @@ static bool __rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d /* Check for overlap with other resource groups */ for (i = 0; i < closids_supported(); i++) { - ctrl_b = resctrl_arch_get_config(r, d, i, type); + ctrl_b = resctrl_arch_get_config(r, d, i, type, FEAT_PBM); mode = rdtgroup_mode_by_closid(i); if (closid_allocated(i) && i != closid && mode != RDT_MODE_PSEUDO_LOCKSETUP) { @@ -1461,6 +1462,7 @@ bool rdtgroup_cbm_overlaps(struct resctrl_schema *s, struct rdt_domain *d, if (!resctrl_arch_get_cdp_enabled(r->rid)) return false; + return __rdtgroup_cbm_overlaps(r, d, cbm, closid, peer_type, exclusive); } @@ -1496,7 +1498,8 @@ static bool rdtgroup_mode_test_exclusive(struct rdtgroup *rdtgrp) has_cache = true; list_for_each_entry(d, &r->domains, list) { ctrl = resctrl_arch_get_config(r, d, closid, - s->conf_type); + s->conf_type, + s->feat_type); if (rdtgroup_cbm_overlaps(s, d, ctrl, closid, false)) { rdt_last_cmd_puts("Schemata overlaps\n"); return false; @@ -1629,6 +1632,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of, { struct resctrl_schema *schema; enum resctrl_conf_type type; + enum resctrl_feat_type feat; struct rdtgroup *rdtgrp; struct rdt_resource *r; struct rdt_domain *d; @@ -1665,6 +1669,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of, list_for_each_entry(schema, &resctrl_schema_all, list) { r = schema->res; type = schema->conf_type; + feat = schema->feat_type; sep = false; seq_printf(s, "%*s:", max_name_width, schema->name); list_for_each_entry(d, &r->domains, list) { @@ -1678,12 +1683,13 @@ static int rdtgroup_size_show(struct kernfs_open_file *of, else ctrl = resctrl_arch_get_config(r, d, closid, - type); - if (r->rid == RDT_RESOURCE_MBA || - r->rid == RDT_RESOURCE_SMBA) - size = ctrl; - else + type, + feat); + if ((r->fflags & RFTYPE_RES_CACHE) && + feat == FEAT_PBM) size = rdtgroup_cbm_to_size(r, d, ctrl); + else + size = ctrl; } seq_printf(s, "%d=%u", d->id, size); sep = true; @@ -2293,6 +2299,20 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn) /* loop over enabled controls, these are all alloc_capable */ list_for_each_entry(s, &resctrl_schema_all, list) { r = s->res; + + /* + * Only CPBM and MB MAX are supported to create partition + * information folders under the resctrl/info. + */ + if (r->fflags & RFTYPE_RES_CACHE) { + if (s->feat_type != FEAT_PBM) + continue; + + } else if (r->fflags & RFTYPE_RES_MB) { + if (s->feat_type != FEAT_MAX) + continue; + } + fflags = r->fflags | RFTYPE_CTRL_INFO; ret = rdtgroup_mkdir_info_resdir(s, s->name, fflags); if (ret) @@ -2543,22 +2563,17 @@ static int rdt_enable_ctx(struct rdt_fs_context *ctx) return ret; } -static int schemata_list_add(struct rdt_resource *r, enum resctrl_conf_type type) +static int schemata_list_add(struct rdt_resource *r, + enum resctrl_conf_type type, + enum resctrl_feat_type feat) { struct resctrl_schema *s; - const char *suffix = ""; + const char *suffix; int ret, cl; - s = kzalloc(sizeof(*s), GFP_KERNEL); - if (!s) - return -ENOMEM; - - s->res = r; - s->num_closid = resctrl_arch_get_num_closid(r); - if (resctrl_arch_get_cdp_enabled(r->rid)) - s->num_closid /= 2; + if (!resctrl_arch_feat_capable(r->rid, feat)) + return 0; - s->conf_type = type; switch (type) { case CDP_CODE: suffix = "CODE"; @@ -2569,9 +2584,25 @@ static int schemata_list_add(struct rdt_resource *r, enum resctrl_conf_type type case CDP_NONE: suffix = ""; break; + default: + return -EINVAL; } - ret = snprintf(s->name, sizeof(s->name), "%s%s", r->name, suffix); + s = kzalloc(sizeof(*s), GFP_KERNEL); + if (!s) + return -ENOMEM; + + s->res = r; + s->num_closid = resctrl_arch_get_num_closid(r); + if (resctrl_arch_get_cdp_enabled(r->rid)) + s->num_closid /= 2; + + s->conf_type = type; + s->feat_type = feat; + + ret = snprintf(s->name, sizeof(s->name), "%s%s%s", + r->name, suffix, + resctrl_arch_get_feat_lab(feat, r->fflags)); if (ret >= sizeof(s->name)) { kfree(s); return -EINVAL; @@ -2604,29 +2635,33 @@ static int schemata_list_add(struct rdt_resource *r, enum resctrl_conf_type type static int schemata_list_create(void) { + enum resctrl_feat_type feat; enum resctrl_res_level i; struct rdt_resource *r; int ret = 0; for (i = 0; i < RDT_NUM_RESOURCES; i++) { r = resctrl_arch_get_resource(i); - if (!r->alloc_capable) + if (!r || !r->alloc_capable) continue; - if (resctrl_arch_get_cdp_enabled(r->rid)) { - ret = schemata_list_add(r, CDP_CODE); - if (ret) - break; + for (feat = 0; feat < FEAT_NUM_TYPES; feat++) { + if (resctrl_arch_get_cdp_enabled(r->rid)) { + ret = schemata_list_add(r, CDP_CODE, feat); + if (ret) + goto out; - ret = schemata_list_add(r, CDP_DATA); - } else { - ret = schemata_list_add(r, CDP_NONE); + ret = schemata_list_add(r, CDP_DATA, feat); + if (ret) + goto out; + } else { + ret = schemata_list_add(r, CDP_NONE, feat); + if (ret) + goto out; + } } - - if (ret) - break; } - +out: return ret; } @@ -3198,6 +3233,7 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s, { enum resctrl_conf_type peer_type = resctrl_peer_type(s->conf_type); enum resctrl_conf_type t = s->conf_type; + enum resctrl_feat_type feat = s->feat_type; struct resctrl_staged_config *cfg; struct rdt_resource *r = s->res; u32 used_b = 0, unused_b = 0; @@ -3206,7 +3242,7 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s, u32 peer_ctl, ctrl_val; int i; - cfg = &d->staged_config[t]; + cfg = &d->staged_config[t][feat]; cfg->have_new_ctrl = false; cfg->new_ctrl = r->cache.shareable_bits; used_b = r->cache.shareable_bits; @@ -3227,11 +3263,13 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s, */ if (resctrl_arch_get_cdp_enabled(r->rid)) peer_ctl = resctrl_arch_get_config(r, d, i, - peer_type); + peer_type, + feat); else peer_ctl = 0; ctrl_val = resctrl_arch_get_config(r, d, i, - s->conf_type); + s->conf_type, + feat); used_b |= ctrl_val | peer_ctl; if (mode == RDT_MODE_SHAREABLE) cfg->new_ctrl |= ctrl_val | peer_ctl; @@ -3297,7 +3335,7 @@ static void rdtgroup_init_mba(struct rdt_resource *r, u32 closid) continue; } - cfg = &d->staged_config[CDP_NONE]; + cfg = &d->staged_config[CDP_NONE][FEAT_MAX]; cfg->new_ctrl = r->default_ctrl; cfg->have_new_ctrl = true; } @@ -3320,9 +3358,11 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp) if (is_mba_sc(r)) continue; } else { - ret = rdtgroup_init_cat(s, rdtgrp->closid); - if (ret < 0) - goto out; + if (s->feat_type == FEAT_PBM) { + ret = rdtgroup_init_cat(s, rdtgrp->closid); + if (ret < 0) + goto out; + } } ret = resctrl_arch_update_domains(r, rdtgrp->closid); diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index c80f220d98d6..571380c6116d 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -68,6 +68,11 @@ bool resctrl_arch_is_mbm_local_enabled(void); bool resctrl_arch_is_mbm_total_enabled(void); bool resctrl_arch_would_mbm_overflow(void); +bool resctrl_arch_feat_capable(enum resctrl_res_level level, + enum resctrl_feat_type feat); +const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, + unsigned long fflags); + /* reset cached configurations, then all devices */ void resctrl_arch_reset_resources(void); diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h index 61ff7dd5d74c..1a4d8612c62b 100644 --- a/include/linux/resctrl.h +++ b/include/linux/resctrl.h @@ -118,7 +118,7 @@ struct rdt_domain { int mbm_work_cpu; int cqm_work_cpu; struct pseudo_lock_region *plr; - struct resctrl_staged_config staged_config[CDP_NUM_TYPES]; + struct resctrl_staged_config staged_config[CDP_NUM_TYPES][FEAT_NUM_TYPES]; u32 *mbps_val; }; @@ -234,8 +234,9 @@ struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l); */ struct resctrl_schema { struct list_head list; - char name[8]; + char name[16]; enum resctrl_conf_type conf_type; + enum resctrl_feat_type feat_type; struct rdt_resource *res; u32 num_closid; }; @@ -293,9 +294,9 @@ static inline u32 resctrl_get_config_index(u32 closid, case CDP_NONE: return closid; case CDP_CODE: - return (closid * 2) + 1; + return (closid * 2) + 1; case CDP_DATA: - return (closid * 2); + return (closid * 2); } } @@ -331,10 +332,12 @@ resctrl_get_domain_from_cpu(int cpu, struct rdt_resource *r) * Must be called on one of the domain's CPUs. */ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, - u32 closid, enum resctrl_conf_type t, u32 cfg_val); + u32 closid, enum resctrl_conf_type t, + enum resctrl_feat_type f, u32 cfg_val); u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, - u32 closid, enum resctrl_conf_type type); + u32 closid, enum resctrl_conf_type type, + enum resctrl_feat_type feat); int resctrl_online_domain(struct rdt_resource *r, struct rdt_domain *d); void resctrl_offline_domain(struct rdt_resource *r, struct rdt_domain *d); void resctrl_online_cpu(unsigned int cpu); diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h index 44f7a47f986b..bf3de7b28769 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -73,6 +73,18 @@ enum resctrl_conf_type { CDP_DATA, }; +/** + * enum resctrl_feat_type - The feature of configuration. + * @FEAT_PBM: Portion Bit Map, allow the usage of bitmap method for + * resource allocation. + * @FEAT_MAX: Controls the maximum fraction of the resource capacity. + */ +enum resctrl_feat_type { + FEAT_PBM, + FEAT_MAX, + FEAT_NUM_TYPES, +}; + enum resctrl_res_level { RDT_RESOURCE_L3, RDT_RESOURCE_L2, -- 2.25.1

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- Implement mbw_min/cmin feature for mata/cache msc, and provide MBMIN/LxMIN interface in schemata file for user. On some specific platforms, L3 implements the cmin feature, but L2 may not provide it, or vice versa. Therefore, it is necessary to separately determine whether the cache msc has implemented the corresponding feature. Before transmitting the cache MIN portion value to msc, need to check whether the CMIN setting from user space is validate or not. The same goes for MBMIN. It should be noted that the new configuration value is in decimal form instead of hexadecimal, so here reuse the parse_bw() to analysis input value for cache msc. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 25 ++++++++--- drivers/platform/mpam/mpam_internal.h | 7 ++- drivers/platform/mpam/mpam_resctrl.c | 61 +++++++++++++++++++++++++-- fs/resctrl/ctrlmondata.c | 34 +++++++++++++-- include/linux/resctrl_types.h | 2 + 5 files changed, 117 insertions(+), 12 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index 0bc8393541f1..e4ee2cd73cc8 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -577,9 +577,13 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) u32 ccap_features = mpam_read_partsel_reg(msc, CCAP_IDR); props->cmax_wd = FIELD_GET(MPAMF_CCAP_IDR_CMAX_WD, ccap_features); - if (props->cmax_wd && - !FIELD_GET(MPAMF_CCAP_IDR_NO_CMAX, ccap_features)) - mpam_set_feature(mpam_feat_ccap_part, props); + if (props->cmax_wd) { + if (!FIELD_GET(MPAMF_CCAP_IDR_NO_CMAX, ccap_features)) + mpam_set_feature(mpam_feat_ccap_part, props); + + if (FIELD_GET(MPAMF_CCAP_IDR_HAS_CMIN, ccap_features)) + mpam_set_feature(mpam_feat_cmin, props); + } } /* Cache Portion partitioning */ @@ -1211,6 +1215,13 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, rprops->cpbm_wd); } + if (mpam_has_feature(mpam_feat_cmin, rprops)) { + if (mpam_has_feature(mpam_feat_cmin, cfg)) + mpam_write_partsel_reg(msc, CMIN, cfg->ca_min); + else + mpam_write_partsel_reg(msc, CMIN, 0); + } + if (mpam_has_feature(mpam_feat_mbw_part, rprops)) { if (mpam_has_feature(mpam_feat_mbw_part, cfg)) mpam_write_partsel_reg(msc, MBW_PBM, cfg->mbw_pbm); @@ -1219,8 +1230,12 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, rprops->mbw_pbm_bits); } - if (mpam_has_feature(mpam_feat_mbw_min, rprops)) - mpam_write_partsel_reg(msc, MBW_MIN, 0); + if (mpam_has_feature(mpam_feat_mbw_min, rprops)) { + if (mpam_has_feature(mpam_feat_mbw_min, cfg)) + mpam_write_partsel_reg(msc, MBW_MIN, cfg->mbw_min); + else + mpam_write_partsel_reg(msc, MBW_MIN, 0); + } if (mpam_has_feature(mpam_feat_mbw_max, rprops)) { if (mpam_has_feature(mpam_feat_mbw_max, cfg)) diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index d8854cc6f78e..b094095abe49 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -86,6 +86,7 @@ typedef u32 mpam_features_t; enum mpam_device_features { mpam_feat_ccap_part = 0, mpam_feat_cpor_part, + mpam_feat_cmin, mpam_feat_mbw_part, mpam_feat_mbw_min, mpam_feat_mbw_max, @@ -160,8 +161,11 @@ struct mpam_config { mpam_features_t features; u32 cpbm; + u16 ca_min; + u32 mbw_pbm; u16 mbw_max; + u16 mbw_min; }; struct mpam_component @@ -340,7 +344,8 @@ void mpam_resctrl_exit(void); /* Configuration and Status Register offsets in the memory mapped page */ #define MPAMCFG_PART_SEL 0x0100 /* partid to configure: */ #define MPAMCFG_CPBM 0x1000 /* cache-portion config */ -#define MPAMCFG_CMAX 0x0108 /* cache-capacity config */ +#define MPAMCFG_CMAX 0x0108 /* cache-capacity max config */ +#define MPAMCFG_CMIN 0x0110 /* cache-capacity min config */ #define MPAMCFG_MBW_MIN 0x0200 /* min mem-bw config */ #define MPAMCFG_MBW_MAX 0x0208 /* max mem-bw config */ #define MPAMCFG_MBW_WINWD 0x0220 /* mem-bw accounting window config */ diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 826acc6183bb..8c62e3b29f24 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -69,16 +69,26 @@ bool resctrl_arch_mon_capable(void) return exposed_mon_capable; } +static bool min_capable[RDT_NUM_RESOURCES]; bool resctrl_arch_feat_capable(enum resctrl_res_level level, enum resctrl_feat_type feat) { - if (feat == FEAT_PBM) { + switch (feat) { + case FEAT_PBM: if (level == RDT_RESOURCE_L3) return true; + break; - } else if (feat == FEAT_MAX) { + case FEAT_MAX: if (level == RDT_RESOURCE_MBA) return true; + break; + + case FEAT_MIN: + return min_capable[level]; + + default: + break; } return false; @@ -87,6 +97,14 @@ bool resctrl_arch_feat_capable(enum resctrl_res_level level, const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, unsigned long fflags) { + switch (feat) { + case FEAT_MIN: + return "MIN"; + + default: + break; + } + return ""; } @@ -829,6 +847,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) exposed_alloc_capable = true; } + if (mpam_has_feature(mpam_feat_cmin, &class->props)) + min_capable[r->rid] = true; + /* * MBWU counters may be 'local' or 'total' depending on where * they are in the topology. Counters on caches are assumed to @@ -870,6 +891,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) exposed_alloc_capable = true; } + if (mpam_has_feature(mpam_feat_mbw_min, cprops)) + min_capable[r->rid] = true; + if (has_mbwu && class->type == MPAM_CLASS_MEMORY) { mbm_total_class = class; r->mon_capable = true; @@ -984,6 +1008,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (feat == FEAT_PBM)) { configured_by = mpam_feat_cpor_part; break; + } else if (mpam_has_feature(mpam_feat_cmin, cprops) && + (feat == FEAT_MIN)) { + configured_by = mpam_feat_cmin; + break; } return -EINVAL; @@ -996,6 +1024,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (feat == FEAT_MAX)) { configured_by = mpam_feat_mbw_max; break; + } else if (mpam_has_feature(mpam_feat_mbw_min, cprops) && + (feat == FEAT_MIN)) { + configured_by = mpam_feat_mbw_min; + break; } fallthrough; default: @@ -1003,18 +1035,29 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, } if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r) || - !mpam_has_feature(configured_by, cfg)) + !mpam_has_feature(configured_by, cfg)) { + if (configured_by == mpam_feat_cmin) + return 0; + + if (configured_by == mpam_feat_mbw_min) + return 0; + return r->default_ctrl; + } switch (configured_by) { case mpam_feat_cpor_part: /* TODO: Scaling is not yet supported */ return cfg->cpbm; + case mpam_feat_cmin: + return mbw_max_to_percent(cfg->ca_min, cprops->cmax_wd); case mpam_feat_mbw_part: /* TODO: Scaling is not yet supported */ return mbw_pbm_to_percent(cfg->mbw_pbm, cprops); case mpam_feat_mbw_max: return mbw_max_to_percent(cfg->mbw_max, cprops->bwa_wd); + case mpam_feat_mbw_min: + return mbw_max_to_percent(cfg->mbw_min, cprops->bwa_wd); default: return -EINVAL; } @@ -1044,6 +1087,8 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r)) return -EINVAL; + cfg = dom->comp->cfg[partid]; + switch (r->rid) { case RDT_RESOURCE_L2: case RDT_RESOURCE_L3: @@ -1053,6 +1098,11 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.cpbm = cfg_val; mpam_set_feature(mpam_feat_cpor_part, &cfg); break; + } else if (mpam_has_feature(mpam_feat_cmin, cprops) && + (f == FEAT_MIN)) { + cfg.ca_min = percent_to_mbw_max(cfg_val, cprops->cmax_wd); + mpam_set_feature(mpam_feat_cmin, &cfg); + break; } return -EINVAL; @@ -1066,6 +1116,11 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.mbw_max = percent_to_mbw_max(cfg_val, cprops->bwa_wd); mpam_set_feature(mpam_feat_mbw_max, &cfg); break; + } else if (mpam_has_feature(mpam_feat_mbw_min, cprops) && + (f == FEAT_MIN)) { + cfg.mbw_min = percent_to_mbw_max(cfg_val, cprops->bwa_wd); + mpam_set_feature(mpam_feat_mbw_min, &cfg); + break; } fallthrough; default: diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index 0cdedb7f3c3a..4a74b71daed8 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -66,6 +66,26 @@ static bool bw_validate(char *buf, unsigned long *data, struct rdt_resource *r) return true; } +static bool deci_validate(char *buf, unsigned long *data, struct rdt_resource *r) +{ + unsigned long deci; + int ret; + + ret = kstrtoul(buf, 10, &deci); + if (ret) { + rdt_last_cmd_printf("Non-decimal digit in value %s\n", buf); + return false; + } + + if (deci > 100) { + rdt_last_cmd_printf("Value %ld out of range [0,100]\n", deci); + return false; + } + + *data = deci; + return true; +} + static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, struct rdt_domain *d) { @@ -80,10 +100,18 @@ static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, return -EINVAL; } - if (!bw_validate(data->buf, &bw_val, r)) - return -EINVAL; + if (r->fflags & RFTYPE_RES_MB) { + if (!bw_validate(data->buf, &bw_val, r)) + return -EINVAL; + + } else { + /* For the RDT_RESOURCE_L3/L2 */ + if (!deci_validate(data->buf, &bw_val, r)) + return -EINVAL; + } - if (is_mba_sc(r)) { + if ((r->fflags & RFTYPE_RES_MB) && (s->feat_type == FEAT_MAX) && + is_mba_sc(r)) { d->mbps_val[closid] = bw_val; return 0; } diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h index bf3de7b28769..270ab3d479e3 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -78,10 +78,12 @@ enum resctrl_conf_type { * @FEAT_PBM: Portion Bit Map, allow the usage of bitmap method for * resource allocation. * @FEAT_MAX: Controls the maximum fraction of the resource capacity. + * @FEAT_MIN: Controls the minimum fraction of the resource capacity. */ enum resctrl_feat_type { FEAT_PBM, FEAT_MAX, + FEAT_MIN, FEAT_NUM_TYPES, }; -- 2.25.1

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- The Priority Partition feature controls the priority of requests attributed to the target PARTID. In addition to the MATA msc implementing priority features, the L3 controller can also have the same features. Here the *MBPRI* and *L3PRI* interface are provided in the schemata file to allow users to configure and query QoS partition settings. Before transmitting the priority value to msc, it needs to check whether the setting from user is validate or not. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 35 ++++++++++++-------- drivers/platform/mpam/mpam_internal.h | 6 ++++ drivers/platform/mpam/mpam_resctrl.c | 47 +++++++++++++++++++++++++-- fs/resctrl/ctrlmondata.c | 33 ++++++++++++++++++- include/linux/resctrl.h | 4 +++ include/linux/resctrl_types.h | 2 ++ 6 files changed, 109 insertions(+), 18 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index e4ee2cd73cc8..e9d03f2abdc3 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -1193,12 +1193,11 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, struct mpam_config *cfg) { u32 pri_val = 0; + u16 intpri, dspri; u16 cmax = MPAMCFG_CMAX_CMAX; struct mpam_msc *msc = ris->msc; u16 bwa_fract = MPAMCFG_MBW_MAX_MAX; struct mpam_props *rprops = &ris->props; - u16 dspri = GENMASK(rprops->dspri_wd, 0); - u16 intpri = GENMASK(rprops->intpri_wd, 0); spin_lock(&msc->part_sel_lock); __mpam_part_sel(ris->ris_idx, partid, msc); @@ -1250,21 +1249,29 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, if (mpam_has_feature(mpam_feat_ccap_part, rprops)) mpam_write_partsel_reg(msc, CMAX, cmax); - if (mpam_has_feature(mpam_feat_intpri_part, rprops) || - mpam_has_feature(mpam_feat_dspri_part, rprops)) { - /* aces high? */ - if (!mpam_has_feature(mpam_feat_intpri_part_0_low, rprops)) - intpri = 0; - if (!mpam_has_feature(mpam_feat_dspri_part_0_low, rprops)) - dspri = 0; - - if (mpam_has_feature(mpam_feat_intpri_part, rprops)) + if (mpam_has_feature(mpam_feat_intpri_part_0_low, rprops)) + intpri = GENMASK(rprops->intpri_wd - 1, 0); + else + intpri = 0; + + if (mpam_has_feature(mpam_feat_intpri_part, rprops)) { + if (mpam_has_feature(mpam_feat_intpri_part, cfg)) + pri_val |= FIELD_PREP(MPAMCFG_PRI_INTPRI, cfg->intpri); + else pri_val |= FIELD_PREP(MPAMCFG_PRI_INTPRI, intpri); - if (mpam_has_feature(mpam_feat_dspri_part, rprops)) - pri_val |= FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri); + } + if (mpam_has_feature(mpam_feat_dspri_part_0_low, rprops)) + dspri = GENMASK(rprops->dspri_wd - 1, 0); + else + dspri = 0; + + if (mpam_has_feature(mpam_feat_dspri_part, rprops)) + pri_val |= FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri); + + if (mpam_has_feature(mpam_feat_intpri_part, rprops) || + mpam_has_feature(mpam_feat_dspri_part, rprops)) mpam_write_partsel_reg(msc, PRI, pri_val); - } spin_unlock(&msc->part_sel_lock); } diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index b094095abe49..2b0bc33e5efa 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -166,6 +166,12 @@ struct mpam_config { u32 mbw_pbm; u16 mbw_max; u16 mbw_min; + + /* + * dspri is downstream priority, intpri is internal priority. + */ + u16 dspri; + u16 intpri; }; struct mpam_component diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 8c62e3b29f24..16857f5929c1 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -70,6 +70,7 @@ bool resctrl_arch_mon_capable(void) } static bool min_capable[RDT_NUM_RESOURCES]; +static bool intpri_capable[RDT_NUM_RESOURCES]; bool resctrl_arch_feat_capable(enum resctrl_res_level level, enum resctrl_feat_type feat) { @@ -87,6 +88,9 @@ bool resctrl_arch_feat_capable(enum resctrl_res_level level, case FEAT_MIN: return min_capable[level]; + case FEAT_INTPRI: + return intpri_capable[level]; + default: break; } @@ -101,6 +105,9 @@ const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, case FEAT_MIN: return "MIN"; + case FEAT_INTPRI: + return "PRI"; + default: break; } @@ -824,6 +831,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) /* TODO: Scaling is not yet supported */ r->cache.cbm_len = class->props.cpbm_wd; r->cache.arch_has_sparse_bitmasks = true; + r->cache.intpri_wd = class->props.intpri_wd; /* mpam_devices will reject empty bitmaps */ r->cache.min_cbm_bits = 1; @@ -850,6 +858,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) if (mpam_has_feature(mpam_feat_cmin, &class->props)) min_capable[r->rid] = true; + if (mpam_has_feature(mpam_feat_intpri_part, &class->props)) + intpri_capable[r->rid] = true; + /* * MBWU counters may be 'local' or 'total' depending on where * they are in the topology. Counters on caches are assumed to @@ -881,6 +892,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) r->membw.delay_linear = true; r->membw.throttle_mode = THREAD_THROTTLE_UNDEFINED; r->membw.bw_gran = get_mba_granularity(cprops); + r->membw.intpri_wd = class->props.intpri_wd; /* Round up to at least 1% */ if (!r->membw.bw_gran) @@ -894,6 +906,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) if (mpam_has_feature(mpam_feat_mbw_min, cprops)) min_capable[r->rid] = true; + if (mpam_has_feature(mpam_feat_intpri_part, cprops)) + intpri_capable[r->rid] = true; + if (has_mbwu && class->type == MPAM_CLASS_MEMORY) { mbm_total_class = class; r->mon_capable = true; @@ -1012,6 +1027,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (feat == FEAT_MIN)) { configured_by = mpam_feat_cmin; break; + } else if (mpam_has_feature(mpam_feat_intpri_part, cprops) && + (feat == FEAT_INTPRI)) { + configured_by = mpam_feat_intpri_part; + break; } return -EINVAL; @@ -1028,6 +1047,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (feat == FEAT_MIN)) { configured_by = mpam_feat_mbw_min; break; + } else if (mpam_has_feature(mpam_feat_intpri_part, cprops) && + (feat == FEAT_INTPRI)) { + configured_by = mpam_feat_intpri_part; + break; } fallthrough; default: @@ -1036,11 +1059,16 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r) || !mpam_has_feature(configured_by, cfg)) { - if (configured_by == mpam_feat_cmin) + if ((configured_by == mpam_feat_cmin) || + (configured_by == mpam_feat_mbw_min)) return 0; - if (configured_by == mpam_feat_mbw_min) - return 0; + if (configured_by == mpam_feat_intpri_part) { + if (!mpam_has_feature(mpam_feat_intpri_part_0_low, cprops)) + return 0; + + return (u32)GENMASK(cprops->intpri_wd - 1, 0); + } return r->default_ctrl; } @@ -1058,6 +1086,8 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, return mbw_max_to_percent(cfg->mbw_max, cprops->bwa_wd); case mpam_feat_mbw_min: return mbw_max_to_percent(cfg->mbw_min, cprops->bwa_wd); + case mpam_feat_intpri_part: + return cfg->intpri; default: return -EINVAL; } @@ -1103,6 +1133,11 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.ca_min = percent_to_mbw_max(cfg_val, cprops->cmax_wd); mpam_set_feature(mpam_feat_cmin, &cfg); break; + } else if (mpam_has_feature(mpam_feat_intpri_part, cprops) && + (f == FEAT_INTPRI)) { + cfg.intpri = cfg_val; + mpam_set_feature(mpam_feat_intpri_part, &cfg); + break; } return -EINVAL; @@ -1121,7 +1156,13 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.mbw_min = percent_to_mbw_max(cfg_val, cprops->bwa_wd); mpam_set_feature(mpam_feat_mbw_min, &cfg); break; + } else if (mpam_has_feature(mpam_feat_intpri_part, cprops) && + (f == FEAT_INTPRI)) { + cfg.intpri = cfg_val; + mpam_set_feature(mpam_feat_intpri_part, &cfg); + break; } + fallthrough; default: return -EINVAL; diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index 4a74b71daed8..a4a971c34db8 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -86,6 +86,32 @@ static bool deci_validate(char *buf, unsigned long *data, struct rdt_resource *r return true; } +static bool prio_validate(char *buf, unsigned long *data, struct rdt_resource *r) +{ + unsigned long prio, prio_max; + int ret; + + ret = kstrtoul(buf, 10, &prio); + if (ret) { + rdt_last_cmd_printf("Non-decimal digit in PRIO value %s\n", buf); + return false; + } + + if (r->fflags & RFTYPE_RES_CACHE) + prio_max = GENMASK(r->cache.intpri_wd - 1, 0); + else + prio_max = GENMASK(r->membw.intpri_wd - 1, 0); + + if (prio > prio_max) { + rdt_last_cmd_printf("PRIO value %ld out of range [0,%ld]\n", + prio, prio_max); + return false; + } + + *data = prio; + return true; +} + static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, struct rdt_domain *d) { @@ -100,7 +126,12 @@ static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, return -EINVAL; } - if (r->fflags & RFTYPE_RES_MB) { + if (s->feat_type == FEAT_INTPRI) { + if (!prio_validate(data->buf, &bw_val, r)) + return -EINVAL; + + } else if (r->fflags & RFTYPE_RES_MB) { + /* For FEAT_MAX and FEAT_MIN */ if (!bw_validate(data->buf, &bw_val, r)) return -EINVAL; diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h index 1a4d8612c62b..34b246105c78 100644 --- a/include/linux/resctrl.h +++ b/include/linux/resctrl.h @@ -133,6 +133,7 @@ struct rdt_domain { * @arch_has_sparse_bitmasks: True if a bitmask like f00f is valid. * @arch_has_per_cpu_cfg: True if QOS_CFG register for this cache * level has CPU scope. + * @intpri_wd: Number of implemented bits in the priority partition. */ struct resctrl_cache { unsigned int cbm_len; @@ -140,6 +141,7 @@ struct resctrl_cache { unsigned int shareable_bits; bool arch_has_sparse_bitmasks; bool arch_has_per_cpu_cfg; + unsigned int intpri_wd; }; /** @@ -166,6 +168,7 @@ enum membw_throttle_mode { * different memory bandwidths * @mba_sc: True if MBA software controller(mba_sc) is enabled * @mb_map: Mapping of memory B/W percentage to memory B/W delay + * @intpri_wd: Number of implemented bits in the priority partition. */ struct resctrl_membw { u32 min_bw; @@ -175,6 +178,7 @@ struct resctrl_membw { enum membw_throttle_mode throttle_mode; bool mba_sc; u32 *mb_map; + u32 intpri_wd; }; /** diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h index 270ab3d479e3..37b5cfbdecc7 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -79,11 +79,13 @@ enum resctrl_conf_type { * resource allocation. * @FEAT_MAX: Controls the maximum fraction of the resource capacity. * @FEAT_MIN: Controls the minimum fraction of the resource capacity. + * @FEAT_INTPRI:Controls the priority for the resource. */ enum resctrl_feat_type { FEAT_PBM, FEAT_MAX, FEAT_MIN, + FEAT_INTPRI, FEAT_NUM_TYPES, }; -- 2.25.1

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- Implement the cmax feature, which controls the cache maximum capacity for the PARTID selected by the MPAMCFG_PART_SEL. User can update CMAX settings by the interface {L2,L3}MAX:$domain_id=$value in the schemata file. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 11 ++++++--- drivers/platform/mpam/mpam_internal.h | 1 + drivers/platform/mpam/mpam_resctrl.c | 34 ++++++++++++++++++++++++--- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index e9d03f2abdc3..637cf13052a6 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -1214,6 +1214,14 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, rprops->cpbm_wd); } + if (mpam_has_feature(mpam_feat_ccap_part, rprops)) { + if (mpam_has_feature(mpam_feat_ccap_part, cfg)) + mpam_write_partsel_reg(msc, CMAX, cfg->ca_max); + else + mpam_write_partsel_reg(msc, CMAX, cmax); + + } + if (mpam_has_feature(mpam_feat_cmin, rprops)) { if (mpam_has_feature(mpam_feat_cmin, cfg)) mpam_write_partsel_reg(msc, CMIN, cfg->ca_min); @@ -1246,9 +1254,6 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, if (mpam_has_feature(mpam_feat_mbw_prop, rprops)) mpam_write_partsel_reg(msc, MBW_PROP, bwa_fract); - if (mpam_has_feature(mpam_feat_ccap_part, rprops)) - mpam_write_partsel_reg(msc, CMAX, cmax); - if (mpam_has_feature(mpam_feat_intpri_part_0_low, rprops)) intpri = GENMASK(rprops->intpri_wd - 1, 0); else diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index 2b0bc33e5efa..935184bba45b 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -161,6 +161,7 @@ struct mpam_config { mpam_features_t features; u32 cpbm; + u16 ca_max; u16 ca_min; u32 mbw_pbm; diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 16857f5929c1..4f43d6718836 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -69,6 +69,7 @@ bool resctrl_arch_mon_capable(void) return exposed_mon_capable; } +static bool max_capable[RDT_NUM_RESOURCES]; static bool min_capable[RDT_NUM_RESOURCES]; static bool intpri_capable[RDT_NUM_RESOURCES]; bool resctrl_arch_feat_capable(enum resctrl_res_level level, @@ -81,9 +82,7 @@ bool resctrl_arch_feat_capable(enum resctrl_res_level level, break; case FEAT_MAX: - if (level == RDT_RESOURCE_MBA) - return true; - break; + return max_capable[level]; case FEAT_MIN: return min_capable[level]; @@ -102,6 +101,11 @@ const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, unsigned long fflags) { switch (feat) { + case FEAT_MAX: + if (fflags & RFTYPE_RES_MB) + break; + return "MAX"; + case FEAT_MIN: return "MIN"; @@ -855,6 +859,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) exposed_alloc_capable = true; } + if (mpam_has_feature(mpam_feat_ccap_part, &class->props)) + max_capable[r->rid] = true; + if (mpam_has_feature(mpam_feat_cmin, &class->props)) min_capable[r->rid] = true; @@ -901,6 +908,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) if (class_has_usable_mba(cprops)) { r->alloc_capable = true; exposed_alloc_capable = true; + + if (mpam_has_feature(mpam_feat_mbw_max, cprops)) + max_capable[r->rid] = true; } if (mpam_has_feature(mpam_feat_mbw_min, cprops)) @@ -1023,6 +1033,12 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (feat == FEAT_PBM)) { configured_by = mpam_feat_cpor_part; break; + + } else if (mpam_has_feature(mpam_feat_ccap_part, cprops) && + (feat == FEAT_MAX)) { + configured_by = mpam_feat_ccap_part; + break; + } else if (mpam_has_feature(mpam_feat_cmin, cprops) && (feat == FEAT_MIN)) { configured_by = mpam_feat_cmin; @@ -1059,6 +1075,11 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r) || !mpam_has_feature(configured_by, cfg)) { + + if ((configured_by == mpam_feat_ccap_part) || + (configured_by == mpam_feat_mbw_max)) + return MAX_MBA_BW; + if ((configured_by == mpam_feat_cmin) || (configured_by == mpam_feat_mbw_min)) return 0; @@ -1077,6 +1098,8 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, case mpam_feat_cpor_part: /* TODO: Scaling is not yet supported */ return cfg->cpbm; + case mpam_feat_ccap_part: + return mbw_max_to_percent(cfg->ca_max, cprops->cmax_wd); case mpam_feat_cmin: return mbw_max_to_percent(cfg->ca_min, cprops->cmax_wd); case mpam_feat_mbw_part: @@ -1128,6 +1151,11 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.cpbm = cfg_val; mpam_set_feature(mpam_feat_cpor_part, &cfg); break; + } else if (mpam_has_feature(mpam_feat_ccap_part, cprops) && + (f == FEAT_MAX)) { + cfg.ca_max = percent_to_mbw_max(cfg_val, cprops->cmax_wd); + mpam_set_feature(mpam_feat_ccap_part, &cfg); + break; } else if (mpam_has_feature(mpam_feat_cmin, cprops) && (f == FEAT_MIN)) { cfg.ca_min = percent_to_mbw_max(cfg_val, cprops->cmax_wd); -- 2.25.1

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- Support both of CPBM and MBW_PBM features, which provides the cache and memory bandwidth portion bitmap. User can update PBM settings by the interface {L2,L3,MBPBM}:$domain_id=$value in the schemata file. Software would update the MPAMCFG_CPBM<n> register to configure which cache portions the PARTID is allowed to allocate. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 4f43d6718836..ff1b11c79f46 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -69,6 +69,7 @@ bool resctrl_arch_mon_capable(void) return exposed_mon_capable; } +static bool pbm_capable[RDT_NUM_RESOURCES]; static bool max_capable[RDT_NUM_RESOURCES]; static bool min_capable[RDT_NUM_RESOURCES]; static bool intpri_capable[RDT_NUM_RESOURCES]; @@ -77,9 +78,7 @@ bool resctrl_arch_feat_capable(enum resctrl_res_level level, { switch (feat) { case FEAT_PBM: - if (level == RDT_RESOURCE_L3) - return true; - break; + return pbm_capable[level]; case FEAT_MAX: return max_capable[level]; @@ -101,6 +100,11 @@ const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, unsigned long fflags) { switch (feat) { + case FEAT_PBM: + if (fflags & RFTYPE_RES_CACHE) + break; + return "PBM"; + case FEAT_MAX: if (fflags & RFTYPE_RES_MB) break; @@ -857,6 +861,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) if (mpam_has_feature(mpam_feat_cpor_part, &class->props)) { r->alloc_capable = true; exposed_alloc_capable = true; + pbm_capable[r->rid] = true; } if (mpam_has_feature(mpam_feat_ccap_part, &class->props)) @@ -909,6 +914,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) r->alloc_capable = true; exposed_alloc_capable = true; + if (mpam_has_feature(mpam_feat_mbw_part, cprops)) + pbm_capable[r->rid] = true; + if (mpam_has_feature(mpam_feat_mbw_max, cprops)) max_capable[r->rid] = true; } @@ -1076,6 +1084,11 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, if (!r->alloc_capable || partid >= resctrl_arch_get_num_closid(r) || !mpam_has_feature(configured_by, cfg)) { + if (configured_by == mpam_feat_cpor_part) + return BIT_MASK(cprops->cpbm_wd) - 1; + if (configured_by == mpam_feat_mbw_part) + return BIT_MASK(cprops->mbw_pbm_bits) - 1; + if ((configured_by == mpam_feat_ccap_part) || (configured_by == mpam_feat_mbw_max)) return MAX_MBA_BW; -- 2.25.1

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- Allow users can configure the mata hard-limit feature and cache soft-limit feature by the schemata {MB,L3}HDL:$domain_id=$value interface under the resctrl fs. When MAX bandwidth is exceeded, the hard-limit feature not allows the partition use any more bandwidth until the memory bandwidth measurement for the partition falls below MAX. When CMAX cache capacity is exceeded, the soft-limit allows the partition to allocate capacity beyond CMAX, but only from invalid lines or lines belonging to disabled PARTIDs. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_devices.c | 32 +++++++++++++++++---- drivers/platform/mpam/mpam_internal.h | 4 +++ drivers/platform/mpam/mpam_resctrl.c | 41 ++++++++++++++++++++++++++- fs/resctrl/ctrlmondata.c | 24 ++++++++++++++++ include/linux/resctrl_types.h | 4 +++ 5 files changed, 99 insertions(+), 6 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index 637cf13052a6..72f0f8c2db0d 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -578,9 +578,13 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) props->cmax_wd = FIELD_GET(MPAMF_CCAP_IDR_CMAX_WD, ccap_features); if (props->cmax_wd) { - if (!FIELD_GET(MPAMF_CCAP_IDR_NO_CMAX, ccap_features)) + if (!FIELD_GET(MPAMF_CCAP_IDR_NO_CMAX, ccap_features)) { mpam_set_feature(mpam_feat_ccap_part, props); + if (FIELD_GET(MPAMF_CCAP_IDR_HAS_CMAX_SOFTLIM, ccap_features)) + mpam_set_feature(mpam_feat_max_limit, props); + } + if (FIELD_GET(MPAMF_CCAP_IDR_HAS_CMIN, ccap_features)) mpam_set_feature(mpam_feat_cmin, props); } @@ -606,8 +610,10 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) mpam_set_feature(mpam_feat_mbw_part, props); props->bwa_wd = FIELD_GET(MPAMF_MBW_IDR_BWA_WD, mbw_features); - if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_MAX, mbw_features)) + if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_MAX, mbw_features)) { mpam_set_feature(mpam_feat_mbw_max, props); + mpam_set_feature(mpam_feat_max_limit, props); + } if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_MIN, mbw_features)) mpam_set_feature(mpam_feat_mbw_min, props); @@ -1192,6 +1198,7 @@ static void mpam_reset_msc_bitmap(struct mpam_msc *msc, u16 reg, u16 wd) static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, struct mpam_config *cfg) { + bool limit; u32 pri_val = 0; u16 intpri, dspri; u16 cmax = MPAMCFG_CMAX_CMAX; @@ -1216,10 +1223,17 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, if (mpam_has_feature(mpam_feat_ccap_part, rprops)) { if (mpam_has_feature(mpam_feat_ccap_part, cfg)) - mpam_write_partsel_reg(msc, CMAX, cfg->ca_max); + cmax = cfg->ca_max; + + if (mpam_has_feature(mpam_feat_max_limit, cfg)) + limit = cfg->max_limit; else - mpam_write_partsel_reg(msc, CMAX, cmax); + limit = true; + if (limit) + mpam_write_partsel_reg(msc, CMAX, cmax); + else + mpam_write_partsel_reg(msc, CMAX, cmax | MPAMCFG_CMAX_CMAX_SOFTLIM); } if (mpam_has_feature(mpam_feat_cmin, rprops)) { @@ -1246,9 +1260,17 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, if (mpam_has_feature(mpam_feat_mbw_max, rprops)) { if (mpam_has_feature(mpam_feat_mbw_max, cfg)) - mpam_write_partsel_reg(msc, MBW_MAX, cfg->mbw_max | MPAMCFG_MBW_MAX_HARDLIM); + bwa_fract = cfg->mbw_max; + + if (mpam_has_feature(mpam_feat_max_limit, cfg)) + limit = cfg->max_limit; else + limit = false; + + if (!limit) mpam_write_partsel_reg(msc, MBW_MAX, bwa_fract); + else + mpam_write_partsel_reg(msc, MBW_MAX, bwa_fract | MPAMCFG_MBW_MAX_HARDLIM); } if (mpam_has_feature(mpam_feat_mbw_prop, rprops)) diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index 935184bba45b..d36d4bd7c618 100644 --- a/drivers/platform/mpam/mpam_internal.h +++ b/drivers/platform/mpam/mpam_internal.h @@ -110,6 +110,7 @@ enum mpam_device_features { mpam_feat_msmon_mbwu_rwbw, mpam_feat_msmon_capt, mpam_feat_partid_nrw, + mpam_feat_max_limit, MPAM_FEATURE_LAST, }; #define MPAM_ALL_FEATURES ((1<<MPAM_FEATURE_LAST) - 1) @@ -173,6 +174,8 @@ struct mpam_config { */ u16 dspri; u16 intpri; + + bool max_limit; }; struct mpam_component @@ -459,6 +462,7 @@ void mpam_resctrl_exit(void); /* MPAMCFG_CMAX - MPAM cache portion bitmap partition configuration register */ #define MPAMCFG_CMAX_CMAX GENMASK(15, 0) +#define MPAMCFG_CMAX_CMAX_SOFTLIM BIT(31) /* * MPAMCFG_MBW_MIN - MPAM memory minimum bandwidth partitioning configuration diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index ff1b11c79f46..e36b3467a14d 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -71,6 +71,7 @@ bool resctrl_arch_mon_capable(void) static bool pbm_capable[RDT_NUM_RESOURCES]; static bool max_capable[RDT_NUM_RESOURCES]; +static bool lim_capable[RDT_NUM_RESOURCES]; static bool min_capable[RDT_NUM_RESOURCES]; static bool intpri_capable[RDT_NUM_RESOURCES]; bool resctrl_arch_feat_capable(enum resctrl_res_level level, @@ -83,6 +84,9 @@ bool resctrl_arch_feat_capable(enum resctrl_res_level level, case FEAT_MAX: return max_capable[level]; + case FEAT_LIMIT: + return lim_capable[level]; + case FEAT_MIN: return min_capable[level]; @@ -110,6 +114,9 @@ const char *resctrl_arch_get_feat_lab(enum resctrl_feat_type feat, break; return "MAX"; + case FEAT_LIMIT: + return "HDL"; + case FEAT_MIN: return "MIN"; @@ -873,6 +880,9 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) if (mpam_has_feature(mpam_feat_intpri_part, &class->props)) intpri_capable[r->rid] = true; + if (mpam_has_feature(mpam_feat_max_limit, &class->props)) + lim_capable[r->rid] = true; + /* * MBWU counters may be 'local' or 'total' depending on where * they are in the topology. Counters on caches are assumed to @@ -917,8 +927,10 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) if (mpam_has_feature(mpam_feat_mbw_part, cprops)) pbm_capable[r->rid] = true; - if (mpam_has_feature(mpam_feat_mbw_max, cprops)) + if (mpam_has_feature(mpam_feat_mbw_max, cprops)) { max_capable[r->rid] = true; + lim_capable[r->rid] = true; + } } if (mpam_has_feature(mpam_feat_mbw_min, cprops)) @@ -1047,6 +1059,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, configured_by = mpam_feat_ccap_part; break; + } else if (mpam_has_feature(mpam_feat_max_limit, cprops) && + (feat == FEAT_LIMIT)) { + configured_by = mpam_feat_max_limit; + break; } else if (mpam_has_feature(mpam_feat_cmin, cprops) && (feat == FEAT_MIN)) { configured_by = mpam_feat_cmin; @@ -1067,6 +1083,10 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (feat == FEAT_MAX)) { configured_by = mpam_feat_mbw_max; break; + } else if (mpam_has_feature(mpam_feat_max_limit, cprops) && + (feat == FEAT_LIMIT)) { + configured_by = mpam_feat_max_limit; + break; } else if (mpam_has_feature(mpam_feat_mbw_min, cprops) && (feat == FEAT_MIN)) { configured_by = mpam_feat_mbw_min; @@ -1093,6 +1113,13 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, (configured_by == mpam_feat_mbw_max)) return MAX_MBA_BW; + if (configured_by == mpam_feat_max_limit) { + if (r->fflags & RFTYPE_RES_CACHE) + return true; + else + return false; + } + if ((configured_by == mpam_feat_cmin) || (configured_by == mpam_feat_mbw_min)) return 0; @@ -1120,6 +1147,8 @@ u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_domain *d, return mbw_pbm_to_percent(cfg->mbw_pbm, cprops); case mpam_feat_mbw_max: return mbw_max_to_percent(cfg->mbw_max, cprops->bwa_wd); + case mpam_feat_max_limit: + return cfg->max_limit; case mpam_feat_mbw_min: return mbw_max_to_percent(cfg->mbw_min, cprops->bwa_wd); case mpam_feat_intpri_part: @@ -1169,6 +1198,11 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.ca_max = percent_to_mbw_max(cfg_val, cprops->cmax_wd); mpam_set_feature(mpam_feat_ccap_part, &cfg); break; + } else if (mpam_has_feature(mpam_feat_max_limit, cprops) && + (f == FEAT_LIMIT)) { + cfg.max_limit = cfg_val; + mpam_set_feature(mpam_feat_max_limit, &cfg); + break; } else if (mpam_has_feature(mpam_feat_cmin, cprops) && (f == FEAT_MIN)) { cfg.ca_min = percent_to_mbw_max(cfg_val, cprops->cmax_wd); @@ -1192,6 +1226,11 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl cfg.mbw_max = percent_to_mbw_max(cfg_val, cprops->bwa_wd); mpam_set_feature(mpam_feat_mbw_max, &cfg); break; + } else if (mpam_has_feature(mpam_feat_max_limit, cprops) && + (f == FEAT_LIMIT)) { + cfg.max_limit = cfg_val; + mpam_set_feature(mpam_feat_max_limit, &cfg); + break; } else if (mpam_has_feature(mpam_feat_mbw_min, cprops) && (f == FEAT_MIN)) { cfg.mbw_min = percent_to_mbw_max(cfg_val, cprops->bwa_wd); diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index a4a971c34db8..676c9d311f22 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -112,6 +112,26 @@ static bool prio_validate(char *buf, unsigned long *data, struct rdt_resource *r return true; } +static bool lim_validate(char *buf, unsigned long *data, struct rdt_resource *r) +{ + unsigned long cap; + int ret; + + ret = kstrtoul(buf, 10, &cap); + if (ret) { + rdt_last_cmd_printf("Non-decimal digit in limit value %s\n", buf); + return false; + } + + if (cap > 1) { + rdt_last_cmd_printf("Limit value %ld out of range [0,1]\n", cap); + return false; + } + + *data = !!cap; + return true; +} + static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, struct rdt_domain *d) { @@ -130,6 +150,10 @@ static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, if (!prio_validate(data->buf, &bw_val, r)) return -EINVAL; + } else if (s->feat_type == FEAT_LIMIT) { + if (!lim_validate(data->buf, &bw_val, r)) + return -EINVAL; + } else if (r->fflags & RFTYPE_RES_MB) { /* For FEAT_MAX and FEAT_MIN */ if (!bw_validate(data->buf, &bw_val, r)) diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h index 37b5cfbdecc7..1cb2ec922ac8 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -80,12 +80,16 @@ enum resctrl_conf_type { * @FEAT_MAX: Controls the maximum fraction of the resource capacity. * @FEAT_MIN: Controls the minimum fraction of the resource capacity. * @FEAT_INTPRI:Controls the priority for the resource. + * @FEAT_LIMIT: Allows some allocations by a PARTID when its resource + * use is above the maximum capacity partition. */ enum resctrl_feat_type { FEAT_PBM, FEAT_MAX, FEAT_MIN, FEAT_INTPRI, + FEAT_LIMIT, + FEAT_NUM_TYPES, }; -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAFXTZ -------------------------------- Fix struct rdt_resource initialization about cache level in mpam_resctrl_resource_init(), otherwise when obtaining allocated cache size by size file under control group, it would be found that the cache level is uninitialized. Fixes: 1ca491c7bbcd ("arm_mpam: resctrl: Pick the caches we will use as resctrl resources") Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index e36b3467a14d..3c0ffa08f4f8 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -856,6 +856,7 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) r->fflags = RFTYPE_RES_CACHE; r->default_ctrl = BIT_MASK(class->props.cpbm_wd) - 1; r->data_width = (class->props.cpbm_wd + 3) / 4; + r->cache_level = class->level; /* * Which bits are shared with other ...things... -- 2.25.1

hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAK8CS -------------------------------- When CDP is enabled, but the resource like MATA doesn't support it, we need to apply the same configuration to both of the CDP_CODE and CDP_DATA partids. In mpam_apply_config(), it will synchronize the configuration to the wrong comp->cfg[partid]. We will first update the staged_config with correct conf_type and then update the configuration to the comp->cfg corresponding to the partid by resctrl_arch_update_one(). In the same way, when get configuration from schemata interface by resctrl_arch_get_config(), we need to get the configuration of the CDP_CODE partid. Fixes: 58db5c68e84a ("untested: arm_mpam: resctrl: Add support for MB resource") 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, 42 insertions(+), 22 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index d83f7c9b244e..830d7d0048f0 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -222,6 +222,10 @@ 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; +}; static inline bool resctrl_arch_feat_capable(enum resctrl_res_level level, enum resctrl_feat_type feat) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 3c0ffa08f4f8..39d6b30f700c 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -181,7 +181,7 @@ int resctrl_arch_set_cdp_enabled(enum resctrl_res_level ignored, bool enable) return 0; } -static bool mpam_resctrl_hide_cdp(enum resctrl_res_level rid) +bool resctrl_arch_hide_cdp(enum resctrl_res_level rid) { return cdp_enabled && !resctrl_arch_get_cdp_enabled(rid); } @@ -1044,7 +1044,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_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); + cfg = &dom->comp->cfg[partid]; switch (r->rid) { @@ -1163,7 +1172,6 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl enum resctrl_conf_type t, enum resctrl_feat_type f, u32 cfg_val) { - int err; u32 partid; struct mpam_config cfg; struct mpam_props *cprops; @@ -1249,22 +1257,7 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, u32 cl return -EINVAL; } - /* - * 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); - } + 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 676c9d311f22..936839bda811 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -132,15 +132,15 @@ static bool lim_validate(char *buf, unsigned long *data, struct rdt_resource *r) return true; } -static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, - struct rdt_domain *d) +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) { struct resctrl_staged_config *cfg; u32 closid = data->rdtgrp->closid; struct rdt_resource *r = s->res; unsigned long bw_val; - cfg = &d->staged_config[s->conf_type][s->feat_type]; + cfg = &d->staged_config[conf_type][s->feat_type]; if (cfg->have_new_ctrl) { rdt_last_cmd_printf("Duplicate domain %d\n", d->id); return -EINVAL; @@ -177,6 +177,28 @@ static int parse_bw(struct rdt_parse_data *data, struct resctrl_schema *s, 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 571380c6116d..a2754eac4967 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -78,6 +78,7 @@ 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); void resctrl_arch_set_cpu_default_closid(int cpu, u32 closid); -- 2.25.1

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- If the CDP mount option is enabled, allow users to configure separately code and data portion, but still provide one monitor for each MSC class instead of two. Based on the above reason, add debugging information about monitor value for code and data streams separately. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- drivers/platform/mpam/mpam_resctrl.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 39d6b30f700c..f7da0022c5d6 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -463,15 +463,19 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d, cfg.opts = resctrl_evt_config_to_mpam(dom->mbm_local_evt_cfg); if (cdp_enabled) { - cfg.partid = closid << 1; + cfg.partid = resctrl_get_config_index(closid, CDP_DATA); err = mpam_msmon_read(dom->comp, &cfg, type, val); if (err) return err; - cfg.partid += 1; + cfg.partid = resctrl_get_config_index(closid, CDP_CODE); err = mpam_msmon_read(dom->comp, &cfg, type, &cdp_val); - if (!err) + 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); *val += cdp_val; + } } else { cfg.partid = closid; err = mpam_msmon_read(dom->comp, &cfg, type, val); -- 2.25.1

hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC35SV -------------------------------- The newly added resctrl_feat_type are all about ARM-specific, meaning they are architecture-specific. If more architectures support more features in the future, the staged_config array inside struct rdt_domain will become larger. Moreover, this array is a waste of space for other architectures. Here we introduce the arch-specific resctrl_arch_staged_config struct to solve it. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- arch/x86/include/asm/resctrl.h | 4 +++ arch/x86/kernel/cpu/resctrl/ctrlmondata.c | 41 +++++++++++++---------- drivers/platform/mpam/mpam_resctrl.c | 10 +++++- fs/resctrl/ctrlmondata.c | 6 ++-- fs/resctrl/rdtgroup.c | 4 +-- include/linux/arm_mpam.h | 4 +++ include/linux/resctrl.h | 19 +++++------ include/linux/resctrl_types.h | 10 ++++++ 8 files changed, 63 insertions(+), 35 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 830d7d0048f0..f067ef961e55 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -9,6 +9,10 @@ #include <linux/sched.h> #include <linux/resctrl_types.h> +struct resctrl_arch_staged_config { + struct resctrl_staged_config config; +}; + /* * This value can never be a valid CLOSID, and is used when mapping a * (closid, rmid) pair to an index and back. On x86 only the RMID is diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c index 30b57c88e3bf..f86c43fbacfb 100644 --- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c +++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c @@ -61,13 +61,20 @@ int resctrl_arch_update_one(struct rdt_resource *r, struct rdt_domain *d, return 0; } +struct resctrl_staged_config * +resctrl_arch_get_staged_config(struct rdt_domain *domain, + enum resctrl_conf_type conf_type, + enum resctrl_feat_type feat_type) +{ + return &domain->staged_config[conf_type].config; +} + int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) { struct resctrl_staged_config *cfg; struct rdt_hw_domain *hw_dom; struct msr_param msr_param; enum resctrl_conf_type t; - enum resctrl_feat_type f; cpumask_var_t cpu_mask; struct rdt_domain *d; u32 idx; @@ -82,23 +89,21 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) list_for_each_entry(d, &r->domains, list) { hw_dom = resctrl_to_arch_dom(d); for (t = 0; t < CDP_NUM_TYPES; t++) { - for (f = 0; f < FEAT_NUM_TYPES; f++) { - cfg = &hw_dom->d_resctrl.staged_config[t][f]; - if (!cfg->have_new_ctrl) - continue; - - idx = resctrl_get_config_index(closid, t); - if (!apply_config(hw_dom, cfg, idx, cpu_mask)) - continue; - - if (!msr_param.res) { - msr_param.low = idx; - msr_param.high = msr_param.low + 1; - msr_param.res = r; - } else { - msr_param.low = min(msr_param.low, idx); - msr_param.high = max(msr_param.high, idx + 1); - } + cfg = resctrl_arch_get_staged_config(&hw_dom->d_resctrl, t, 0); + if (!cfg->have_new_ctrl) + continue; + + idx = resctrl_get_config_index(closid, t); + if (!apply_config(hw_dom, cfg, idx, cpu_mask)) + continue; + + if (!msr_param.res) { + msr_param.low = idx; + msr_param.high = msr_param.low + 1; + msr_param.res = r; + } else { + msr_param.low = min(msr_param.low, idx); + msr_param.high = max(msr_param.high, idx + 1); } } } diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index f7da0022c5d6..13fdfe11ae95 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -356,6 +356,14 @@ struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l) return &mpam_resctrl_exports[l].resctrl_res; } +struct resctrl_staged_config * +resctrl_arch_get_staged_config(struct rdt_domain *domain, + enum resctrl_conf_type conf_type, + enum resctrl_feat_type feat_type) +{ + return &domain->staged_config[conf_type].config[feat_type]; +} + static void *resctrl_arch_mon_ctx_alloc_no_wait(struct rdt_resource *r, int evtid) { @@ -1279,7 +1287,7 @@ int resctrl_arch_update_domains(struct rdt_resource *r, u32 closid) list_for_each_entry(d, &r->domains, list) { for (t = 0; t < CDP_NUM_TYPES; t++) { for (f = 0; f < FEAT_NUM_TYPES; f++) { - cfg = &d->staged_config[t][f]; + cfg = resctrl_arch_get_staged_config(d, t, f); if (!cfg->have_new_ctrl) continue; diff --git a/fs/resctrl/ctrlmondata.c b/fs/resctrl/ctrlmondata.c index 936839bda811..23393f02dcb4 100644 --- a/fs/resctrl/ctrlmondata.c +++ b/fs/resctrl/ctrlmondata.c @@ -140,7 +140,7 @@ static int parse_bw_conf_type(struct rdt_parse_data *data, struct resctrl_schema struct rdt_resource *r = s->res; unsigned long bw_val; - cfg = &d->staged_config[conf_type][s->feat_type]; + cfg = resctrl_arch_get_staged_config(d, conf_type, s->feat_type); if (cfg->have_new_ctrl) { rdt_last_cmd_printf("Duplicate domain %d\n", d->id); return -EINVAL; @@ -258,7 +258,7 @@ static int parse_cbm(struct rdt_parse_data *data, struct resctrl_schema *s, struct rdt_resource *r = s->res; u32 cbm_val; - cfg = &d->staged_config[s->conf_type][s->feat_type]; + cfg = resctrl_arch_get_staged_config(d, s->conf_type, s->feat_type); if (cfg->have_new_ctrl) { rdt_last_cmd_printf("Duplicate domain %d\n", d->id); return -EINVAL; @@ -362,7 +362,7 @@ static int parse_line(char *line, struct resctrl_schema *s, if (parse_ctrlval(&data, s, d)) return -EINVAL; if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKSETUP) { - cfg = &d->staged_config[t][f]; + cfg = resctrl_arch_get_staged_config(d, t, f); /* * In pseudo-locking setup mode and just * parsed a valid CBM that should be diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 21ddd5abab49..a94f21297049 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -3242,7 +3242,7 @@ static int __init_one_rdt_domain(struct rdt_domain *d, struct resctrl_schema *s, u32 peer_ctl, ctrl_val; int i; - cfg = &d->staged_config[t][feat]; + cfg = resctrl_arch_get_staged_config(d, t, feat); cfg->have_new_ctrl = false; cfg->new_ctrl = r->cache.shareable_bits; used_b = r->cache.shareable_bits; @@ -3335,7 +3335,7 @@ static void rdtgroup_init_mba(struct rdt_resource *r, u32 closid) continue; } - cfg = &d->staged_config[CDP_NONE][FEAT_MAX]; + cfg = resctrl_arch_get_staged_config(d, CDP_NONE, FEAT_MAX); cfg->new_ctrl = r->default_ctrl; cfg->have_new_ctrl = true; } diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index a2754eac4967..181397c67585 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -31,6 +31,10 @@ enum mpam_class_types { MPAM_CLASS_UNKNOWN, /* Everything else, e.g. SMMU */ }; +struct resctrl_arch_staged_config { + struct resctrl_staged_config config[FEAT_NUM_TYPES]; +}; + #ifdef CONFIG_ACPI_MPAM /* Parse the ACPI description of resources entries for this MSC. */ int acpi_mpam_parse_resources(struct mpam_msc *msc, diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h index 34b246105c78..b2c7e86c67a4 100644 --- a/include/linux/resctrl.h +++ b/include/linux/resctrl.h @@ -78,16 +78,6 @@ struct pseudo_lock_region { struct list_head pm_reqs; }; -/** - * struct resctrl_staged_config - parsed configuration to be applied - * @new_ctrl: new ctrl value to be loaded - * @have_new_ctrl: whether the user provided new_ctrl is valid - */ -struct resctrl_staged_config { - u32 new_ctrl; - bool have_new_ctrl; -}; - /** * struct rdt_domain - group of CPUs sharing a resctrl resource * @list: all instances of this resource @@ -118,7 +108,9 @@ struct rdt_domain { int mbm_work_cpu; int cqm_work_cpu; struct pseudo_lock_region *plr; - struct resctrl_staged_config staged_config[CDP_NUM_TYPES][FEAT_NUM_TYPES]; +#ifdef CONFIG_ARCH_HAS_CPU_RESCTRL + struct resctrl_arch_staged_config staged_config[CDP_NUM_TYPES]; +#endif u32 *mbps_val; }; @@ -224,6 +216,11 @@ struct rdt_resource { */ struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l); +struct resctrl_staged_config * +resctrl_arch_get_staged_config(struct rdt_domain *domain, + enum resctrl_conf_type conf_type, + enum resctrl_feat_type feat_type); + /** * struct resctrl_schema - configuration abilities of a resource presented to * user-space diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h index 1cb2ec922ac8..6d41ceb5eeb0 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -115,4 +115,14 @@ enum resctrl_event_id { QOS_L3_MBM_LOCAL_EVENT_ID = 0x03, }; +/** + * struct resctrl_staged_config - parsed configuration to be applied + * @new_ctrl: new ctrl value to be loaded + * @have_new_ctrl: whether the user provided new_ctrl is valid + */ +struct resctrl_staged_config { + u32 new_ctrl; + bool have_new_ctrl; +}; + #endif /* __LINUX_RESCTRL_TYPES_H */ -- 2.25.1
participants (2)
-
patchwork bot
-
Zeng Heng