From b35363793291e36c91d4a5b62d7ae7079c70d826 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 --- 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 c8ea37558f690..ecb5ecad50f8b 100644 --- a/drivers/resctrl/mpam_devices.c +++ b/drivers/resctrl/mpam_devices.c @@ -985,11 +985,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; @@ -1011,13 +1018,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: @@ -1037,7 +1051,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 12ce80bc7ff7f..218e2f48c7bf2 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -211,7 +211,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.47.3