[RFC PATCH 3/7] arm_mpam: resctrl: Split monitor context for code/data
From: Jinjie Ruan
Date: Thu Oct 22 2026 - 04:52:10 EST
The arch_mon_ctx passed between resctrl and the driver was a single
monitor index. CDP needs one accumulating monitor per PARTID, as
reprogramming one monitor's filter between the code and data PARTIDs
resets the counter on every read.
Turn the context into a u32[2] indexed by MON_CTX_DATA and MON_CTX_CODE
so a caller can borrow one monitor per PARTID. The L3 flows keep using
a single monitor for both entries.
No functional change.
Signed-off-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
---
drivers/resctrl/mpam_resctrl.c | 49 ++++++++++++++++++++++------------
1 file changed, 32 insertions(+), 17 deletions(-)
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index 9d223057953a..9ffee18e657c 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
@@ -372,7 +372,18 @@ struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
return &mpam_resctrl_controls[l].resctrl_res;
}
-static int resctrl_arch_mon_ctx_alloc_no_wait(enum resctrl_event_id evtid)
+/*
+ * The arch_mon_ctx for borrowed monitors is a u32[2]: index 0 selects the
+ * monitor for CDP_DATA (and non-CDP) reads, index 1 the monitor for CDP_CODE.
+ * With CDP each partid needs its own accumulating monitor; reprogramming a
+ * single monitor's filter for each sub-read would reset the counter every
+ * time. For the pre-allocated events both entries hold USE_PRE_ALLOCATED.
+ */
+#define MON_CTX_DATA 0
+#define MON_CTX_CODE 1
+
+static int resctrl_arch_mon_ctx_alloc_no_wait(enum resctrl_event_id evtid,
+ u32 *mon_ctx)
{
struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[evtid];
@@ -385,9 +396,14 @@ static int resctrl_arch_mon_ctx_alloc_no_wait(enum resctrl_event_id evtid)
switch (evtid) {
case QOS_L3_OCCUP_EVENT_ID:
/* With CDP, one monitor gets used for both code/data reads */
- return mpam_alloc_csu_mon(mon->class);
+ mon_ctx[MON_CTX_DATA] = mpam_alloc_csu_mon(mon->class);
+ mon_ctx[MON_CTX_CODE] = mon_ctx[MON_CTX_DATA];
+ return mon_ctx[MON_CTX_DATA];
case QOS_L3_MBM_LOCAL_EVENT_ID:
case QOS_L3_MBM_TOTAL_EVENT_ID:
+ /* Served by the pre-assigned ABMC counters */
+ mon_ctx[MON_CTX_DATA] = USE_PRE_ALLOCATED;
+ mon_ctx[MON_CTX_CODE] = USE_PRE_ALLOCATED;
return USE_PRE_ALLOCATED;
default:
return -EOPNOTSUPP;
@@ -398,16 +414,16 @@ void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r,
enum resctrl_event_id evtid)
{
DEFINE_WAIT(wait);
- int *ret;
+ u32 *ret;
- ret = kmalloc_obj(*ret);
+ ret = kmalloc_array(2, sizeof(*ret), GFP_KERNEL);
if (!ret)
return ERR_PTR(-ENOMEM);
do {
prepare_to_wait(&resctrl_mon_ctx_waiters, &wait,
TASK_INTERRUPTIBLE);
- *ret = resctrl_arch_mon_ctx_alloc_no_wait(evtid);
+ *ret = resctrl_arch_mon_ctx_alloc_no_wait(evtid, ret);
if (*ret == -ENOSPC)
schedule();
} while (*ret == -ENOSPC && !signal_pending(current));
@@ -417,7 +433,7 @@ void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r,
}
static void resctrl_arch_mon_ctx_free_no_wait(enum resctrl_event_id evtid,
- u32 mon_idx)
+ const u32 *mon_ctx)
{
struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[evtid];
@@ -428,7 +444,7 @@ static void resctrl_arch_mon_ctx_free_no_wait(enum resctrl_event_id evtid,
return;
if (evtid == QOS_L3_OCCUP_EVENT_ID)
- mpam_free_csu_mon(mon->class, mon_idx);
+ mpam_free_csu_mon(mon->class, mon_ctx[MON_CTX_DATA]);
wake_up(&resctrl_mon_ctx_waiters);
}
@@ -436,11 +452,9 @@ static void resctrl_arch_mon_ctx_free_no_wait(enum resctrl_event_id evtid,
void resctrl_arch_mon_ctx_free(struct rdt_resource *r,
enum resctrl_event_id evtid, void *arch_mon_ctx)
{
- u32 mon_idx = *(u32 *)arch_mon_ctx;
+ resctrl_arch_mon_ctx_free_no_wait(evtid, arch_mon_ctx);
kfree(arch_mon_ctx);
-
- resctrl_arch_mon_ctx_free_no_wait(evtid, mon_idx);
}
static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_comp,
@@ -481,18 +495,18 @@ static int __read_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_c
static int read_mon_cdp_safe(struct mpam_resctrl_mon *mon, struct mpam_component *mon_comp,
enum mpam_device_features mon_type,
- int mon_idx, u32 closid, u32 rmid, u64 *val)
+ const u32 *mon_ctx, u32 closid, u32 rmid, u64 *val)
{
if (cdp_enabled) {
u64 code_val = 0, data_val = 0;
int err;
- err = __read_mon(mon, mon_comp, mon_type, mon_idx,
+ err = __read_mon(mon, mon_comp, mon_type, mon_ctx[MON_CTX_CODE],
CDP_CODE, closid, rmid, &code_val);
if (err)
return err;
- err = __read_mon(mon, mon_comp, mon_type, mon_idx,
+ err = __read_mon(mon, mon_comp, mon_type, mon_ctx[MON_CTX_DATA],
CDP_DATA, closid, rmid, &data_val);
if (err)
return err;
@@ -501,7 +515,7 @@ static int read_mon_cdp_safe(struct mpam_resctrl_mon *mon, struct mpam_component
return 0;
}
- return __read_mon(mon, mon_comp, mon_type, mon_idx,
+ return __read_mon(mon, mon_comp, mon_type, mon_ctx[MON_CTX_DATA],
CDP_NONE, closid, rmid, val);
}
@@ -512,7 +526,6 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr,
{
struct mpam_resctrl_dom *l3_dom;
struct mpam_component *mon_comp;
- u32 mon_idx = *(u32 *)arch_mon_ctx;
enum mpam_device_features mon_type;
struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[eventid];
@@ -532,7 +545,7 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr,
mon_type = mpam_feat_msmon_csu;
- return read_mon_cdp_safe(mon, mon_comp, mon_type, mon_idx,
+ return read_mon_cdp_safe(mon, mon_comp, mon_type, arch_mon_ctx,
closid, rmid, val);
}
@@ -544,6 +557,8 @@ int resctrl_arch_cntr_read(struct rdt_resource *r, struct rdt_l3_mon_domain *d,
struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[eventid];
struct mpam_resctrl_dom *l3_dom;
struct mpam_component *mon_comp;
+ /* The pre-allocated counters resolve their monitor in __read_mon() */
+ u32 mon_ctx_prealloc[2] = { USE_PRE_ALLOCATED, USE_PRE_ALLOCATED };
if (!mpam_is_enabled())
return -EINVAL;
@@ -555,7 +570,7 @@ int resctrl_arch_cntr_read(struct rdt_resource *r, struct rdt_l3_mon_domain *d,
mon_comp = l3_dom->mon_comp[eventid];
return read_mon_cdp_safe(mon, mon_comp, mpam_feat_msmon_mbwu,
- USE_PRE_ALLOCATED, closid, rmid, val);
+ mon_ctx_prealloc, closid, rmid, val);
}
static void __reset_mon(struct mpam_resctrl_mon *mon, struct mpam_component *mon_comp,
--
2.43.0