[RFC PATCH 05/10] fs/resctrl: Prepare for range-format pseudo resources

From: Jinjie Ruan

Date: Thu Oct 22 2026 - 22:55:43 EST


arm_mpam exposes the MPAM priority, capacity and limit controls as
extra resources that reuse the schema machinery but have no resource
of their own: they share the base resource's class, domains and
components, and only the mpam_config field written differs.

Prepare the resctrl core for them:
- Add RDT_RESOURCE_L{2,3}_{MAX,MIN,PRI} and RDT_RESOURCE_MB_{MIN,PRI,
HDL,OPT} slots after PERF_PKG. The entries are unconditional; an
architecture only gets dead slots it never initialises.
- Dispatch rdtgroup_init_alloc(), rdtgroup_size_show() and
rdtgroup_mode_test_exclusive() on schema_fmt instead of the MBA/SMBA
rids, so every RESCTRL_SCHEMA_RANGE resource takes the percentage path.
- Skip the pseudo rids in fflags_from_resource() and
rdtgroup_create_info_dir(): they are only reachable through schemata.
- resctrl_get_default_ctrl() returns the defaults for the pseudo rids.

No behaviour change until an architecture populates the slots.

Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
fs/resctrl/rdtgroup.c | 15 ++++++++++-----
include/linux/resctrl.h | 33 +++++++++++++++++++++++++++++++--
2 files changed, 41 insertions(+), 7 deletions(-)

diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 5dcbb0a964e8..bdc568bb13d6 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -1491,7 +1491,8 @@ static bool rdtgroup_mode_test_exclusive(struct rdtgroup *rdtgrp)

list_for_each_entry(s, &resctrl_schema_all, list) {
r = s->res;
- if (r->rid == RDT_RESOURCE_MBA || r->rid == RDT_RESOURCE_SMBA)
+ /* Only the bitmap resources are caches with CBM semantics */
+ if (r->schema_fmt == RESCTRL_SCHEMA_RANGE)
continue;
has_cache = true;
list_for_each_entry_rcu(d, &r->ctrl_domains, hdr.list, lockdep_is_cpus_held()) {
@@ -1696,8 +1697,7 @@ static int rdtgroup_size_show(struct kernfs_open_file *of,
ctrl = resctrl_arch_get_config(r, d,
closid,
type);
- if (r->rid == RDT_RESOURCE_MBA ||
- r->rid == RDT_RESOURCE_SMBA)
+ if (r->schema_fmt == RESCTRL_SCHEMA_RANGE)
size = ctrl;
else
size = rdtgroup_cbm_to_size(r, d, ctrl);
@@ -2497,6 +2497,9 @@ static unsigned long fflags_from_resource(struct rdt_resource *r)
return RFTYPE_RES_MB;
case RDT_RESOURCE_PERF_PKG:
return RFTYPE_RES_PERF_PKG;
+ default:
+ /* The pseudo resources have no info directory of their own */
+ break;
}

return WARN_ON_ONCE(1);
@@ -2522,6 +2525,9 @@ static int rdtgroup_create_info_dir(struct kernfs_node *parent_kn)
/* loop over enabled controls, these are all alloc_capable */
list_for_each_entry(s, &resctrl_schema_all, list) {
r = s->res;
+ /* The pseudo resources are only reachable through schemata */
+ if (r->rid >= RDT_RESOURCE_L3_MAX)
+ continue;
fflags = fflags_from_resource(r) | RFTYPE_CTRL_INFO;
ret = rdtgroup_mkdir_info_resdir(s, s->name, fflags);
if (ret)
@@ -3859,8 +3865,7 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)

list_for_each_entry(s, &resctrl_schema_all, list) {
r = s->res;
- if (r->rid == RDT_RESOURCE_MBA ||
- r->rid == RDT_RESOURCE_SMBA) {
+ if (r->schema_fmt == RESCTRL_SCHEMA_RANGE) {
rdtgroup_init_mba(r, rdtgrp->closid);
if (is_mba_sc(r))
continue;
diff --git a/include/linux/resctrl.h b/include/linux/resctrl.h
index dd09c2ce9a0f..33af56f953c0 100644
--- a/include/linux/resctrl.h
+++ b/include/linux/resctrl.h
@@ -54,7 +54,23 @@ enum resctrl_res_level {
RDT_RESOURCE_MBA,
RDT_RESOURCE_SMBA,
RDT_RESOURCE_PERF_PKG,
- RDT_RESOURCE_LAST = RDT_RESOURCE_PERF_PKG
+ /*
+ * Pseudo resources re-using the class picked for the resource above
+ * to expose the MPAM priority/capacity/limit controls. They have no
+ * class of their own, share the base resource's domains, and never
+ * appear in info/.
+ */
+ RDT_RESOURCE_L3_MAX,
+ RDT_RESOURCE_L2_MAX,
+ RDT_RESOURCE_L3_MIN,
+ RDT_RESOURCE_L2_MIN,
+ RDT_RESOURCE_MB_MIN,
+ RDT_RESOURCE_L3_PRI,
+ RDT_RESOURCE_L2_PRI,
+ RDT_RESOURCE_MB_PRI,
+ RDT_RESOURCE_MB_HDL,
+ RDT_RESOURCE_MB_OPT,
+ RDT_RESOURCE_LAST = RDT_RESOURCE_MB_OPT
};

#define RDT_NUM_RESOURCES (RDT_RESOURCE_LAST + 1)
@@ -408,7 +424,20 @@ static inline u32 resctrl_get_default_ctrl(struct rdt_resource *r)
case RESCTRL_SCHEMA_BITMAP:
return BIT_MASK(r->cache.cbm_len) - 1;
case RESCTRL_SCHEMA_RANGE:
- return r->membw.max_bw;
+ switch (r->rid) {
+ case RDT_RESOURCE_L3_MIN:
+ case RDT_RESOURCE_L2_MIN:
+ case RDT_RESOURCE_MB_MIN:
+ case RDT_RESOURCE_L3_PRI:
+ case RDT_RESOURCE_L2_PRI:
+ return 0;
+ case RDT_RESOURCE_MB_PRI:
+ return 3;
+ case RDT_RESOURCE_MB_HDL:
+ return 1;
+ default:
+ return r->membw.max_bw;
+ }
}

return WARN_ON_ONCE(1);
--
2.34.1