From 65dbf0f26154d0686a91c7a3690e93ad9ccad265 Mon Sep 17 00:00:00 2001 From: Ben Horgan Date: Wed, 19 Nov 2025 12:22:58 +0000 Subject: [PATCH] arm_mpam: Consider overflow in bandwidth counter state 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 Reviewed-by: Gavin Shan Reviewed-by: Zeng Heng Reviewed-by: Jonathan Cameron Reviewed-by: Shaopeng Tan Reviewed-by: Fenghua Yu Tested-by: Carl Worth Tested-by: Gavin Shan Tested-by: Zeng Heng Tested-by: Shaopeng Tan Tested-by: Hanjun Guo Signed-off-by: Ben Horgan Signed-off-by: Catalin Marinas (backported from commit b35363793291e36c91d4a5b62d7ae7079c70d826) Signed-off-by: Fenghua Yu [fenghuay: Fix mem bw monitoring counter overflow issue. - Resolve conflict in mpam_msmon_overflow_val(); - Resolve conflict in __ris_msmon_read(); ] --- drivers/resctrl/mpam_devices.c | 27 +++++++++++++++------------ drivers/resctrl/mpam_internal.h | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c index caf88c460dd28..3127ffb96b907 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -1400,6 +1400,7 @@ static void __ris_msmon_read(void *arg) { bool nrdy = false; bool config_mismatch; + bool overflow; struct mon_read *m = arg; u64 now, overflow_val = 0; struct mon_cfg *ctx = m->ctx; @@ -1431,13 +1432,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 || reset_on_next_read) + if (config_mismatch || reset_on_next_read) { 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: @@ -1477,18 +1485,13 @@ static void __ris_msmon_read(void *arg) mbwu_state = &ris->mbwu_state[ctx->mon]; - /* Add any pre-overflow value to the mbwu_state->val */ - if (mbwu_state->prev_val > now) { - overflow_val = mpam_msmon_overflow_val(m->type); - if (mpam_has_quirk(T241_MBW_COUNTER_SCALE_64, msc)) - overflow_val *= 64; - overflow_val -= mbwu_state->prev_val; - } - - mbwu_state->prev_val = now; - mbwu_state->correction += overflow_val; + if (overflow) + mbwu_state->correction += mpam_msmon_overflow_val(m->type); - /* Include bandwidth consumed before the last hardware reset */ + /* + * 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 e006a1bdbd1ec..913821416bde6 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -327,7 +327,7 @@ struct msmon_mbwu_state { /* * The value to add to the new reading to account for power management, - * and shifts to trigger the overflow interrupt. + * and overflow. */ u64 correction;