The ABMC feature provides an option to the user to assign a hardware counter to an RMID, event pair and monitor the bandwidth as long as it is assigned. The assigned RMID will be tracked by the hardware until the user unassigns it manually. Implement an architecture-specific handler to assign and unassign the counter. Configure counters by writing to the L3_QOS_ABMC_CFG MSR, specifying the counter ID, bandwidth source (RMID), and event configuration. The feature details are documented in the APM listed below [1]. [1] AMD64 Architecture Programmer's Manual Volume 2: System Programming Publication # 24593 Revision 3.41 section 19.3.3.3 Assignable Bandwidth Monitoring (ABMC). Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537 Signed-off-by: Babu Moger <babu.moger@xxxxxxx> --- v11: Moved resctrl_arch_assign_cntr() and resctrl_abmc_config_one_amd() to monitor.c. Added the code to reset the arch state in resctrl_arch_assign_cntr(). Also removed resctrl_arch_reset_rmid() inside IPI as the counters are reset from the callers. Re-wrote commit message. v10: Added call resctrl_arch_reset_rmid() to reset the RMID in the domain inside IPI call. SMP and non-SMP call support is not required in resctrl_arch_config_cntr with new domain specific assign approach/data structure. Commit message update. v9: Removed the code to reset the architectural state. It will done in another patch. v8: Rename resctrl_arch_assign_cntr to resctrl_arch_config_cntr. v7: Separated arch and fs functions. This patch only has arch implementation. Added struct rdt_resource to the interface resctrl_arch_assign_cntr. Rename rdtgroup_abmc_cfg() to resctrl_abmc_config_one_amd(). v6: Removed mbm_cntr_alloc() from this patch to keep fs and arch code separate. Added code to update the counter assignment at domain level. v5: Few name changes to match cntr_id. Changed the function names to rdtgroup_assign_cntr resctr_arch_assign_cntr More comments on commit log. Added function summary. v4: Commit message update. User bitmap APIs where applicable. Changed the interfaces considering MPAM(arm). Added domain specific assignment. v3: Removed the static from the prototype of rdtgroup_assign_abmc. The function is not called directly from user anymore. These changes are related to global assignment interface. v2: Minor text changes in commit message. --- arch/x86/kernel/cpu/resctrl/internal.h | 3 ++ arch/x86/kernel/cpu/resctrl/monitor.c | 42 ++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h index acac7972cea4..161d3feb567c 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -724,4 +724,7 @@ 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); #endif /* _ASM_X86_RESCTRL_INTERNAL_H */ diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c index f2bf5b13465d..ef836bb69b9b 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -1371,3 +1371,45 @@ void resctrl_arch_mon_event_config_set(void *info) break; } } + +static void resctrl_abmc_config_one_amd(void *info) +{ + union l3_qos_abmc_cfg *abmc_cfg = info; + + wrmsrl(MSR_IA32_L3_QOS_ABMC_CFG, abmc_cfg->full); +} + +/* + * Send an IPI to the domain to assign the counter to RMID, event pair. + */ +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) +{ + struct rdt_hw_mon_domain *hw_dom = resctrl_to_arch_mon_dom(d); + union l3_qos_abmc_cfg abmc_cfg = { 0 }; + struct arch_mbm_state *am; + + abmc_cfg.split.cfg_en = 1; + abmc_cfg.split.cntr_en = assign ? 1 : 0; + abmc_cfg.split.cntr_id = cntr_id; + abmc_cfg.split.bw_src = rmid; + + /* Update the event configuration from the domain */ + if (evtid == QOS_L3_MBM_TOTAL_EVENT_ID) + abmc_cfg.split.bw_type = hw_dom->mbm_total_cfg; + else + abmc_cfg.split.bw_type = hw_dom->mbm_local_cfg; + + smp_call_function_any(&d->hdr.cpu_mask, resctrl_abmc_config_one_amd, &abmc_cfg, 1); + + /* + * Reset the architectural state so that reading of hardware + * counter is not considered as an overflow in next update. + */ + am = get_arch_mbm_state(hw_dom, rmid, evtid); + if (am) + memset(am, 0, sizeof(*am)); + + return 0; +} -- 2.34.1