
hulk inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/IC30P1 -------------------------------- Support MPAM to create *mon_L2_${cache_id}/l2c_occupancy* cache occupancy monitors under mon_data directory. In the other hand, RDT doesn't support L2 monitor feature. In addition, let MPAM L2 cache msc support memory bandwidth monitor feature. L2 cache msc not only has the MSMON_CSU monitor, but also has the MSMON_MBWU monitor. Now provide *mon_L2_${cache_id}/mbm_core_bytes* interface to display the value of l2c MSMON_MBWU counter. Signed-off-by: Zeng Heng <zengheng4@huawei.com> --- arch/x86/include/asm/resctrl.h | 2 ++ drivers/platform/mpam/mpam_devices.c | 1 + drivers/platform/mpam/mpam_resctrl.c | 50 ++++++++++++++++++++++++---- fs/resctrl/monitor.c | 14 ++++++++ fs/resctrl/rdtgroup.c | 17 ++++++++-- include/linux/arm_mpam.h | 2 ++ include/linux/resctrl.h | 1 + include/linux/resctrl_types.h | 10 ++++++ 8 files changed, 88 insertions(+), 9 deletions(-) diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h index b4a0a99bde6a..406b4cf301bb 100644 --- a/arch/x86/include/asm/resctrl.h +++ b/arch/x86/include/asm/resctrl.h @@ -101,6 +101,8 @@ static inline bool resctrl_arch_is_mbm_local_enabled(void) return (rdt_mon_features & (1 << QOS_L3_MBM_LOCAL_EVENT_ID)); } +static inline bool resctrl_arch_is_mbm_core_enabled(void) { return false; } + /* * __resctrl_sched_in() - Writes the task's CLOSid/RMID to IA32_PQR_MSR * diff --git a/drivers/platform/mpam/mpam_devices.c b/drivers/platform/mpam/mpam_devices.c index 814959ac1ed2..0bafdb83db45 100644 --- a/drivers/platform/mpam/mpam_devices.c +++ b/drivers/platform/mpam/mpam_devices.c @@ -930,6 +930,7 @@ static u64 mpam_msmon_overflow_val(struct mpam_msc_ris *ris) static const struct midr_range mbwu_flowrate_list[] = { MIDR_ALL_VERSIONS(MIDR_HISI_TSV110), MIDR_ALL_VERSIONS(MIDR_HISI_LINXICORE9100), + MIDR_ALL_VERSIONS(MIDR_HISI_HIP12), { /* sentinel */ } }; diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c index 0e0011a0eb03..17ecda4c7ab6 100644 --- a/drivers/platform/mpam/mpam_resctrl.c +++ b/drivers/platform/mpam/mpam_resctrl.c @@ -36,6 +36,7 @@ static bool exposed_alloc_capable; static bool exposed_mon_capable; static struct mpam_class *mbm_local_class; static struct mpam_class *mbm_total_class; +static struct mpam_class *mbm_core_class; /* * MPAM emulates CDP by setting different PARTID in the I/D fields of MPAM1_EL1. @@ -79,6 +80,11 @@ bool resctrl_arch_is_mbm_total_enabled(void) return mbm_total_class; } +bool resctrl_arch_is_mbm_core_enabled(void) +{ + return mbm_core_class; +} + bool resctrl_arch_get_cdp_enabled(enum resctrl_res_level rid) { switch (rid) { @@ -307,6 +313,8 @@ static void *resctrl_arch_mon_ctx_alloc_no_wait(struct rdt_resource *r, case QOS_L3_OCCUP_EVENT_ID: case QOS_L3_MBM_LOCAL_EVENT_ID: case QOS_L3_MBM_TOTAL_EVENT_ID: + case QOS_L2_OCCUP_EVENT_ID: + case QOS_L2_MBM_CORE_EVENT_ID: *ret = __mon_is_rmid_idx; return ret; @@ -372,10 +380,12 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain *d, switch (eventid) { case QOS_L3_OCCUP_EVENT_ID: + case QOS_L2_OCCUP_EVENT_ID: type = mpam_feat_msmon_csu; break; case QOS_L3_MBM_LOCAL_EVENT_ID: case QOS_L3_MBM_TOTAL_EVENT_ID: + case QOS_L2_MBM_CORE_EVENT_ID: type = mpam_feat_msmon_mbwu; break; default: @@ -524,6 +534,11 @@ bool resctrl_arch_is_llc_occupancy_enabled(void) return cache_has_usable_csu(mpam_resctrl_exports[RDT_RESOURCE_L3].class); } +bool resctrl_arch_is_l2c_occupancy_enabled(void) +{ + return cache_has_usable_csu(mpam_resctrl_exports[RDT_RESOURCE_L2].class); +} + static bool class_has_usable_mbwu(struct mpam_class *class) { struct mpam_props *cprops = &class->props; @@ -918,19 +933,23 @@ static int mpam_resctrl_resource_init(struct mpam_resctrl_res *res) * be local. If it's on the memory controller, its assumed to * be global. */ - if (has_mbwu && class->level >= 3) { - mbm_local_class = class; - r->mon_capable = true; + if (has_mbwu) { + if (class->level == 3) { + mbm_local_class = class; + r->mon_capable = true; + + } else if (class->level == 2) { + mbm_core_class = class; + r->mon_capable = true; + } } /* * CSU counters only make sense on a cache. The file is called * llc_occupancy, but its expected to the on the L3. */ - if (has_csu && class->type == MPAM_CLASS_CACHE && - class->level == 3) { + if (has_csu && class->type == MPAM_CLASS_CACHE) r->mon_capable = true; - } break; case RDT_RESOURCE_MBA: @@ -1502,6 +1521,11 @@ static struct mon_evt llc_occupancy_event = { .evtid = QOS_L3_OCCUP_EVENT_ID, }; +static struct mon_evt l2c_occupancy_event = { + .name = "l2c_occupancy", + .evtid = QOS_L2_OCCUP_EVENT_ID, +}; + static struct mon_evt mbm_total_event = { .name = "mbm_total_bytes", .evtid = QOS_L3_MBM_TOTAL_EVENT_ID, @@ -1512,6 +1536,11 @@ static struct mon_evt mbm_local_event = { .evtid = QOS_L3_MBM_LOCAL_EVENT_ID, }; +static struct mon_evt mbm_core_event = { + .name = "mbm_core_bytes", + .evtid = QOS_L2_MBM_CORE_EVENT_ID, +}; + /* * Initialize the event list for the resource. * @@ -1534,6 +1563,14 @@ static void l3_mon_evt_init(struct rdt_resource *r) list_add_tail(&mbm_local_event.list, &r->evt_list); } + if (r->rid == RDT_RESOURCE_L2) { + if (resctrl_arch_is_l2c_occupancy_enabled()) + list_add_tail(&l2c_occupancy_event.list, &r->evt_list); + + if (resctrl_arch_is_mbm_core_enabled()) + list_add_tail(&mbm_core_event.list, &r->evt_list); + } + if ((r->rid == RDT_RESOURCE_MBA) && resctrl_arch_is_mbm_total_enabled()) list_add_tail(&mbm_total_event.list, &r->evt_list); @@ -1542,6 +1579,7 @@ static void l3_mon_evt_init(struct rdt_resource *r) int resctrl_arch_mon_resource_init(void) { l3_mon_evt_init(resctrl_arch_get_resource(RDT_RESOURCE_L3)); + l3_mon_evt_init(resctrl_arch_get_resource(RDT_RESOURCE_L2)); l3_mon_evt_init(resctrl_arch_get_resource(RDT_RESOURCE_MBA)); if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_TOTAL_EVENT_ID)) { diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c index 7d824dc8fa90..fb60316199c4 100644 --- a/fs/resctrl/monitor.c +++ b/fs/resctrl/monitor.c @@ -595,6 +595,20 @@ static void mbm_update(struct rdt_resource *r, struct rdt_domain *d, if (is_mba_sc(NULL)) mbm_bw_count(closid, rmid, &rr); + resctrl_arch_mon_ctx_free(rr.r, rr.evtid, rr.arch_mon_ctx); + } + if (resctrl_arch_is_mbm_core_enabled()) { + rr.evtid = QOS_L2_MBM_CORE_EVENT_ID; + rr.val = 0; + rr.arch_mon_ctx = resctrl_arch_mon_ctx_alloc(rr.r, rr.evtid); + if (IS_ERR(rr.arch_mon_ctx)) { + pr_warn_ratelimited("Failed to allocate monitor context: %ld", + PTR_ERR(rr.arch_mon_ctx)); + return; + } + + __mon_event_count(closid, rmid, &rr); + resctrl_arch_mon_ctx_free(rr.r, rr.evtid, rr.arch_mon_ctx); } } diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c index ffb6b8930435..dffc2392e9c9 100644 --- a/fs/resctrl/rdtgroup.c +++ b/fs/resctrl/rdtgroup.c @@ -114,13 +114,15 @@ void rdt_staged_configs_clear(void) static bool resctrl_is_mbm_enabled(void) { return (resctrl_arch_is_mbm_total_enabled() || - resctrl_arch_is_mbm_local_enabled()); + resctrl_arch_is_mbm_local_enabled() || + resctrl_arch_is_mbm_core_enabled()); } static bool resctrl_is_mbm_event(int e) { - return (e >= QOS_L3_MBM_TOTAL_EVENT_ID && - e <= QOS_L3_MBM_LOCAL_EVENT_ID); + return (e == QOS_L3_MBM_TOTAL_EVENT_ID || + e == QOS_L3_MBM_LOCAL_EVENT_ID || + e == QOS_L2_MBM_CORE_EVENT_ID); } /* @@ -4001,6 +4003,15 @@ static int domain_setup_mon_state(struct rdt_resource *r, struct rdt_domain *d) return -ENOMEM; } } + if (resctrl_arch_is_mbm_core_enabled()) { + tsize = sizeof(*d->mbm_core); + d->mbm_core = kcalloc(idx_limit, tsize, GFP_KERNEL); + if (!d->mbm_core) { + bitmap_free(d->rmid_busy_llc); + kfree(d->mbm_core); + return -ENOMEM; + } + } return 0; } diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index aef951595f65..3a06a8afad7c 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -64,6 +64,8 @@ static inline bool resctrl_arch_event_is_free_running(enum resctrl_event_id evt) bool resctrl_arch_alloc_capable(void); bool resctrl_arch_mon_capable(void); bool resctrl_arch_is_llc_occupancy_enabled(void); +bool resctrl_arch_is_l2c_occupancy_enabled(void); +bool resctrl_arch_is_mbm_core_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); diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h index 566a891f1e04..ba716c3c6cfb 100644 --- a/include/linux/resctrl.h +++ b/include/linux/resctrl.h @@ -113,6 +113,7 @@ struct rdt_domain { unsigned long *rmid_busy_llc; struct mbm_state *mbm_total; struct mbm_state *mbm_local; + struct mbm_state *mbm_core; struct delayed_work mbm_over; struct delayed_work cqm_limbo; int mbm_work_cpu; diff --git a/include/linux/resctrl_types.h b/include/linux/resctrl_types.h index fd1704766c29..3d56c35877ea 100644 --- a/include/linux/resctrl_types.h +++ b/include/linux/resctrl_types.h @@ -99,11 +99,21 @@ enum resctrl_res_level { /* * Event IDs, the values match those used to program IA32_QM_EVTSEL before * reading IA32_QM_CTR on RDT systems. + * + * Monitor Event IDs, representative a variety of monitoring events: + * QOS_L3_OCCUP_EVENT_ID: L3 Cache Occupancy statistics event + * QOS_L3_MBM_TOTAL_EVENT_ID: Global Memory Bandwidth statistics event + * QOS_L3_MBM_LOCAL_EVENT_ID: L3 Cache Bandwidth statistics event + * QOS_L2_OCCUP_EVENT_ID: L2 Cache Occupancy statistics event + * QOS_L2_MBM_CORE_EVENT_ID: L2 Cache Bandwidth statistics event */ enum resctrl_event_id { QOS_L3_OCCUP_EVENT_ID = 0x01, QOS_L3_MBM_TOTAL_EVENT_ID = 0x02, QOS_L3_MBM_LOCAL_EVENT_ID = 0x03, + + QOS_L2_OCCUP_EVENT_ID, + QOS_L2_MBM_CORE_EVENT_ID, }; #endif /* __LINUX_RESCTRL_TYPES_H */ -- 2.25.1