[PATCH v10 04/12] x86/resctrl: Detect Sub-NUMA Cluster mode before enumerating resources
From: Chen Yu
Date: Thu Nov 05 2026 - 05:27:54 EST
The Sub-NUMA Cluster (SNC) configuration is currently detected only while
setting up L3 monitoring, so it is unknown to code that runs earlier during
resctrl initialization. Upcoming Enhanced RDT (ERDT) support needs to know
whether SNC is enabled while parsing its ACPI table, before the monitoring
resources are set up.
Detect SNC once at the start of resource enumeration so that its configuration
is available to all of resctrl initialization. SNC is now also detected on
systems without L3 monitoring, which is harmless because only monitoring
depends on the SNC configuration.
Suggested-by: Tony Luck <tony.luck@xxxxxxxxx>
Suggested-by: Reinette Chatre <reinette.chatre@xxxxxxxxx>
Signed-off-by: Chen Yu <yu.c.chen@xxxxxxxxx>
Tested-by: Hongyu Ning <hongyu.ning@xxxxxxxxxxxxxxx>
---
Changes since v9:
- New patch, split out of v9 "x86/resctrl: Do not enable ERDT when
Sub-NUMA Cluster is enabled". It only moves SNC detection to the start
of resource enumeration. The ERDT/SNC check itself moves into
"x86/resctrl: Parse ACPI ERDT table and save CACD cpumask per RMD".
(Reinette Chatre)
- Drop the resctrl_arch_update_snc() helper: the resctrl_arch_ prefix is
reserved for the functions declared in include/linux/resctrl.h. Move
the definition of snc_nodes_per_l3_cache to core.c, declare it in
internal.h, and open code its initialization in get_rdt_resources().
Existing users in monitor.c are unchanged. (Reinette Chatre)
- Describe the change at a high level in the changelog instead of
narrating the code. (Reinette Chatre)
arch/x86/kernel/cpu/resctrl/core.c | 3 +++
arch/x86/kernel/cpu/resctrl/internal.h | 3 +++
arch/x86/kernel/cpu/resctrl/monitor.c | 6 +-----
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 55214d6fdc49..b5a86e5aa4e3 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -51,6 +51,8 @@ DEFINE_PER_CPU(struct resctrl_pqr_state, pqr_state);
*/
bool rdt_alloc_capable;
+int snc_nodes_per_l3_cache = 1;
+
static void mba_wrmsr_intel(struct msr_param *m);
static void cat_wrmsr(struct msr_param *m);
static void mba_wrmsr_amd(struct msr_param *m);
@@ -1016,6 +1018,7 @@ static __init void check_quirks(void)
static __init bool get_rdt_resources(void)
{
+ snc_nodes_per_l3_cache = snc_get_config();
rdt_alloc_capable = get_rdt_alloc_resources();
rdt_mon_capable = get_rdt_mon_resources();
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index e3cfa0c10e92..4436b976aedf 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -151,6 +151,8 @@ static inline struct rdt_hw_resource *resctrl_to_arch_res(struct rdt_resource *r
extern struct rdt_hw_resource rdt_resources_all[];
+extern int snc_nodes_per_l3_cache;
+
void arch_mon_domain_online(struct rdt_resource *r, struct rdt_l3_mon_domain *d);
/* CPUID.(EAX=10H, ECX=ResID=1).EAX */
@@ -225,6 +227,7 @@ union l3_qos_abmc_cfg {
void rdt_ctrl_update(void *arg);
int rdt_get_l3_mon_config(struct rdt_resource *r);
+__init int snc_get_config(void);
bool rdt_cpu_has(int flag);
diff --git a/arch/x86/kernel/cpu/resctrl/monitor.c b/arch/x86/kernel/cpu/resctrl/monitor.c
index 97fc60c23958..a30444dd638a 100644
--- a/arch/x86/kernel/cpu/resctrl/monitor.c
+++ b/arch/x86/kernel/cpu/resctrl/monitor.c
@@ -34,8 +34,6 @@ bool rdt_mon_capable;
#define CF(cf) ((unsigned long)(1048576 * (cf) + 0.5))
-static int snc_nodes_per_l3_cache = 1;
-
/*
* The correction factor table is documented in Documentation/filesystems/resctrl.rst.
* If rmid > rmid threshold, MBM total and local values should be multiplied
@@ -384,7 +382,7 @@ static const struct x86_cpu_id snc_cpu_ids[] __initconst = {
{}
};
-static __init int snc_get_config(void)
+__init int snc_get_config(void)
{
int ret;
@@ -432,8 +430,6 @@ int __init rdt_get_l3_mon_config(struct rdt_resource *r)
unsigned int threshold;
u32 eax, ebx, ecx, edx;
- snc_nodes_per_l3_cache = snc_get_config();
-
resctrl_rmid_realloc_limit = boot_cpu_data.x86_cache_size * 1024;
hw_res->mon_scale = boot_cpu_data.x86_cache_occ_scale / snc_nodes_per_l3_cache;
r->mon.num_rmid = (boot_cpu_data.x86_cache_max_rmid + 1) / snc_nodes_per_l3_cache;
--
2.25.1