From: Fenghua Yu <fenghuay@nvidia.com>
To: Reinette Chatre <reinette.chatre@intel.com>,
Tony Luck <tony.luck@intel.com>, Ben Horgan <ben.horgan@arm.com>,
James Morse <james.morse@arm.com>,
Dave Martin <Dave.Martin@arm.com>, Will Deacon <will@kernel.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Shaopeng Tan <tan.shaopeng@fujitsu.com>,
Chen Yu <yu.c.chen@intel.com>, Babu Moger <babu.moger@amd.com>,
Drew Fustini <fustini@kernel.org>,
Vikram Sethi <vsethi@nvidia.com>,
Shanker Donthineni <sdonthineni@nvidia.com>,
Newton Liu <newtonl@nvidia.com>,
Richard Cheng <icheng@nvidia.com>
Cc: linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
Fenghua Yu <fenghuay@nvidia.com>
Subject: [PATCH RFC v2 01/19] resctrl: De-hardcode L3 monitor infrastructure
Date: Mon, 31 Aug 2026 10:22:27 -0700 [thread overview]
Message-ID: <20260831172245.42253-2-fenghuay@nvidia.com> (raw)
In-Reply-To: <20260831172245.42253-1-fenghuay@nvidia.com>
ARM MPAM can expose MBM counters on an MBA (memory-level MSC) resource
as well as on L3, but the resctrl monitor core hardcodes
RDT_RESOURCE_L3 in domain validation, online/offline, and assignment
paths. That prevents reusing the same monitor infrastructure for MBA
without copying large chunks of code.
Generalise the monitor layer to operate on any resource ID while
keeping existing L3 userspace behaviour unchanged:
- Rename resctrl_l3_mon_resource_init/exit to resctrl_mon_init/exit
- Factor MBM counter assignment show/write helpers for reuse
- Validate monitor domains using r->rid instead of hardcoding L3
- Allow monitor domain online/offline for any resource ID
Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
Signed-off-by: Fenghua Yu <fenghuay@nvidia.com>
---
fs/resctrl/internal.h | 4 +-
fs/resctrl/monitor.c | 94 +++++++++++++++++++++++++++----------------
fs/resctrl/rdtgroup.c | 35 +++++++++++-----
3 files changed, 86 insertions(+), 47 deletions(-)
diff --git a/fs/resctrl/internal.h b/fs/resctrl/internal.h
index 4bd09b1541c7..af2e6e0b2af8 100644
--- a/fs/resctrl/internal.h
+++ b/fs/resctrl/internal.h
@@ -381,9 +381,9 @@ int alloc_rmid(u32 closid);
void free_rmid(u32 closid, u32 rmid);
-int resctrl_l3_mon_resource_init(void);
+int resctrl_mon_init(void);
-void resctrl_l3_mon_resource_exit(void);
+void resctrl_mon_exit(void);
void mon_event_count(void *info);
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 1552ce2b4f7e..2b5654f05480 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -432,7 +432,7 @@ static int __l3_mon_event_count(struct rdtgroup *rdtgrp, struct rmid_read *rr)
struct mbm_state *m;
u64 tval = 0;
- if (!domain_header_is_valid(rr->hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3)) {
+ if (!domain_header_is_valid(rr->hdr, RESCTRL_MON_DOMAIN, rr->r->rid)) {
rr->err = -EIO;
return -EINVAL;
}
@@ -583,7 +583,7 @@ static void mbm_bw_count(struct rdtgroup *rdtgrp, struct rmid_read *rr)
struct rdt_l3_mon_domain *d;
struct mbm_state *m;
- if (!domain_header_is_valid(rr->hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3))
+ if (!domain_header_is_valid(rr->hdr, RESCTRL_MON_DOMAIN, rr->r->rid))
return;
d = container_of(rr->hdr, struct rdt_l3_mon_domain, hdr);
m = get_mbm_state(d, closid, rmid, rr->evt->evtid);
@@ -1688,9 +1688,9 @@ int resctrl_available_mbm_cntrs_show(struct kernfs_open_file *of,
return ret;
}
-int mbm_L3_assignments_show(struct kernfs_open_file *of, struct seq_file *s, void *v)
+static int mbm_assignments_show(struct kernfs_open_file *of, struct seq_file *s,
+ void *v, struct rdt_resource *r)
{
- struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
struct rdt_l3_mon_domain *d;
struct rdtgroup *rdtgrp;
struct mon_evt *mevt;
@@ -1735,6 +1735,12 @@ int mbm_L3_assignments_show(struct kernfs_open_file *of, struct seq_file *s, voi
return ret;
}
+int mbm_L3_assignments_show(struct kernfs_open_file *of, struct seq_file *s, void *v)
+{
+ return mbm_assignments_show(of, s, v,
+ resctrl_arch_get_resource(RDT_RESOURCE_L3));
+}
+
/*
* mbm_get_mon_event_by_name() - Return the mon_evt entry for the matching
* event name.
@@ -1829,10 +1835,10 @@ static int resctrl_parse_mbm_assignment(struct rdt_resource *r, struct rdtgroup
return -EINVAL;
}
-ssize_t mbm_L3_assignments_write(struct kernfs_open_file *of, char *buf,
- size_t nbytes, loff_t off)
+static ssize_t mbm_assignments_write(struct kernfs_open_file *of, char *buf,
+ size_t nbytes, loff_t off,
+ struct rdt_resource *r)
{
- struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
struct rdtgroup *rdtgrp;
char *token, *event;
int ret = 0;
@@ -1877,6 +1883,13 @@ ssize_t mbm_L3_assignments_write(struct kernfs_open_file *of, char *buf,
return ret ?: nbytes;
}
+ssize_t mbm_L3_assignments_write(struct kernfs_open_file *of, char *buf,
+ size_t nbytes, loff_t off)
+{
+ return mbm_assignments_write(of, buf, nbytes, off,
+ resctrl_arch_get_resource(RDT_RESOURCE_L3));
+}
+
static int closid_num_dirty_rmid_alloc(struct rdt_resource *r)
{
if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID)) {
@@ -1916,40 +1929,21 @@ static void closid_num_dirty_rmid_free(void)
}
}
-/**
- * resctrl_l3_mon_resource_init() - Initialise global monitoring structures.
- *
- * Allocate and initialise global monitor resources that do not belong to a
- * specific domain. i.e. the closid_num_dirty_rmid[] used to find the CLOSID
- * with the cleanest set of RMIDs.
- * Called once during boot after the struct rdt_resource's have been configured
- * but before the filesystem is mounted.
- * Resctrl's cpuhp callbacks may be called before this point to bring a domain
- * online.
- *
- * Return: 0 for success, or -ENOMEM.
- */
-int resctrl_l3_mon_resource_init(void)
+static void resctrl_mon_resource_init(struct rdt_resource *r)
{
- struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
- int ret;
+ unsigned long fflags;
- if (!r->mon_capable)
- return 0;
-
- ret = closid_num_dirty_rmid_alloc(r);
- if (ret)
- return ret;
+ fflags = RFTYPE_RES_CACHE;
if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_TOTAL_EVENT_ID)) {
mon_event_all[QOS_L3_MBM_TOTAL_EVENT_ID].configurable = true;
resctrl_file_fflags_init("mbm_total_bytes_config",
- RFTYPE_MON_INFO | RFTYPE_RES_CACHE);
+ RFTYPE_MON_INFO | fflags);
}
if (resctrl_arch_is_evt_configurable(QOS_L3_MBM_LOCAL_EVENT_ID)) {
mon_event_all[QOS_L3_MBM_LOCAL_EVENT_ID].configurable = true;
resctrl_file_fflags_init("mbm_local_bytes_config",
- RFTYPE_MON_INFO | RFTYPE_RES_CACHE);
+ RFTYPE_MON_INFO | fflags);
}
if (resctrl_is_mon_event_enabled(QOS_L3_MBM_LOCAL_EVENT_ID))
@@ -1967,21 +1961,51 @@ int resctrl_l3_mon_resource_init(void)
NON_TEMP_WRITE_TO_LOCAL_MEM);
r->mon.mbm_assign_on_mkdir = true;
resctrl_file_fflags_init("num_mbm_cntrs",
- RFTYPE_MON_INFO | RFTYPE_RES_CACHE);
+ RFTYPE_MON_INFO | fflags);
resctrl_file_fflags_init("available_mbm_cntrs",
- RFTYPE_MON_INFO | RFTYPE_RES_CACHE);
+ RFTYPE_MON_INFO | fflags);
resctrl_file_fflags_init("event_filter", RFTYPE_ASSIGN_CONFIG);
if (r->mon.mbm_cntr_configurable)
resctrl_file_mode_init("event_filter", 0644);
resctrl_file_fflags_init("mbm_assign_on_mkdir", RFTYPE_MON_INFO |
- RFTYPE_RES_CACHE);
+ fflags);
resctrl_file_fflags_init("mbm_L3_assignments", RFTYPE_MON_BASE);
+ resctrl_file_fflags_init("mbm_assign_mode", RFTYPE_MON_INFO |
+ fflags);
}
+}
+
+/**
+ * resctrl_mon_init() - Initialise global monitoring structures.
+ *
+ * Allocate and initialise global monitor resources that do not belong to a
+ * specific domain. i.e. the closid_num_dirty_rmid[] used to find the CLOSID
+ * with the cleanest set of RMIDs.
+ * Called once during boot after the struct rdt_resource's have been configured
+ * but before the filesystem is mounted.
+ * Resctrl's cpuhp callbacks may be called before this point to bring a domain
+ * online.
+ *
+ * Return: 0 for success, or -ENOMEM.
+ */
+int resctrl_mon_init(void)
+{
+ struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
+ int ret;
+
+ if (!r->mon_capable)
+ return 0;
+
+ ret = closid_num_dirty_rmid_alloc(r);
+ if (ret)
+ return ret;
+
+ resctrl_mon_resource_init(r);
return 0;
}
-void resctrl_l3_mon_resource_exit(void)
+void resctrl_mon_exit(void)
{
struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 416b73c57016..a658e4958562 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -5102,10 +5102,17 @@ void resctrl_offline_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *h
if (resctrl_mounted && resctrl_arch_mon_capable())
rmdir_mondata_subdir_allrdtgrp(r, hdr);
- if (r->rid != RDT_RESOURCE_L3)
+ /*
+ * The remaining teardown operates on struct rdt_l3_mon_domain, which
+ * only backs the L3 and memory bandwidth monitor resources. Other
+ * mon_capable resources (e.g. the package-scoped RDT_RESOURCE_PERF_PKG)
+ * embed a smaller domain struct, so casting their header here would read
+ * past the allocation.
+ */
+ if (r->rid != RDT_RESOURCE_L3 && r->rid != RDT_RESOURCE_MBA)
goto out_unlock;
- if (!domain_header_is_valid(hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3))
+ if (!domain_header_is_valid(hdr, RESCTRL_MON_DOMAIN, r->rid))
goto out_unlock;
d = container_of(hdr, struct rdt_l3_mon_domain, hdr);
@@ -5135,7 +5142,7 @@ void resctrl_offline_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *h
* Called when the first CPU of a domain comes online, regardless of whether
* the filesystem is mounted.
* During boot this may be called before global allocations have been made by
- * resctrl_l3_mon_resource_init().
+ * resctrl_mon_init().
*
* Called during CPU online that may run as soon as CPU online callbacks
* are set up during resctrl initialization. The number of supported RMIDs
@@ -5209,10 +5216,18 @@ int resctrl_online_mon_domain(struct rdt_resource *r, struct rdt_domain_hdr *hdr
mutex_lock(&rdtgroup_mutex);
- if (r->rid != RDT_RESOURCE_L3)
+ /*
+ * domain_setup_l3_mon_state() and the workers below operate on struct
+ * rdt_l3_mon_domain, which only backs the L3 and memory bandwidth
+ * monitor resources. Other mon_capable resources (e.g. the
+ * package-scoped RDT_RESOURCE_PERF_PKG) embed a smaller domain struct,
+ * so skip the per-RMID setup for them and only create their filesystem
+ * directories.
+ */
+ if (r->rid != RDT_RESOURCE_L3 && r->rid != RDT_RESOURCE_MBA)
goto mkdir;
- if (!domain_header_is_valid(hdr, RESCTRL_MON_DOMAIN, RDT_RESOURCE_L3))
+ if (!domain_header_is_valid(hdr, RESCTRL_MON_DOMAIN, r->rid))
goto out_unlock;
d = container_of(hdr, struct rdt_l3_mon_domain, hdr);
@@ -5361,13 +5376,13 @@ int resctrl_init(void)
if (ret)
return ret;
- ret = resctrl_l3_mon_resource_init();
+ ret = resctrl_mon_init();
if (ret)
return ret;
ret = sysfs_create_mount_point(fs_kobj, "resctrl");
if (ret) {
- resctrl_l3_mon_resource_exit();
+ resctrl_mon_exit();
return ret;
}
@@ -5402,7 +5417,7 @@ int resctrl_init(void)
cleanup_mountpoint:
sysfs_remove_mount_point(fs_kobj, "resctrl");
- resctrl_l3_mon_resource_exit();
+ resctrl_mon_exit();
return ret;
}
@@ -5441,7 +5456,7 @@ static bool resctrl_online_domains_exist(void)
* When called by the architecture code, all CPUs and resctrl domains must be
* offline. This ensures the limbo and overflow handlers are not scheduled to
* run, meaning the data structures they access can be freed by
- * resctrl_l3_mon_resource_exit().
+ * resctrl_mon_exit().
*
* After resctrl_exit() returns, the architecture code should return an
* error from all resctrl_arch_ functions that can do this.
@@ -5468,6 +5483,6 @@ void resctrl_exit(void)
* it can be used to umount resctrl.
*/
- resctrl_l3_mon_resource_exit();
+ resctrl_mon_exit();
free_rmid_lru_list();
}
--
2.53.0
next prev parent reply other threads:[~2026-08-31 17:23 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-31 17:22 [PATCH RFC v2 00/19] arm,fs/resctrl: ARM MPAM MB_NODE support Fenghua Yu
2026-08-31 17:22 ` Fenghua Yu [this message]
2026-08-31 17:22 ` [PATCH RFC v2 02/19] resctrl: Expose MBA MBM counter assignment sysfs Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 03/19] resctrl: name node-scoped monitor domains mon_NODE_<id> Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 04/19] resctrl: Add node-scope MBM total event Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 05/19] resctrl: Make MBM paths resource-aware Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 06/19] arm_mpam: Support memory-level MSCs and ABMC per class Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 07/19] arm_mpam: Refine L3 topology and class selection Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 08/19] arm_mpam: Include all MSC components during domain setup Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 09/19] fs/resctrl: Take memory hotplug lock whenever taking CPU hotplug lock Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 10/19] arm_mpam: Handle CPU-less numa nodes Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 11/19] arm_mpam: Emulate MB control with node-scoped MB_NODE control Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 12/19] arm_mpam: resctrl: Add NUMA node notifier for domain online/offline Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 13/19] resctrl: Add mbm_assign_scope_mode for native assignment file names Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 14/19] Documentation: resctrl: document mbm_assign_scope_mode Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 15/19] Documentation: arm64: mpam: document memory-level MB control and NUMA nodes Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 16/19] Documentation: resctrl: document NODE-scoped MBA domains and mon_NODE monitoring Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 17/19] Documentation: resctrl: document MB_NODE emulation example on ARM MPAM Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 18/19] arm_mpam: Add KUnit test for CPU-less NUMA node affinity Fenghua Yu
2026-08-31 17:22 ` [PATCH RFC v2 19/19] selftests/resctrl: Add MB emulation test for ARM MPAM Fenghua Yu
2026-09-01 9:37 ` [PATCH RFC v2 00/19] arm,fs/resctrl: ARM MPAM MB_NODE support Richard Cheng
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260831172245.42253-2-fenghuay@nvidia.com \
--to=fenghuay@nvidia.com \
--cc=Dave.Martin@arm.com \
--cc=babu.moger@amd.com \
--cc=ben.horgan@arm.com \
--cc=catalin.marinas@arm.com \
--cc=fustini@kernel.org \
--cc=icheng@nvidia.com \
--cc=james.morse@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=newtonl@nvidia.com \
--cc=reinette.chatre@intel.com \
--cc=sdonthineni@nvidia.com \
--cc=tan.shaopeng@fujitsu.com \
--cc=tony.luck@intel.com \
--cc=vsethi@nvidia.com \
--cc=will@kernel.org \
--cc=yu.c.chen@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox