[PATCH v4 1/3] x86/resctrl: Fix ABMC counter programming
From: Babu Moger
Date: Fri Oct 09 2026 - 19:45:12 EST
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 <babu.moger@xxxxxxx>
Cc: stable@xxxxxxxxxxxxxxx
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@xxxxxxx/
---
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