[PATCH v3 10/12] fs/resctrl: Expose kmode_cpus / kmode_cpus_list per rdtgroup
From: Babu Moger
Date: Thu Apr 30 2026 - 19:28:57 EST
rdtgrp->kmode_cpu_mask selects which CPUs of a group have the
kernel-mode binding programmed, but the mask is not visible from the
resctrl filesystem; user space has no way to verify the result of a
write to info/kernel_mode without reading kernel memory.
Add two read-only files alongside cpus / cpus_list in every rdtgroup:
kmode_cpus - bitmap form of rdtgrp->kmode_cpu_mask
kmode_cpus_list - range-list form of the same mask
The handler returns -ENOENT for a deleted group and -ENODEV for a
pseudo-locked group, mirroring rdtgroup_cpus_show(). An empty mask
reads back as a bare newline, matching the "all online CPUs" semantics
rdtgroup_config_kmode() applies to an empty kmode_cpu_mask.
Signed-off-by: Babu Moger <babu.moger@xxxxxxx>
---
v3: New patch to add "kmode_cpus" and "kmode_cpus_list" to support
kernel_modes.
---
fs/resctrl/rdtgroup.c | 53 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index faf390893109..e155160ba2b1 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -387,6 +387,44 @@ static int rdtgroup_cpus_show(struct kernfs_open_file *of,
return ret;
}
+/*
+ * Show the per-rdtgroup kmode_cpu_mask, the set of CPUs scoped for this
+ * group's kernel-mode binding. Backs both the "kmode_cpus" (bitmap) and
+ * "kmode_cpus_list" (range list) files; the format is selected by
+ * is_cpu_list() based on the file's RFTYPE_FLAGS_CPUS_LIST flag.
+ *
+ * An empty mask is emitted as a bare newline. rdtgroup_config_kmode()
+ * treats an empty kmode_cpu_mask as "all online CPUs", so reading just
+ * "\n" means the binding is applied group-wide rather than restricted
+ * to a subset.
+ *
+ * Returns -ENOENT if the group has been deleted, and -ENODEV for
+ * pseudo-locked groups -- which cannot host a kernel-mode binding, so
+ * reporting an empty mask would be misleading (the empty form elsewhere
+ * means "all online CPUs"). Mirrors rdtgroup_cpus_show() for parity.
+ */
+static int rdtgroup_kmode_cpus_show(struct kernfs_open_file *of, struct seq_file *s, void *v)
+{
+ struct rdtgroup *rdtgrp;
+ int ret = 0;
+
+ rdtgrp = rdtgroup_kn_lock_live(of->kn);
+
+ if (rdtgrp) {
+ if (rdtgrp->mode == RDT_MODE_PSEUDO_LOCKED) {
+ ret = -ENODEV;
+ } else {
+ seq_printf(s, is_cpu_list(of) ? "%*pbl\n" : "%*pb\n",
+ cpumask_pr_args(&rdtgrp->kmode_cpu_mask));
+ }
+ } else {
+ ret = -ENOENT;
+ }
+ rdtgroup_kn_unlock(of->kn);
+
+ return ret;
+}
+
/*
* Update the PGR_ASSOC MSR on all cpus in @cpu_mask,
*
@@ -2547,6 +2585,21 @@ static struct rftype res_common_files[] = {
.flags = RFTYPE_FLAGS_CPUS_LIST,
.fflags = RFTYPE_BASE,
},
+ {
+ .name = "kmode_cpus",
+ .mode = 0444,
+ .kf_ops = &rdtgroup_kf_single_ops,
+ .seq_show = rdtgroup_kmode_cpus_show,
+ .fflags = RFTYPE_BASE,
+ },
+ {
+ .name = "kmode_cpus_list",
+ .mode = 0444,
+ .kf_ops = &rdtgroup_kf_single_ops,
+ .seq_show = rdtgroup_kmode_cpus_show,
+ .flags = RFTYPE_FLAGS_CPUS_LIST,
+ .fflags = RFTYPE_BASE,
+ },
{
.name = "tasks",
.mode = 0644,
--
2.43.0