[PATCH v2 2/8] x86/resctrl: Add RESCTRL_NPS_NODE scope for AMD NPS-aligned domains

From: Babu Moger

Date: Thu Apr 23 2026 - 21:42:50 EST


Global Memory Bandwidth Allocation (GMBA) control domains on AMD follow the
Nodes Per Socket (NPS) configuration. With NPS 4 there is a single domain
per package; otherwise the domain aligns with the NUMA node.

By default, all QOS Domains in the system are included in a single GLBE
Control Domain. However, BIOS options may establish several GLBE Control
Domains within the system using NPS configuration. When configured, each
NUMA node functions as an individual GLBE domain, except when the system is
configured in NPS=4 mode in which case only a single GLBE domain exists
which contains all QOS Domains in the system.

Add RESCTRL_NPS_NODE to enum resctrl_scope and implement
get_domain_id_nps().

Signed-off-by: Babu Moger <babu.moger@xxxxxxx>
---
v2: Add RESCTRL_NPS_NODE scope to add support for NPS-aligned resource.
---
arch/x86/kernel/cpu/resctrl/core.c | 20 ++++++++++++++++++++
include/linux/resctrl.h | 1 +
2 files changed, 21 insertions(+)

diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 269265d98ad7..0f58f5e3b853 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -451,6 +451,24 @@ static int l3_mon_domain_mbm_alloc(u32 num_rmid, struct rdt_hw_l3_mon_domain *hw
return -ENOMEM;
}

+/**
+ * get_domain_id_nps() - Domain id for %RESCTRL_NPS_NODE (AMD NPS / GMBA)
+ * @cpu: CPU to query.
+ *
+ * Global memory bandwidth allocation (GMBA) control domains on AMD follow
+ * the socket NPS layout. With NPS 4 there is a single control domain per
+ * package, so every CPU maps to domain id 0. For other NPS settings the
+ * domain matches the CPU's NUMA node.
+ *
+ * Return: 0 when NPS is 4, otherwise the NUMA node id for @cpu.
+ */
+static int get_domain_id_nps(int cpu)
+{
+ if (topology_num_nodes_per_package() == 4)
+ return 0;
+ return cpu_to_node(cpu);
+}
+
static int get_domain_id_from_scope(int cpu, enum resctrl_scope scope)
{
switch (scope) {
@@ -459,6 +477,8 @@ static int get_domain_id_from_scope(int cpu, enum resctrl_scope scope)
return get_cpu_cacheinfo_id(cpu, scope);
case RESCTRL_L3_NODE:
return cpu_to_node(cpu);
+ case RESCTRL_NPS_NODE:
+ return get_domain_id_nps(cpu);
case RESCTRL_PACKAGE:
return topology_physical_package_id(cpu);
default:
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index 006e57fd7ca5..80290ded0b82 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -271,6 +271,7 @@ enum resctrl_scope {
RESCTRL_L2_CACHE = 2,
RESCTRL_L3_CACHE = 3,
RESCTRL_L3_NODE,
+ RESCTRL_NPS_NODE,
RESCTRL_PACKAGE,
};

--
2.43.0