
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I8T2RT -------------------------------- 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 | 2 ++ 5 files changed, 97 insertions(+), 6 deletions(-) diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index b70a771382c3..05c7e45a304e 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); @@ -1184,6 +1190,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; @@ -1208,10 +1215,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)) { @@ -1238,9 +1252,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 532f55795ad6..f5af8d240e59 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 994c1c6e06c4..fac1af07c44c 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 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, @@ -82,6 +83,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]; @@ -109,6 +113,9 @@ const char *resctrl_arch_set_feat_lab(enum resctrl_feat_type feat, break; return "MAX"; + case FEAT_LIMIT: + return "HDL"; + case FEAT_MIN: return "MIN"; @@ -829,6 +836,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 @@ -873,8 +883,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)) @@ -1003,6 +1015,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; @@ -1023,6 +1039,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; @@ -1049,6 +1069,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; @@ -1076,6 +1103,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: @@ -1125,6 +1154,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); @@ -1148,6 +1182,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 61e498ce808a..7c728b4eaaa2 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->rid == RDT_RESOURCE_MBA) { /* 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 7a33a4c119c3..f6a0d8142fde 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -78,6 +78,8 @@ enum resctrl_feat_type { FEAT_MAX, FEAT_MIN, FEAT_INTPRI, + FEAT_LIMIT, + FEAT_NUM_TYPES, }; -- 2.25.1