* [PATCH v10 01/15] fs/resctrl: Return -EBUSY when per-CLOSID RMIDs are in limbo
[not found] <20261019073453.2142856-1-2118537295@qq.com>
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 8:27 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 02/15] fs/resctrl: Skip monitor context allocation when force-freeing RMIDs Jinjie Ruan
` (10 subsequent siblings)
11 siblings, 1 reply; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
resctrl_find_free_rmid() returns ERR_PTR(-ENOSPC) when no matching RMID
is found in the free list. On systems where RMIDs depend on CLOSIDs
(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID), the target CLOSID may have RMIDs
temporarily in limbo rather than permanently exhausted.
When userspace attempts to create a new monitoring group, a permanent
-ENOSPC failure prevents retry even though the CLOSID's RMIDs may become
available once the limbo handler completes.
Check closid_num_dirty_rmid[] before returning -ENOSPC. If the target
CLOSID has dirty RMIDs, return -EBUSY to signal a retryable condition.
Fixes: c4c0376eefe1 ("x86/resctrl: Allow RMID allocation to be scoped by CLOSID")
Cc: James Morse <james.morse@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Babu Moger <babu.moger@amd.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
fs/resctrl/monitor.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index 73413cb128ea..da883adc3adc 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -225,6 +225,14 @@ static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
return itr;
}
+ /*
+ * If this CLOSID has RMIDs in limbo, return -EBUSY so userspace can
+ * retry. Otherwise, the CLOSID is genuinely out of RMIDs.
+ */
+ if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID) &&
+ closid_num_dirty_rmid[closid])
+ return ERR_PTR(-EBUSY);
+
return ERR_PTR(-ENOSPC);
}
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 02/15] fs/resctrl: Skip monitor context allocation when force-freeing RMIDs
[not found] <20261019073453.2142856-1-2118537295@qq.com>
2026-10-19 7:33 ` [PATCH v10 01/15] fs/resctrl: Return -EBUSY when per-CLOSID RMIDs are in limbo Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 03/15] arm_mpam: Fix error return in resctrl_arch_mon_ctx_alloc() Jinjie Ruan
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
__check_limbo() allocates the architecture monitor context before the
scan loop, even when force_free is set. The force-free path never reads
occupancy and never uses the context.
If the allocation fails, the function returns early and leaves the limbo
list unflushed. Callers such as the unmount path then silently fail to
return the RMIDs to the free list, leaving stale CLOSIDs in limbo that
are re-interpreted with the CDP state of the next mount.
Only allocate and free the monitor context when occupancy will be read.
Fixes: fa7d949337cc ("x86/resctrl: Rename and move rdt files to a separate directory")
Cc: James Morse <james.morse@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
fs/resctrl/monitor.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index da883adc3adc..ffa9c67c9f00 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -142,11 +142,13 @@ void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
u64 val = 0;
arch_priv = mon_event_all[QOS_L3_OCCUP_EVENT_ID].arch_priv;
- arch_mon_ctx = resctrl_arch_mon_ctx_alloc(r, QOS_L3_OCCUP_EVENT_ID);
- if (IS_ERR(arch_mon_ctx)) {
- pr_warn_ratelimited("Failed to allocate monitor context: %pe",
- arch_mon_ctx);
- return;
+ if (!force_free) {
+ arch_mon_ctx = resctrl_arch_mon_ctx_alloc(r, QOS_L3_OCCUP_EVENT_ID);
+ if (IS_ERR(arch_mon_ctx)) {
+ pr_warn_ratelimited("Failed to allocate monitor context: %pe",
+ arch_mon_ctx);
+ return;
+ }
}
/*
@@ -192,7 +194,8 @@ void __check_limbo(struct rdt_l3_mon_domain *d, bool force_free)
cur_idx = idx + 1;
}
- resctrl_arch_mon_ctx_free(r, QOS_L3_OCCUP_EVENT_ID, arch_mon_ctx);
+ if (!force_free)
+ resctrl_arch_mon_ctx_free(r, QOS_L3_OCCUP_EVENT_ID, arch_mon_ctx);
}
bool has_busy_rmid(struct rdt_l3_mon_domain *d)
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 03/15] arm_mpam: Fix error return in resctrl_arch_mon_ctx_alloc()
[not found] <20261019073453.2142856-1-2118537295@qq.com>
2026-10-19 7:33 ` [PATCH v10 01/15] fs/resctrl: Return -EBUSY when per-CLOSID RMIDs are in limbo Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 02/15] fs/resctrl: Skip monitor context allocation when force-freeing RMIDs Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 04/15] arm_mpam: Fix infinite PARTID reset loop when 65536 PARTIDs are supported Jinjie Ruan
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
resctrl_arch_mon_ctx_alloc() stores the allocation result in a
heap-allocated int and returns the pointer unconditionally. When
allocation fails with anything other than a retryable -ENOSPC (e.g.
-EINVAL, -EOPNOTSUPP, or -ENOSPC with a pending signal), the caller
receives a valid heap pointer that IS_ERR() does not detect.
The caller then treats the error code as a monitor index: hardware
reads use an out-of-range index, and resctrl_arch_mon_ctx_free() hands
it to ida_free(), corrupting the allocator state.
Return ERR_PTR() when the allocation failed.
Fixes: 2a3c79c61539 ("arm_mpam: resctrl: Allow resctrl to allocate monitors")
Cc: James Morse <james.morse@arm.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
drivers/resctrl/mpam_resctrl.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index 9d223057953a..945be7465ad3 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -413,6 +413,13 @@ void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r,
} while (*ret == -ENOSPC && !signal_pending(current));
finish_wait(&resctrl_mon_ctx_waiters, &wait);
+ if (*ret < 0) {
+ int err = *ret;
+
+ kfree(ret);
+ return ERR_PTR(err);
+ }
+
return ret;
}
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 04/15] arm_mpam: Fix infinite PARTID reset loop when 65536 PARTIDs are supported
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (2 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 03/15] arm_mpam: Fix error return in resctrl_arch_mon_ctx_alloc() Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 05/15] arm_mpam: Don't stall MPAM enable when an MSC fails to probe Jinjie Ruan
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
mpam_reset_ris() and mpam_reprogram_msc walks the PARTID range with
a u16 counter bounded by mpam_partid_max, which can be 65535 on
hardware implementing the full 16-bit PARTID space. After the final
iteration the counter wraps back to zero and the loop never terminates.
Widen the counter to u32.
Fixes: 09b89d2a72f3 ("arm_mpam: Allow configuration to be applied and restored during cpu online")
Fixes: f188a36ca241 ("arm_mpam: Reset MSC controls from cpuhp callbacks")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
drivers/resctrl/mpam_devices.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index dd422c56fbb1..61cbc75625fa 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -1720,7 +1720,8 @@ static int mpam_save_mbwu_state(void *arg)
*/
static int mpam_reset_ris(void *arg)
{
- u16 partid, partid_max;
+ u16 partid_max;
+ u32 partid;
struct mpam_config reset_cfg = {};
struct mpam_msc_ris *ris = arg;
@@ -1777,7 +1778,7 @@ static int __write_config(void *arg)
static void mpam_reprogram_msc(struct mpam_msc *msc)
{
- u16 partid;
+ u32 partid;
bool reset;
struct mpam_config *cfg;
struct mpam_msc_ris *ris;
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 05/15] arm_mpam: Don't stall MPAM enable when an MSC fails to probe
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (3 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 04/15] arm_mpam: Fix infinite PARTID reset loop when 65536 PARTIDs are supported Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 06/15] fs/resctrl: Unmount resctrl with the CDP state it was mounted with Jinjie Ruan
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
mpam_msc_drv_probe() registers the discovery cpuhp callbacks only when
the number of successfully probed MSCs reaches fw_num_msc. Every failure
path returns before the counter is incremented, and a failed probe is
final - the driver core does not retry. One failing MSC therefore leaves
the counter below fw_num_msc forever: the discovery callbacks are never
registered, mpam_enable() is never scheduled, and MPAM stays dead
system-wide - the resctrl filesystem is never registered, and no error
message hints at the cause.
An MSC can legitimately fail to probe on an otherwise working system:
firmware may describe MSCs that are not accessible from any possible
CPU, e.g. when the possible CPUs are restricted with nr_cpus=. The MSCs
of the clipped CPUs then fail with "MSC is not accessible from any
CPU!", or their cache resources become unresolvable from PPTT.
Count every completed probe, successful or not. Failed MSCs are not on
mpam_all_msc (either never added, or removed by mpam_msc_drv_remove()),
so the discovery path skips them naturally, and MPAM is enabled for the
surviving devices.
Cc: stable@vger.kernel.org
Cc: Ben Horgan <ben.horgan@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Fenghua Yu <fenghuay@nvidia.com>
Cc: Shaopeng Tan <tan.shaopeng@jp.fujitsu.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Fixes: f04046f2577a5 ("arm_mpam: Add probe/remove for mpam msc driver and kbuild boiler plate")
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
drivers/resctrl/mpam_devices.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 61cbc75625fa..a44d66a5733d 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -2120,21 +2120,31 @@ static int mpam_msc_drv_probe(struct platform_device *pdev)
msc = do_mpam_msc_drv_probe(pdev);
mutex_unlock(&mpam_list_lock);
- if (IS_ERR(msc))
- return PTR_ERR(msc);
+ if (IS_ERR(msc)) {
+ err = PTR_ERR(msc);
+ goto out;
+ }
/* Create RIS entries described by firmware */
err = acpi_mpam_parse_resources(msc, plat_data);
- if (err) {
+ if (err)
mpam_msc_drv_remove(pdev);
- return err;
- }
-
- if (atomic_add_return(1, &mpam_num_msc) == fw_num_msc)
+out:
+ /*
+ * A failed MSC must not prevent MPAM being enabled for the
+ * surviving devices. Firmware may describe MSCs that are not
+ * accessible from any possible CPU, e.g. when the possible CPUs
+ * were restricted by nr_cpus=. The failed device is not
+ * re-probed, so count it here too: otherwise the counter never
+ * reaches fw_num_msc, the discovery cpuhp callbacks are never
+ * registered and mpam_enable() is never scheduled - MPAM stays
+ * dead system-wide, without any error message.
+ */
+ if (atomic_inc_return(&mpam_num_msc) == fw_num_msc)
mpam_register_cpuhp_callbacks(mpam_discovery_cpu_online, NULL,
"mpam:drv_probe");
- return 0;
+ return err;
}
static struct platform_driver mpam_msc_driver = {
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 06/15] fs/resctrl: Unmount resctrl with the CDP state it was mounted with
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (4 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 05/15] arm_mpam: Don't stall MPAM enable when an MSC fails to probe Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 07/15] fs/resctrl: Add resctrl_arch_rmid_idx_match() helper Jinjie Ruan
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Zeng Heng <zengheng4@huawei.com>
resctrl disables CDP before the control and monitor groups are torn down
on unmount. The architecture translates between CLOSID and PARTID using
the CDP state, so the RMIDs freed by rmdir_all_sub() and
resctrl_fs_teardown() are parsed with the wrong mapping. On arm64 the
RMID limbo handler can still be running, and a CLOSID left in the limbo
list is re-interpreted with the CDP state of the next mount. Enabling
CDP doubles the CLOSID on arm64, which can push the stale value out of
range and take an MPAM error interrupt.
Disable CDP after the groups have been torn down, so every CLOSID freed
on unmount is parsed with the CDP state it was allocated under. Return
the RMIDs still in limbo to the free list and stop the worker, so
nothing carries over to the next mount.
Cc: Tony Luck <tony.luck@intel.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Babu Moger <babu.moger@amd.com>
Signed-off-by: Zeng Heng <zengheng4@huawei.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
v9->v10:
- Use cancel_delayed_work_sync() with proper mutex handling
- Add comment explaining the lock pattern
---
fs/resctrl/rdtgroup.c | 46 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 44 insertions(+), 2 deletions(-)
diff --git a/fs/resctrl/rdtgroup.c b/fs/resctrl/rdtgroup.c
index 5dcbb0a964e8..40821cf07649 100644
--- a/fs/resctrl/rdtgroup.c
+++ b/fs/resctrl/rdtgroup.c
@@ -3145,6 +3145,41 @@ static void resctrl_fs_teardown(void)
rdtgroup_destroy_root();
}
+/*
+ * The RMID limbo handler keeps running after unmount. Any CLOSID still in
+ * limbo would be re-interpreted with the CDP state of the next mount. MPAM
+ * doubles CLOSID when CDP is enabled, which can push the stale value out of
+ * range. Force the limbo list back to the free list before the CLOSID state
+ * is torn down.
+ */
+static void rdt_flush_limbo(void)
+{
+ struct rdt_resource *r = resctrl_arch_get_resource(RDT_RESOURCE_L3);
+ struct rdt_l3_mon_domain *d;
+
+ if (!IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID))
+ return;
+
+ if (!resctrl_is_mon_event_enabled(QOS_L3_OCCUP_EVENT_ID))
+ return;
+
+ list_for_each_entry(d, &r->mon_domains, hdr.list) {
+ if (!has_busy_rmid(d))
+ continue;
+
+ /*
+ * The limbo handler acquires rdtgroup_mutex. Release it
+ * here to allow the handler to complete, then reacquire
+ * to maintain lock ordering for __check_limbo().
+ * This matches the pattern used in resctrl_offline_cpu().
+ */
+ mutex_unlock(&rdtgroup_mutex);
+ cancel_delayed_work_sync(&d->cqm_limbo);
+ mutex_lock(&rdtgroup_mutex);
+ __check_limbo(d, true);
+ }
+}
+
static void resctrl_unmount(void)
{
struct rdt_resource *r;
@@ -3152,13 +3187,20 @@ static void resctrl_unmount(void)
cpus_read_lock();
mutex_lock(&rdtgroup_mutex);
- rdt_disable_ctx();
-
/* Put everything back to default values. */
for_each_alloc_capable_rdt_resource(r)
resctrl_arch_reset_all_ctrls(r);
resctrl_fs_teardown();
+ rdt_flush_limbo();
+
+ /*
+ * Clear the CDP state last. free_rmid() translates between CLOSID and
+ * PARTID using the CDP state; clearing it first would make the
+ * translation inconsistent for the RMIDs being torn down.
+ */
+ rdt_disable_ctx();
+
if (resctrl_arch_alloc_capable())
resctrl_arch_disable_alloc();
if (resctrl_arch_mon_capable())
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 07/15] fs/resctrl: Add resctrl_arch_rmid_idx_match() helper
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (5 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 06/15] fs/resctrl: Unmount resctrl with the CDP state it was mounted with Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 08/15] arm_mpam: resctrl: Add resctrl_closid_rmid_to_partid_pmg() helper Jinjie Ruan
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
The current RMID allocator assumes that RMID and CLOSID are entirely
independent or follow a rigid 2D encoding. This prevents architectures
where an RMID is bound to a specific CLOSID from properly filtering
free RMIDs.
Introduce resctrl_arch_rmid_idx_match() to allow architectures to define
their own compatibility rules between a target CLOSID and an allocated
RMID's CLOSID.
No functional change.
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Babu Moger <babu.moger@amd.com>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Ben Horgan <ben.horgan@arm.com>
Cc: Fenghua Yu <fenghuay@nvidia.com>
Suggested-by: James Morse <james.morse@arm.com>
Signed-off-by: Zeng Heng <zengheng4@huawei.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
arch/x86/include/asm/resctrl.h | 6 ++++++
drivers/resctrl/mpam_resctrl.c | 6 ++++++
fs/resctrl/monitor.c | 13 +++----------
include/linux/arm_mpam.h | 1 +
4 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
index 8f6edcdcfd87..7bb297a0ab6e 100644
--- a/arch/x86/include/asm/resctrl.h
+++ b/arch/x86/include/asm/resctrl.h
@@ -181,6 +181,12 @@ static inline u32 resctrl_arch_rmid_idx_encode(u32 ignored, u32 rmid)
return rmid;
}
+/* x86 RMIDs are independent; any RMID can be used with any CLOSID. */
+static inline bool resctrl_arch_rmid_idx_match(u32 closid, u32 rmid_closid)
+{
+ return true;
+}
+
/* x86 can always read an rmid, nothing needs allocating */
struct rdt_resource;
static inline void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r,
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index 945be7465ad3..5107f4811cb2 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -279,6 +279,12 @@ u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid)
return closid * (mpam_pmg_max + 1) + rmid;
}
+/* Check if the RMID's associated closid matches the target CLOSID. */
+bool resctrl_arch_rmid_idx_match(u32 closid, u32 rmid_closid)
+{
+ return closid == rmid_closid;
+}
+
void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid)
{
*closid = idx / (mpam_pmg_max + 1);
diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
index ffa9c67c9f00..b5a3b70bb809 100644
--- a/fs/resctrl/monitor.c
+++ b/fs/resctrl/monitor.c
@@ -208,23 +208,16 @@ bool has_busy_rmid(struct rdt_l3_mon_domain *d)
static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
{
struct rmid_entry *itr;
- u32 itr_idx, cmp_idx;
if (list_empty(&rmid_free_lru))
return rmid_limbo_count ? ERR_PTR(-EBUSY) : ERR_PTR(-ENOSPC);
list_for_each_entry(itr, &rmid_free_lru, list) {
/*
- * Get the index of this free RMID, and the index it would need
- * to be if it were used with this CLOSID.
- * If the CLOSID is irrelevant on this architecture, the two
- * index values are always the same on every entry and thus the
- * very first entry will be returned.
+ * Check if the free RMID matches the target CLOSID.
+ * Architecture-specific rules apply.
*/
- itr_idx = resctrl_arch_rmid_idx_encode(itr->closid, itr->rmid);
- cmp_idx = resctrl_arch_rmid_idx_encode(closid, itr->rmid);
-
- if (itr_idx == cmp_idx)
+ if (resctrl_arch_rmid_idx_match(closid, itr->closid))
return itr;
}
diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h
index f92a36187a52..0bc8049a3733 100644
--- a/include/linux/arm_mpam.h
+++ b/include/linux/arm_mpam.h
@@ -60,6 +60,7 @@ void resctrl_arch_sched_in(struct task_struct *tsk);
bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid);
bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid);
u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid);
+bool resctrl_arch_rmid_idx_match(u32 closid, u32 rmid_closid);
void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid);
u32 resctrl_arch_system_num_rmid_idx(void);
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 08/15] arm_mpam: resctrl: Add resctrl_closid_rmid_to_partid_pmg() helper
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (6 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 07/15] fs/resctrl: Add resctrl_arch_rmid_idx_match() helper Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 09/15] arm_mpam: Add a helper to check a PARTID is in a CLOSID Jinjie Ruan
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
The translation from resctrl (CLOSID, RMID) to MPAM (PARTID, PMG)
is currently open-coded across multiple paths (CPU default settings,
task setters, matching logic, and monitor readers). This duplicates
the special-case logic for CDP handling in multiple places.
Consolidate this translation into a single helper. This not only
eliminates duplication but also provides a unified checkpoint to support
non-linear partitioning mappings (such as PARTID narrowing) in subsequent
patches.
No functional change.
Cc: James Morse <james.morse@arm.com>
Cc: Ben Horgan <ben.horgan@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Fenghua Yu <fenghuay@nvidia.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
drivers/resctrl/mpam_resctrl.c | 64 ++++++++++++++++++++--------------
1 file changed, 38 insertions(+), 26 deletions(-)
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index 5107f4811cb2..cf5db752aa35 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -298,25 +298,37 @@ void resctrl_arch_sched_in(struct task_struct *tsk)
mpam_thread_switch(tsk);
}
-void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid)
+static void resctrl_closid_rmid_to_partid_pmg(u32 closid, u32 rmid,
+ u32 *partid_d, u32 *partid_i,
+ u8 *pmg_d, u8 *pmg_i)
{
WARN_ON_ONCE(closid > U16_MAX);
WARN_ON_ONCE(rmid > U8_MAX);
if (!cdp_enabled) {
- mpam_set_cpu_defaults(cpu, closid, closid, rmid, rmid);
+ *partid_d = *partid_i = closid;
+ *pmg_d = *pmg_i = rmid;
} else {
/*
* When CDP is enabled, resctrl halves the closid range and we
* use odd/even partid for one closid.
*/
- u32 partid_d = resctrl_get_config_index(closid, CDP_DATA);
- u32 partid_i = resctrl_get_config_index(closid, CDP_CODE);
-
- mpam_set_cpu_defaults(cpu, partid_d, partid_i, rmid, rmid);
+ *partid_d = resctrl_get_config_index(closid, CDP_DATA);
+ *partid_i = resctrl_get_config_index(closid, CDP_CODE);
+ *pmg_d = *pmg_i = rmid;
}
}
+void resctrl_arch_set_cpu_default_closid_rmid(int cpu, u32 closid, u32 rmid)
+{
+ u32 partid_d, partid_i;
+ u8 pmg_d, pmg_i;
+
+ resctrl_closid_rmid_to_partid_pmg(closid, rmid, &partid_d, &partid_i,
+ &pmg_d, &pmg_i);
+ mpam_set_cpu_defaults(cpu, partid_d, partid_i, pmg_d, pmg_i);
+}
+
void resctrl_arch_sync_cpu_closid_rmid(void *info)
{
struct resctrl_cpu_defaults *r = info;
@@ -333,17 +345,12 @@ void resctrl_arch_sync_cpu_closid_rmid(void *info)
void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
{
- WARN_ON_ONCE(closid > U16_MAX);
- WARN_ON_ONCE(rmid > U8_MAX);
+ u32 partid_d, partid_i;
+ u8 pmg_d, pmg_i;
- if (!cdp_enabled) {
- mpam_set_task_partid_pmg(tsk, closid, closid, rmid, rmid);
- } else {
- u32 partid_d = resctrl_get_config_index(closid, CDP_DATA);
- u32 partid_i = resctrl_get_config_index(closid, CDP_CODE);
-
- mpam_set_task_partid_pmg(tsk, partid_d, partid_i, rmid, rmid);
- }
+ resctrl_closid_rmid_to_partid_pmg(closid, rmid, &partid_d, &partid_i,
+ &pmg_d, &pmg_i);
+ mpam_set_task_partid_pmg(tsk, partid_d, partid_i, pmg_d, pmg_i);
}
bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
@@ -361,13 +368,15 @@ bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
{
u64 regval = mpam_get_regval(tsk);
- u32 tsk_closid = FIELD_GET(MPAM0_EL1_PARTID_D, regval);
- u32 tsk_rmid = FIELD_GET(MPAM0_EL1_PMG_D, regval);
+ u32 tsk_partid = FIELD_GET(MPAM0_EL1_PARTID_D, regval);
+ u32 tsk_pmg = FIELD_GET(MPAM0_EL1_PMG_D, regval);
+ u32 partid_d, partid_i;
+ u8 pmg_d, pmg_i;
- if (cdp_enabled)
- tsk_closid >>= 1;
+ resctrl_closid_rmid_to_partid_pmg(closid, rmid, &partid_d, &partid_i,
+ &pmg_d, &pmg_i);
- return (tsk_closid == closid) && (tsk_rmid == rmid);
+ return (tsk_partid == partid_d) && (tsk_pmg == pmg_d);
}
struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
@@ -461,16 +470,19 @@ static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_c
int mon_idx,
enum resctrl_conf_type cdp_type, u32 closid, u32 rmid, u64 *val)
{
+ u32 partid, partid_d, partid_i;
struct mon_cfg cfg;
+ u8 pmg_d, pmg_i;
if (!mpam_is_enabled())
return -EINVAL;
- /* Shift closid to account for CDP */
- closid = resctrl_get_config_index(closid, cdp_type);
+ resctrl_closid_rmid_to_partid_pmg(closid, rmid, &partid_d, &partid_i,
+ &pmg_d, &pmg_i);
+ partid = (cdp_type == CDP_CODE) ? partid_i : partid_d;
if (mon_idx == USE_PRE_ALLOCATED) {
- int mbwu_idx = resctrl_arch_rmid_idx_encode(closid, rmid);
+ int mbwu_idx = resctrl_arch_rmid_idx_encode(partid, rmid);
mon_idx = mon->mbwu_idx_to_mon[mbwu_idx];
if (mon_idx == -1)
@@ -485,8 +497,8 @@ static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_c
cfg = (struct mon_cfg) {
.mon = mon_idx,
.match_pmg = true,
- .partid = closid,
- .pmg = rmid,
+ .partid = partid,
+ .pmg = pmg_d,
};
return mpam_msmon_read(mon_comp, &cfg, mon_type, val);
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 09/15] arm_mpam: Add a helper to check a PARTID is in a CLOSID
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (7 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 08/15] arm_mpam: resctrl: Add resctrl_closid_rmid_to_partid_pmg() helper Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 10/15] arm_mpam: Track the PARTID and internal PARTID limits per class Jinjie Ruan
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
match_closid() open codes the CDP special case that turns the task
PARTID into the CLOSID it belongs to. Move it into
resctrl_partid_in_closid(), so the question "does this PARTID belong to
this control group" is answered in one place.
No functional change.
Cc: James Morse <james.morse@arm.com>
Cc: Ben Horgan <ben.horgan@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Fenghua Yu <fenghuay@nvidia.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
drivers/resctrl/mpam_resctrl.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index cf5db752aa35..332388a092ce 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -353,15 +353,21 @@ void resctrl_arch_set_closid_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
mpam_set_task_partid_pmg(tsk, partid_d, partid_i, pmg_d, pmg_i);
}
+/* Does the request PARTID belong to this control group? */
+static bool resctrl_partid_in_closid(u16 partid, u32 closid)
+{
+ if (cdp_enabled)
+ partid >>= 1;
+
+ return partid == closid;
+}
+
bool resctrl_arch_match_closid(struct task_struct *tsk, u32 closid)
{
u64 regval = mpam_get_regval(tsk);
- u32 tsk_closid = FIELD_GET(MPAM0_EL1_PARTID_D, regval);
-
- if (cdp_enabled)
- tsk_closid >>= 1;
+ u32 tsk_partid = FIELD_GET(MPAM0_EL1_PARTID_D, regval);
- return tsk_closid == closid;
+ return resctrl_partid_in_closid(tsk_partid, closid);
}
/* The task's pmg is not unique, the partid must be considered too */
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 10/15] arm_mpam: Track the PARTID and internal PARTID limits per class
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (8 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 09/15] arm_mpam: Add a helper to check a PARTID is in a CLOSID Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 11/15] arm_mpam: Divide the PARTIDs between the control groups Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 12/15] arm_mpam: Map resctrl RMIDs onto the request PARTIDs Jinjie Ruan
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
The number of PARTIDs and PMGs a resource supports is global, and the
number of internal PARTIDs is not tracked at all. Tracking this per
class lets the resctrl glue code find the limits of the classes it will
use, and pick the number of control groups before it is initialised.
Resources that implement PARTID narrowing reduce msc->partid_max,
because they don't have one configuration per PARTID. Record the
internal PARTID limit alongside partid_max in struct mpam_props, and
take the smaller of the values a class's RIS advertise.
Cc: James Morse <james.morse@arm.com>
Cc: Ben Horgan <ben.horgan@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Fenghua Yu <fenghuay@nvidia.com>
Suggested-by: James Morse <james.morse@arm.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
v9->v10:
- Copy partid_max/intpartid_max on the first aliasing merge into a
zero-initialized parent instead of clamping to zero
---
drivers/resctrl/mpam_devices.c | 34 ++++++++++++++++++++++++---------
drivers/resctrl/mpam_internal.h | 2 ++
2 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index a44d66a5733d..7f88a0170c05 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -793,7 +793,6 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
struct mpam_msc *msc = ris->vmsc->msc;
struct device *dev = &msc->pdev->dev;
struct mpam_props *props = &ris->props;
- struct mpam_class *class = ris->vmsc->comp->class;
lockdep_assert_held(&msc->probe_lock);
lockdep_assert_held(&msc->part_sel_lock);
@@ -938,18 +937,20 @@ static void mpam_ris_hw_probe(struct mpam_msc_ris *ris)
}
/*
- * RIS with PARTID narrowing don't have enough storage for one
- * configuration per PARTID. If these are in a class we could use,
- * reduce the supported partid_max to match the number of intpartid.
- * If the class is unknown, just ignore it.
+ * A RIS that implements PARTID narrowing has one configuration per
+ * internal PARTID, and several request PARTIDs share it. Record both
+ * limits in the resource properties.
*/
- if (FIELD_GET(MPAMF_IDR_HAS_PARTID_NRW, ris->idr) &&
- class->type != MPAM_CLASS_UNKNOWN) {
+ props->partid_max = msc->partid_max;
+ props->intpartid_max = msc->partid_max;
+
+ if (FIELD_GET(MPAMF_IDR_HAS_PARTID_NRW, ris->idr)) {
u32 nrwidr = mpam_read_partsel_reg(msc, PARTID_NRW_IDR);
- u16 partid_max = FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr);
+ u16 intpartid_max = FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr);
mpam_set_feature(mpam_feat_partid_nrw, props);
- msc->partid_max = min(msc->partid_max, partid_max);
+ props->intpartid_max = min(props->intpartid_max, intpartid_max);
+ msc->partid_max = min(msc->partid_max, intpartid_max);
}
}
@@ -2270,6 +2271,21 @@ static void __props_mismatch(struct mpam_props *parent,
child->num_mbwu_mon);
}
+ /*
+ * Take the smallest, so the result is safe for every RIS in the class.
+ * The first aliasing merge into a zero-initialized parent must copy
+ * the child's value, otherwise min() would clamp the limit to zero.
+ */
+ if (alias && !parent->partid_max)
+ parent->partid_max = child->partid_max;
+ else
+ parent->partid_max = min(parent->partid_max, child->partid_max);
+
+ if (alias && !parent->intpartid_max)
+ parent->intpartid_max = child->intpartid_max;
+ else
+ parent->intpartid_max = min(parent->intpartid_max, child->intpartid_max);
+
if (CAN_MERGE_FEAT(parent, child, mpam_feat_intpri_part, alias)) {
parent->intpri_wd = child->intpri_wd;
} else if (MISMATCHED_FEAT(parent, child, mpam_feat_intpri_part,
diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
index def0e3a65c23..0a2177241615 100644
--- a/drivers/resctrl/mpam_internal.h
+++ b/drivers/resctrl/mpam_internal.h
@@ -203,6 +203,8 @@ struct mpam_props {
u16 dspri_wd;
u16 num_csu_mon;
u16 num_mbwu_mon;
+ u16 partid_max;
+ u16 intpartid_max;
/*
* Kunit tests use memset() to set up feature combinations that should be
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 11/15] arm_mpam: Divide the PARTIDs between the control groups
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (9 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 10/15] arm_mpam: Track the PARTID and internal PARTID limits per class Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 12/15] arm_mpam: Map resctrl RMIDs onto the request PARTIDs Jinjie Ruan
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Jinjie Ruan <ruanjinjie@huawei.com>
To program a class that implements PARTID narrowing once per control
group, the driver needs to know which request PARTIDs belong to which
control group. Add a map from request PARTID to control group, and
program a group's configuration into every request PARTID that maps onto
it.
The map is empty until the resctrl glue code sets one up, so every
PARTID is its own control group and the behaviour is unchanged. A class
that implements narrowing writes the request-PARTID to internal-PARTID
mapping, so its configuration is only programmed for the request PARTID
that maps onto itself.
Cc: James Morse <james.morse@arm.com>
Cc: Ben Horgan <ben.horgan@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Fenghua Yu <fenghuay@nvidia.com>
Signed-off-by: Zeng Heng <zengheng4@huawei.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
v9->v10:
- Run the T241 erratum scrub for request PARTIDs sharing an internal
PARTID
---
drivers/resctrl/mpam_devices.c | 74 +++++++++++++++++++++++++++++----
drivers/resctrl/mpam_internal.h | 2 +
2 files changed, 68 insertions(+), 8 deletions(-)
diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 7f88a0170c05..f81a2df11428 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -67,6 +67,25 @@ u8 mpam_pmg_max;
static bool partid_max_init, partid_max_published;
static DEFINE_SPINLOCK(partid_max_lock);
+/*
+ * Configuration constraints for resctrl-to-MPAM partitioning.
+ * mpam_num_closid == 0 indicates resctrl is unmounted or inactive.
+ */
+static u32 mpam_num_closid;
+static u32 mpam_num_partid;
+
+/*
+ * Map a request PARTID onto its owning control group using modulo
+ * interleaving. Without resctrl active, every PARTID maps 1:1 onto itself.
+ */
+u16 mpam_partid_to_intpartid(u16 partid)
+{
+ if (!mpam_num_closid || partid >= mpam_num_partid)
+ return partid;
+
+ return partid % mpam_num_closid;
+}
+
/*
* mpam is enabled once all devices have been probed from CPU online callbacks,
* scheduled via this work_struct. If access to an MSC depends on a CPU that
@@ -1560,14 +1579,24 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
if (mpam_has_feature(mpam_feat_partid_nrw, rprops)) {
/* Update the intpartid mapping */
+ u16 intpartid = mpam_partid_to_intpartid(partid);
+
mpam_write_partsel_reg(msc, INTPARTID,
- MPAMCFG_INTPARTID_INTERNAL | partid);
+ MPAMCFG_INTPARTID_INTERNAL | intpartid);
+
+ /*
+ * The internal PARTID holds the configuration. Only the
+ * request PARTID that maps onto itself writes the controls,
+ * the others share the same internal PARTID.
+ */
+ if (partid != intpartid)
+ goto post_config_change;
/*
* Then switch to the 'internal' partid to update the
* configuration.
*/
- __mpam_intpart_sel(ris->ris_idx, partid, msc);
+ __mpam_intpart_sel(ris->ris_idx, intpartid, msc);
}
if (mpam_has_feature(mpam_feat_cpor_part, rprops)) {
@@ -1641,6 +1670,7 @@ static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid,
mpam_write_partsel_reg(msc, PRI, pri_val);
}
+post_config_change:
mpam_quirk_post_config_change(ris, partid, cfg);
mutex_unlock(&msc->part_sel_lock);
@@ -1771,19 +1801,41 @@ struct mpam_write_config_arg {
static int __write_config(void *arg)
{
struct mpam_write_config_arg *c = arg;
+ u32 partid;
+
+ if (!mpam_num_closid) {
+ mpam_reprogram_ris_partid(c->ris, c->partid,
+ &c->comp->cfg[c->partid]);
+ return 0;
+ }
+
+ /* c->partid is the control group, and must be a valid one. */
+ WARN_ON_ONCE(c->partid >= mpam_num_closid);
+
+ /*
+ * A control group owns every request PARTID that maps onto it. Write
+ * the group's configuration into each of them. Resources that
+ * implement narrowing collapse them back onto a single internal
+ * PARTID, so only the first write changes the hardware.
+ */
+ for (partid = 0; partid < mpam_num_partid; partid++) {
+ if (mpam_partid_to_intpartid(partid) != c->partid)
+ continue;
- mpam_reprogram_ris_partid(c->ris, c->partid, &c->comp->cfg[c->partid]);
+ mpam_reprogram_ris_partid(c->ris, partid,
+ &c->comp->cfg[c->partid]);
+ }
return 0;
}
static void mpam_reprogram_msc(struct mpam_msc *msc)
{
- u32 partid;
- bool reset;
- struct mpam_config *cfg;
- struct mpam_msc_ris *ris;
struct mpam_write_config_arg arg;
+ struct mpam_msc_ris *ris;
+ struct mpam_config *cfg;
+ u32 partid, loop_max;
+ bool reset;
/*
* No lock for mpam_partid_max as partid_max_published has been
@@ -1803,7 +1855,13 @@ static void mpam_reprogram_msc(struct mpam_msc *msc)
arg.comp = ris->vmsc->comp;
arg.ris = ris;
reset = true;
- for (partid = 0; partid <= mpam_partid_max; partid++) {
+ /*
+ * Configurations are stored per control group. When resctrl
+ * has grouped several PARTIDs together, __write_config()
+ * expands one group into all of its PARTIDs.
+ */
+ loop_max = mpam_num_closid ? mpam_num_closid : mpam_partid_max + 1;
+ for (partid = 0; partid < loop_max; partid++) {
cfg = &ris->vmsc->comp->cfg[partid];
if (!bitmap_empty(cfg->features, MPAM_FEATURE_LAST))
reset = false;
diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
index 0a2177241615..5a7590568a05 100644
--- a/drivers/resctrl/mpam_internal.h
+++ b/drivers/resctrl/mpam_internal.h
@@ -458,6 +458,8 @@ extern struct list_head mpam_classes;
extern u16 mpam_partid_max;
extern u8 mpam_pmg_max;
+u16 mpam_partid_to_intpartid(u16 partid);
+
/* Scheduled work callback to enable mpam once all MSC have been probed */
void mpam_enable(struct work_struct *work);
void mpam_disable(struct work_struct *work);
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v10 12/15] arm_mpam: Map resctrl RMIDs onto the request PARTIDs
[not found] <20261019073453.2142856-1-2118537295@qq.com>
` (10 preceding siblings ...)
2026-10-19 7:33 ` [PATCH v10 11/15] arm_mpam: Divide the PARTIDs between the control groups Jinjie Ruan
@ 2026-10-19 7:33 ` Jinjie Ruan
11 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 7:33 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
From: Zeng Heng <zengheng4@huawei.com>
The current resctrl RMID allocation assumes a rigid 2D encoding, which
limits the total number of monitoring groups to the hardware CLOSID count.
To decouple control and monitoring, redefine resctrl_arch_rmid_idx_encode()
as a flat, global monitoring index. When extra request PARTIDs are active,
the task's hardware PARTID and PMG are derived directly from this global
RMID via modulo division. Otherwise, legacy 1:1 behavior is preserved.
CDP and PARTID narrowing can now coexist through a two-phase mapping:
when both features are active, extract reqPARTID from rmid first, then
apply CDP's even/odd split on that reqPARTID.
No functional change for now as resctrl_using_extra_partids
remains false.
Cc: James Morse <james.morse@arm.com>
Cc: Ben Horgan <ben.horgan@arm.com>
Cc: Reinette Chatre <reinette.chatre@intel.com>
Cc: Fenghua Yu <fenghuay@nvidia.com>
Suggested-by: James Morse <james.morse@arm.com>
Link: https://lore.kernel.org/all/2944b506-a462-42f8-95cf-404241fb27f0@arm.com/
Signed-off-by: Zeng Heng <zengheng4@huawei.com>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
---
v9->v10:
- Remove CDP + narrowing mutual exclusion check
- Add narrowing path in resctrl_closid_rmid_to_partid_pmg() for CDP case
- Handle CDP in resctrl_partid_in_closid()
- Add consistent NULL checks in legacy path
- Remove the dead WARN_ON_ONCE(partid > U16_MAX)
---
drivers/resctrl/mpam_resctrl.c | 76 ++++++++++++++++++++++++++++------
1 file changed, 64 insertions(+), 12 deletions(-)
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index 332388a092ce..d60dea846486 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -62,6 +62,9 @@ static DEFINE_MUTEX(domain_list_lock);
*/
static bool cdp_enabled;
+/* If resctrl is leveraging extra request PARTIDs for monitoring. */
+static bool resctrl_using_extra_partids;
+
/*
* We use cacheinfo to discover the size of the caches and their id. cacheinfo
* populates this from a device_initcall(). mpam_resctrl_setup() must wait.
@@ -274,8 +277,28 @@ u32 resctrl_arch_system_num_rmid_idx(void)
return (mpam_pmg_max + 1) * (mpam_partid_max + 1);
}
+/* The request PARTID and PMG a resctrl RMID maps onto. */
+static u16 resctrl_rmid_to_partid(u32 rmid)
+{
+ return rmid / (mpam_pmg_max + 1);
+}
+
+static u8 resctrl_rmid_to_pmg(u32 rmid)
+{
+ return rmid % (mpam_pmg_max + 1);
+}
+
+/* The control group that owns a request PARTID. */
+static u16 resctrl_partid_to_closid(u16 partid)
+{
+ return mpam_partid_to_intpartid(partid);
+}
+
u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid)
{
+ if (resctrl_using_extra_partids)
+ return rmid;
+
return closid * (mpam_pmg_max + 1) + rmid;
}
@@ -287,8 +310,18 @@ bool resctrl_arch_rmid_idx_match(u32 closid, u32 rmid_closid)
void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid)
{
- *closid = idx / (mpam_pmg_max + 1);
- *rmid = idx % (mpam_pmg_max + 1);
+ if (resctrl_using_extra_partids) {
+ if (rmid)
+ *rmid = idx;
+ if (closid)
+ *closid = resctrl_partid_to_closid(resctrl_rmid_to_partid(idx));
+ return;
+ }
+
+ if (closid)
+ *closid = idx / (mpam_pmg_max + 1);
+ if (rmid)
+ *rmid = idx % (mpam_pmg_max + 1);
}
void resctrl_arch_sched_in(struct task_struct *tsk)
@@ -303,19 +336,35 @@ static void resctrl_closid_rmid_to_partid_pmg(u32 closid, u32 rmid,
u8 *pmg_d, u8 *pmg_i)
{
WARN_ON_ONCE(closid > U16_MAX);
- WARN_ON_ONCE(rmid > U8_MAX);
+ WARN_ON_ONCE(!resctrl_using_extra_partids && rmid > U8_MAX);
if (!cdp_enabled) {
- *partid_d = *partid_i = closid;
- *pmg_d = *pmg_i = rmid;
+ u16 partid;
+ u8 pmg;
+
+ if (resctrl_using_extra_partids) {
+ partid = resctrl_rmid_to_partid(rmid);
+ pmg = resctrl_rmid_to_pmg(rmid);
+ } else {
+ partid = closid;
+ pmg = rmid;
+ }
+
+ *partid_d = *partid_i = partid;
+ *pmg_d = *pmg_i = pmg;
} else {
- /*
- * When CDP is enabled, resctrl halves the closid range and we
- * use odd/even partid for one closid.
- */
- *partid_d = resctrl_get_config_index(closid, CDP_DATA);
- *partid_i = resctrl_get_config_index(closid, CDP_CODE);
- *pmg_d = *pmg_i = rmid;
+ if (resctrl_using_extra_partids) {
+ u16 req_partid = resctrl_rmid_to_partid(rmid);
+ u8 pmg = resctrl_rmid_to_pmg(rmid);
+
+ *partid_d = resctrl_get_config_index(req_partid, CDP_DATA);
+ *partid_i = resctrl_get_config_index(req_partid, CDP_CODE);
+ *pmg_d = *pmg_i = pmg;
+ } else {
+ *partid_d = resctrl_get_config_index(closid, CDP_DATA);
+ *partid_i = resctrl_get_config_index(closid, CDP_CODE);
+ *pmg_d = *pmg_i = rmid;
+ }
}
}
@@ -359,6 +408,9 @@ static bool resctrl_partid_in_closid(u16 partid, u32 closid)
if (cdp_enabled)
partid >>= 1;
+ if (resctrl_using_extra_partids)
+ partid = resctrl_partid_to_closid(partid);
+
return partid == closid;
}
--
2.43.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v10 01/15] fs/resctrl: Return -EBUSY when per-CLOSID RMIDs are in limbo
2026-10-19 7:33 ` [PATCH v10 01/15] fs/resctrl: Return -EBUSY when per-CLOSID RMIDs are in limbo Jinjie Ruan
@ 2026-10-19 8:27 ` Jinjie Ruan
0 siblings, 0 replies; 13+ messages in thread
From: Jinjie Ruan @ 2026-10-19 8:27 UTC (permalink / raw)
To: babu.moger, ben.horgan, bp, catalin.marinas, dave.hansen,
Dave.Martin, fenghuay, gshan, hpa, james.morse, jic23, mingo,
reinette.chatre, ruanjinjie, tan.shaopeng, tglx, tony.luck,
zengheng4, x86, linux-kernel
This patch is part of the v10 series. For the main thread, see:
https://lore.kernel.org/all/tencent_28FE31D80A7A9AEEC43B22D0AD8894E30C06@qq.com/#t
在 2026/10/19 15:33, Jinjie Ruan 写道:
> From: Jinjie Ruan <ruanjinjie@huawei.com>
>
> resctrl_find_free_rmid() returns ERR_PTR(-ENOSPC) when no matching RMID
> is found in the free list. On systems where RMIDs depend on CLOSIDs
> (CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID), the target CLOSID may have RMIDs
> temporarily in limbo rather than permanently exhausted.
>
> When userspace attempts to create a new monitoring group, a permanent
> -ENOSPC failure prevents retry even though the CLOSID's RMIDs may become
> available once the limbo handler completes.
>
> Check closid_num_dirty_rmid[] before returning -ENOSPC. If the target
> CLOSID has dirty RMIDs, return -EBUSY to signal a retryable condition.
>
> Fixes: c4c0376eefe1 ("x86/resctrl: Allow RMID allocation to be scoped by CLOSID")
> Cc: James Morse <james.morse@arm.com>
> Cc: Reinette Chatre <reinette.chatre@intel.com>
> Cc: Babu Moger <babu.moger@amd.com>
> Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
> ---
> fs/resctrl/monitor.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/fs/resctrl/monitor.c b/fs/resctrl/monitor.c
> index 73413cb128ea..da883adc3adc 100644
> --- a/fs/resctrl/monitor.c
> +++ b/fs/resctrl/monitor.c
> @@ -225,6 +225,14 @@ static struct rmid_entry *resctrl_find_free_rmid(u32 closid)
> return itr;
> }
>
> + /*
> + * If this CLOSID has RMIDs in limbo, return -EBUSY so userspace can
> + * retry. Otherwise, the CLOSID is genuinely out of RMIDs.
> + */
> + if (IS_ENABLED(CONFIG_RESCTRL_RMID_DEPENDS_ON_CLOSID) &&
> + closid_num_dirty_rmid[closid])
> + return ERR_PTR(-EBUSY);
> +
> return ERR_PTR(-ENOSPC);
> }
>
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-10-19 8:27 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <20261019073453.2142856-1-2118537295@qq.com>
2026-10-19 7:33 ` [PATCH v10 01/15] fs/resctrl: Return -EBUSY when per-CLOSID RMIDs are in limbo Jinjie Ruan
2026-10-19 8:27 ` Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 02/15] fs/resctrl: Skip monitor context allocation when force-freeing RMIDs Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 03/15] arm_mpam: Fix error return in resctrl_arch_mon_ctx_alloc() Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 04/15] arm_mpam: Fix infinite PARTID reset loop when 65536 PARTIDs are supported Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 05/15] arm_mpam: Don't stall MPAM enable when an MSC fails to probe Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 06/15] fs/resctrl: Unmount resctrl with the CDP state it was mounted with Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 07/15] fs/resctrl: Add resctrl_arch_rmid_idx_match() helper Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 08/15] arm_mpam: resctrl: Add resctrl_closid_rmid_to_partid_pmg() helper Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 09/15] arm_mpam: Add a helper to check a PARTID is in a CLOSID Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 10/15] arm_mpam: Track the PARTID and internal PARTID limits per class Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 11/15] arm_mpam: Divide the PARTIDs between the control groups Jinjie Ruan
2026-10-19 7:33 ` [PATCH v10 12/15] arm_mpam: Map resctrl RMIDs onto the request PARTIDs Jinjie Ruan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®