diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index 37b8d7dfcfedeb091d51cf90154f234c68bd6007..c5f90edc3e20c99982a0bd9f3f44add18a89f412 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 56bbd7290cd9001e87decff1088ec5b7e99bc089..0bc8393541f1daa441f7014908eb8e65879f4369 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; } @@ -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); } @@ -921,6 +922,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 +1018,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; } @@ -1850,9 +1859,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); diff --git a/drivers/platform/mpam/mpam_internal.h b/drivers/platform/mpam/mpam_internal.h index 119660a53e1631c809615961e20aa78bc69b9301..d8854cc6f78ee981e0d1169e1bdfe79326414eab 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; @@ -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) diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 609dcb21c7ac02c45927e9033e28f16032b408ec..b387be745b9b124cb0533f0f1240f9f9d4ba72af 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) { @@ -299,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) @@ -307,16 +305,15 @@ 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: - 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) @@ -341,25 +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; - - 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: - 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) @@ -380,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; @@ -407,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; @@ -420,15 +402,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); @@ -812,6 +798,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... diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index 13c64231c82d091682493864060d81b7b47bfb2b..4b38a68cc0f3e7b92b12912467d1ec2aeaa0dcb4 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, @@ -2714,7 +2717,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); @@ -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()) @@ -3943,7 +3948,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 +4019,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 +4080,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 d70e4e726fe65637ebc760297f4c19b076f48d59..c80f220d98d6eaa5ff38efa5ea1492a5a99b31dd 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);