[PATCH 28/33] arm_mpam: Consider overflow in bandwidth counter state

Ben Horgan
2025-11-07T12:37:55Z

Use the overflow status bit to track overflow on each bandwidth counter
read and add the counter size to the correction when overflow is detected.

This assumes that only a single overflow has occurred since the last read
of the counter. Overflow interrupts, on hardware that supports them could
be used to remove this limitation.

Cc: Zeng Heng <zengheng4@huawei.com>
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
---
drivers/resctrl/mpam_devices.c | 24 ++++++++++++++++++++++--
drivers/resctrl/mpam_internal.h | 3 ++-
2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 2d1cef824b8e..eea082dfcddc 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -986,11 +986,18 @@ static void write_msmon_ctl_flt_vals(struct mon_read *m, u32 ctl_val,
}
}

+static u64 mpam_msmon_overflow_val(enum mpam_device_features type)
+{
+ /* TODO: scaling, and long counters */
+ return BIT_ULL(hweight_long(MSMON___VALUE));
+}
+
static void __ris_msmon_read(void *arg)
{
u64 now;
bool nrdy = false;
bool config_mismatch;
+ bool overflow;
struct mon_read *m = arg;
struct mon_cfg *ctx = m->ctx;
struct mpam_msc_ris *ris = m->ris;
@@ -1012,13 +1019,20 @@ static void __ris_msmon_read(void *arg)
* This saves waiting for 'nrdy' on subsequent reads.
*/
read_msmon_ctl_flt_vals(m, &cur_ctl, &cur_flt);
+ overflow = cur_ctl & MSMON_CFG_x_CTL_OFLOW_STATUS;
+
clean_msmon_ctl_val(&cur_ctl);
gen_msmon_ctl_flt_vals(m, &ctl_val, &flt_val);
config_mismatch = cur_flt != flt_val ||
cur_ctl != (ctl_val | MSMON_CFG_x_CTL_EN);

- if (config_mismatch)
+ if (config_mismatch) {
write_msmon_ctl_flt_vals(m, ctl_val, flt_val);
+ overflow = false;
+ } else if (overflow) {
+ mpam_write_monsel_reg(msc, CFG_MBWU_CTL,
+ cur_ctl & ~MSMON_CFG_x_CTL_OFLOW_STATUS);
+ }

switch (m->type) {
case mpam_feat_msmon_csu:
@@ -1038,7 +1052,13 @@ static void __ris_msmon_read(void *arg)

mbwu_state = &ris->mbwu_state[ctx->mon];

- /* Include bandwidth consumed before the last hardware reset */
+ if (overflow)
+ mbwu_state->correction += mpam_msmon_overflow_val(m->type);
+
+ /*
+ * Include bandwidth consumed before the last hardware reset and
+ * a counter size increment for each overflow.
+ */
now += mbwu_state->correction;
break;
default:
diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
index 1f2b04b7703e..7c99d4f3dc9c 100644
--- a/drivers/resctrl/mpam_internal.h
+++ b/drivers/resctrl/mpam_internal.h
@@ -209,7 +209,8 @@ struct msmon_mbwu_state {
struct mon_cfg cfg;

/*
- * The value to add to the new reading to account for power management.
+ * The value to add to the new reading to account for power management,
+ * and overflow.
*/
u64 correction;

--
2.43.0