Thread (120 messages) 120 messages, 6 authors, 2026-01-13

Re: [PATCH v2 25/45] arm_mpam: resctrl: Add support for 'MB' resource

From: Jonathan Cameron <jonathan.cameron@huawei.com>
Date: 2026-01-06 12:19:50
Also in: kvmarm, lkml

On Fri, 19 Dec 2025 18:11:27 +0000
Ben Horgan [off-list ref] wrote:
From: James Morse <james.morse@arm.com>

resctrl supports 'MB', as a percentage throttling of traffic somewhere
after the L3. This is the control that mba_sc uses, so ideally the class
chosen should be as close as possible to the counters used for mba_local.

MB's percentage control should be backed either with the fixed point
either's "or" is missing.  (sentence should include the second choice)
fraction MBW_MAX. The bandwidth portion bitmaps is not used as its tricky
to pick which bits to use to avoid contention, and may be possible to
expose this as something other than a percentage in the future.

CC: Zeng Heng <redacted>
Co-developed-by: Dave Martin <Dave.Martin@arm.com>
Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>>
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
As mentioned in earlier review I'd like an overview doc of the heuristics
used to map to the resctrl everything is a xeon view of the world.

At least some of our platforms are far enough from this view that the
heuristics fail (others can provide more info on that than I can).
That's fine as I'd rather not squash something inappropriate into a
viewpoint that doesn't fit. Better to leave those for later solutions!


Otherwise, just minor comments inline.

Jonathan
quoted hunk ↗ jump to hunk
---
 drivers/resctrl/mpam_resctrl.c | 212 ++++++++++++++++++++++++++++++++-
 1 file changed, 211 insertions(+), 1 deletion(-)
diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
index a20656e49edc..e376841c5596 100644
--- a/drivers/resctrl/mpam_resctrl.c
+++ b/drivers/resctrl/mpam_resctrl.c
...
+static u32 get_mba_min(struct mpam_props *cprops)
+{
+	u32 val = 0;
+
+	if (mba_class_use_mbw_max(cprops))
+		val = mbw_max_to_percent(val, cprops);
+	else
+		WARN_ON_ONCE(1);
+
+	return val;
I'd be tempted to handle the error case first to make
clear this is really just a sanity checking wrapper around the max_to_percent()
function.

	if (!mba_class_use_mbw_max(cprops)) {
		WARN_ON_ONCE(1);
		return 0;
	}

	return mbw_max_to_percent(val, cprops);
+}
+/*
+ * topology_matches_l3() - Is the provided class the same shape as L3
+ * @victim:		The class we'd like to pretend is L3.
+ *
+ * resctrl expects all the world's a Xeon, and all counters are on the
+ * L3. We play fast and loose with this, mapping counters on other
+ * classes - provided the CPU->domain mapping is the same kind of shape.
+ *
+ * Using cacheinfo directly would make this work even if resctrl can't
+ * use the L3 - but cacheinfo can't tell us anything about offline CPUs.
+ * Using the L3 resctrl domain list also depends on CPUs being online.
+ * Using the mpam_class we picked for L3 so we can use its domain list
+ * assumes that there are MPAM controls on the L3.
+ * Instead, this path eventually uses the mpam_get_cpumask_from_cache_id()
+ * helper which can tell us about offline CPUs ... but getting the cache_id
+ * to start with relies on at least one CPU per L3 cache being online at
+ * boot.
So the usual mess of maxcpus=1 breaks it for anything other than first L3?
I'm not entirely against that but it may be a little unexpected.
+ *
+ * Walk the victim component list and compare the affinity mask with the
+ * corresponding L3. The topology matches if each victim:component's affinity
+ * mask is the same as the CPU's corresponding L3's. These lists/masks are
+ * computed from firmware tables so don't change at runtime.
+ */
+static bool topology_matches_l3(struct mpam_class *victim)

quoted hunk ↗ jump to hunk
+
 static int mpam_resctrl_control_init(struct mpam_resctrl_res *res,
 				     enum resctrl_res_level type)
 {
 	struct mpam_class *class = res->class;
+	struct mpam_props *cprops = &class->props;
 	struct rdt_resource *r = &res->resctrl_res;
 
 	switch (r->rid) {
@@ -361,6 +531,20 @@ static int mpam_resctrl_control_init(struct mpam_resctrl_res *res,
 		 * 'all the bits' is the correct answer here.
 		 */
 		r->cache.shareable_bits = resctrl_get_default_ctrl(r);
+		break;
+	case RDT_RESOURCE_MBA:
+		r->alloc_capable = true;
+		r->schema_fmt = RESCTRL_SCHEMA_RANGE;
+		r->ctrl_scope = RESCTRL_L3_CACHE;
+
+		r->membw.delay_linear = true;
+		r->membw.throttle_mode = THREAD_THROTTLE_UNDEFINED;
+		r->membw.min_bw = get_mba_min(cprops);
+		r->membw.max_bw = MAX_MBA_BW;
+		r->membw.bw_gran = get_mba_granularity(cprops);
+
+		r->name = "MB";
+
Probably should be consistent with either a blank line before break or not.
That might also make the diff a little nicer.
 		break;
 	default:
 		break;

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help