When BMEC (Bandwidth Monitoring Event Configuration) is supported, resctrl provides option to configure events by writing to the interfaces /sys/fs/resctrl/info/L3_MON/mbm_total_bytes_config or /sys/fs/resctrl/info/L3_MON/mbm_local_bytes_config. Update MBM event assignments for all monitor groups in the affected domains whenever the event configuration is changed. Signed-off-by: Babu Moger <babu.moger@xxxxxxx> --- v11: Added non-arch RMID reset code in mbm_config_write_domain() which was missing. Removed resctrl_arch_reset_rmid() call in resctrl_abmc_config_one_amd(). Not required as reset of arch and non-arch rmid counters done from the callers. It simplies the IPI code. Updated the code comments with Reinette's feedback. Updated the commit message in imperative mode. v10: Code changed completely with domain specific counter assignment. Rewrite the commit message. Added few more code comments. v9: Again patch changed completely based on the comment. https://lore.kernel.org/lkml/03b278b5-6c15-4d09-9ab7-3317e84a409e@xxxxxxxxx/ Introduced resctrl_mon_event_config_set to handle IPI. But sending another IPI inside IPI causes problem. Kernel reports SMP warning. So, introduced resctrl_arch_update_cntr() to send the command directly. v8: Patch changed completely. Updated the assignment on same IPI as the event is updated. Could not do the way we discussed in the thread. https://lore.kernel.org/lkml/f77737ac-d3f6-3e4b-3565-564f79c86ca8@xxxxxxx/ Needed to figure out event type to update the configuration. v7: New patch to update the assignments. Missed it earlier. --- arch/x86/kernel/cpu/resctrl/internal.h | 4 +- arch/x86/kernel/cpu/resctrl/monitor.c | 58 ++++++++++++++++++++++---- arch/x86/kernel/cpu/resctrl/rdtgroup.c | 10 ++++- 3 files changed, 61 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h index 2480698b643d..aec564fa2833 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -607,11 +607,13 @@ union cpuid_0x10_x_edx { /** * struct mon_config_info - Monitoring event configuratiin details + * @r: Resource for monitoring * @d: Domain for the event * @evtid: Event type * @mon_config: Event configuration value */ struct mon_config_info { + struct rdt_resource *r; struct rdt_mon_domain *d; enum resctrl_event_id evtid; u32 mon_config; @@ -721,12 +723,12 @@ int resctrl_arch_mbm_cntr_assign_set(struct rdt_resource *r, bool enable); bool resctrl_arch_mbm_cntr_assign_enabled(struct rdt_resource *r); void arch_mbm_evt_config_init(struct rdt_hw_mon_domain *hw_dom); unsigned int mon_event_config_index_get(u32 evtid); -void resctrl_arch_mon_event_config_set(void *info); u32 resctrl_arch_mon_event_config_get(struct rdt_mon_domain *d, enum resctrl_event_id eventid); int resctrl_arch_config_cntr(struct rdt_resource *r, struct rdt_mon_domain *d, enum resctrl_event_id evtid, u32 rmid, u32 closid, u32 cntr_id, bool assign); +void resctrl_mon_event_config_set(void *info); int resctrl_assign_cntr_event(struct rdt_resource *r, struct rdt_mon_domain *d, struct rdtgroup *rdtgrp, enum resctrl_event_id evtid); int resctrl_unassign_cntr_event(struct rdt_resource *r, struct rdt_mon_domain *d, diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c index a9a5dc626a1e..024aabbecbb5 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -1354,26 +1354,26 @@ u32 resctrl_arch_mon_event_config_get(struct rdt_mon_domain *d, return INVALID_CONFIG_VALUE; } -void resctrl_arch_mon_event_config_set(void *info) +static void resctrl_arch_mon_event_config_set(struct rdt_mon_domain *d, + enum resctrl_event_id eventid, u32 val) { - struct mon_config_info *mon_info = info; struct rdt_hw_mon_domain *hw_dom; unsigned int index; - index = mon_event_config_index_get(mon_info->evtid); + index = mon_event_config_index_get(eventid); if (index == INVALID_CONFIG_INDEX) return; - wrmsr(MSR_IA32_EVT_CFG_BASE + index, mon_info->mon_config, 0); + wrmsr(MSR_IA32_EVT_CFG_BASE + index, val, 0); - hw_dom = resctrl_to_arch_mon_dom(mon_info->d); + hw_dom = resctrl_to_arch_mon_dom(d); - switch (mon_info->evtid) { + switch (eventid) { case QOS_L3_MBM_TOTAL_EVENT_ID: - hw_dom->mbm_total_cfg = mon_info->mon_config; + hw_dom->mbm_total_cfg = val; break; case QOS_L3_MBM_LOCAL_EVENT_ID: - hw_dom->mbm_local_cfg = mon_info->mon_config; + hw_dom->mbm_local_cfg = val; break; default: break; @@ -1592,3 +1592,45 @@ void mbm_cntr_reset(struct rdt_resource *r) } } } + +/* + * Update hardware counter configuration after event configuration change. + * Walk the hardware counters of domain @d to reconfigure all assigned + * counters that are monitoring @evtid with the event's new configuration + * value. + * This is run on a CPU belonging to domain @d so call + * resctrl_abmc_config_one_amd() directly. + */ +static void resctrl_arch_update_cntr(struct rdt_resource *r, struct rdt_mon_domain *d, + enum resctrl_event_id evtid, u32 val) +{ + union l3_qos_abmc_cfg abmc_cfg = { 0 }; + struct rdtgroup *rdtgrp; + u32 cntr_id; + + for (cntr_id = 0; cntr_id < r->mon.num_mbm_cntrs; cntr_id++) { + rdtgrp = d->cntr_cfg[cntr_id].rdtgrp; + if (rdtgrp && d->cntr_cfg[cntr_id].evtid == evtid) { + abmc_cfg.split.cfg_en = 1; + abmc_cfg.split.cntr_en = 1; + abmc_cfg.split.cntr_id = cntr_id; + abmc_cfg.split.bw_src = rdtgrp->mon.rmid; + abmc_cfg.split.bw_type = val; + resctrl_abmc_config_one_amd(&abmc_cfg); + } + } +} + +void resctrl_mon_event_config_set(void *info) +{ + struct mon_config_info *mon_info = info; + struct rdt_mon_domain *d = mon_info->d; + struct rdt_resource *r = mon_info->r; + + resctrl_arch_mon_event_config_set(d, mon_info->evtid, mon_info->mon_config); + + /* Check if assignments needs to be updated */ + if (resctrl_arch_mbm_cntr_assign_enabled(r)) + resctrl_arch_update_cntr(r, d, mon_info->evtid, + mon_info->mon_config); +} diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c index 515969c5f64f..5d305d0ac053 100644 --- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c +++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c @@ -1740,10 +1740,10 @@ static int mbm_local_bytes_config_show(struct kernfs_open_file *of, return 0; } - static void mbm_config_write_domain(struct rdt_resource *r, struct rdt_mon_domain *d, u32 evtid, u32 val) { + u32 idx_limit = resctrl_arch_system_num_rmid_idx(); struct mon_config_info mon_info = {0}; u32 config_val; @@ -1755,6 +1755,7 @@ static void mbm_config_write_domain(struct rdt_resource *r, if (config_val == INVALID_CONFIG_VALUE || config_val == val) return; + mon_info.r = r; mon_info.d = d; mon_info.evtid = evtid; mon_info.mon_config = val; @@ -1766,7 +1767,7 @@ static void mbm_config_write_domain(struct rdt_resource *r, * on one CPU is observed by all the CPUs in the domain. */ smp_call_function_any(&d->hdr.cpu_mask, - resctrl_arch_mon_event_config_set, + resctrl_mon_event_config_set, &mon_info, 1); /* @@ -1779,6 +1780,11 @@ static void mbm_config_write_domain(struct rdt_resource *r, * mbm_local and mbm_total counts for all the RMIDs. */ resctrl_arch_reset_rmid_all(r, d); + + if (is_mbm_total_enabled()) + memset(d->mbm_total, 0, sizeof(struct mbm_state) * idx_limit); + if (is_mbm_local_enabled()) + memset(d->mbm_local, 0, sizeof(struct mbm_state) * idx_limit); } static int mon_config_write(struct rdt_resource *r, char *tok, u32 evtid) -- 2.34.1