AMD's Assignable Bandwidth Monitoring Counters (ABMC) are configured via MSR_IA32_L3_QOS_ABMC_CFG; MSR_IA32_L3_QOS_ABMC_CFG.cntr_id selects the counter the configuration applies to. The number of counters a platform supports (the number of possible values written to MSR_IA32_L3_QOS_ABMC_CFG.cntr_id) is enumerated separately via CPUID. On platforms that enumerate more than 32 counters, the current 5-bit encoding truncates the counter ID and misprograms ABMC. The AMD64 Architecture Programmer's Manual [1], available from [2], has been updated to widen MSR_IA32_L3_QOS_ABMC_CFG.cntr_id from 5 bits to 12 bits (the published revision 3.41 does not yet reflect this; a future revision will). The CPUID enumeration reports the maximum counter ID in a 16-bit field and may therefore report more counters than a 12-bit MSR_IA32_L3_QOS_ABMC_CFG.cntr_id can address. Widen MSR_IA32_L3_QOS_ABMC_CFG.cntr_id to 12 bits to match the architecture. Cap the enumerated counter count at BIT(12) so every counter ID used by resctrl can be written to MSR_IA32_L3_QOS_ABMC_CFG.cntr_id without truncation. [1] AMD64 Architecture Programmer's Manual Volume 2: System Programming, Publication #24593, Revision 3.41, Section 19.3.3.3 "Assignable Bandwidth Monitoring (ABMC)" Fixes: 84ecefb76674 ("x86/resctrl: Add data structures and definitions for ABMC assignment") Signed-off-by: Babu Moger Cc: stable@vger.kernel.org Link: https://bugzilla.kernel.org/show_bug.cgi?id=206537 # [2] --- v4: Changelog update(from Reinette's input). v3: Dropped the fix for truncation on 32-bit x86. Removed the change bw_src field(RMID) width to 15 bits. Added new check to limit the number of counters to 12 bits. v2: Moved the link tag to the last. v1: https://lore.kernel.org/lkml/980f39d3a0e0d9f73925e362f835aeef070a1bc5.1784322818.git.babu.moger@amd.com/ --- arch/x86/kernel/cpu/resctrl/internal.h | 4 ++-- arch/x86/kernel/cpu/resctrl/monitor.c | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h index e3cfa0c10e92..ffd74a68671b 100644 --- a/arch/x86/kernel/cpu/resctrl/internal.h +++ b/arch/x86/kernel/cpu/resctrl/internal.h @@ -214,8 +214,8 @@ union l3_qos_abmc_cfg { bw_src :12, reserved1: 3, is_clos : 1, - cntr_id : 5, - reserved : 9, + cntr_id :12, + reserved : 2, cntr_en : 1, cfg_en : 1; } split; diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c index 3838e0a13d36..5d0d3b18f9b8 100644 --- a/arch/x86/kernel/cpu/resctrl/monitor.c +++ b/arch/x86/kernel/cpu/resctrl/monitor.c @@ -470,7 +470,8 @@ int __init rdt_get_l3_mon_config(struct rdt_resource *r) r->mon.mbm_cntr_assignable = true; r->mon.mbm_cntr_configurable = true; cpuid_count(0x80000020, 5, &eax, &ebx, &ecx, &edx); - r->mon.num_mbm_cntrs = (ebx & GENMASK(15, 0)) + 1; + /* cntr_id is 12 bits and can only encode 4096 counters. */ + r->mon.num_mbm_cntrs = min((ebx & GENMASK(15, 0)) + 1, BIT(12)); hw_res->mbm_cntr_assign_enabled = true; } -- 2.43.0