Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Horgan <ben.horgan@arm.com>
To: ben.horgan@arm.com
Cc: james.morse@arm.com, reinette.chatre@intel.com,
	fenghuay@nvidia.com, linux-kernel@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, dave.martin@arm.com,
	andre.przywara@arm.com, Gavin Shan <gshan@redhat.com>
Subject: [PATCH v2 06/12] arm_mpam: Use __ris_msmon_read() for saving MBWU state
Date: Thu, 17 Sep 2026 15:56:11 +0100	[thread overview]
Message-ID: <20260917145617.2202986-7-ben.horgan@arm.com> (raw)
In-Reply-To: <20260917145617.2202986-1-ben.horgan@arm.com>

mbwu_save_mbwu_state() reads the MBWU counters and adds that to a saved
correction value. However, the type of counter to read is determined by the
RIS rather than the class and overflow is not taken into account. Fix this
and mitigate against further divergence by using a locked variant of the
same helper used for user monitor reads, __ris_msmon_read(). Using the
locked variant avoids having to drop and retake the mon_sel lock. If the
lock was dropped, an interleaved monitor read which detects overflow would
cause the overflow not to be accounted for in the saved value of
mbwu_state->correction. The correction is no longer updated for disabled
counters but this has no effect as the saved values are not expected to be
useful for disabled counters.

Fixes: 41e8a14950e1 ("arm_mpam: Track bandwidth counter state for power management")
Signed-off-by: Ben Horgan <ben.horgan@arm.com>
Tested-by: Gavin Shan <gshan@redhat.com>
Reviewed-by: Gavin Shan <gshan@redhat.com>
---
Changes since v1:

'continue' if not monitor not enabled
add __ris_msmon_read() to avoid race on update of mbwu_state->correction (Sashiko)
update the commit message
---
 drivers/resctrl/mpam_devices.c | 63 ++++++++++++++++++++++------------
 1 file changed, 42 insertions(+), 21 deletions(-)

diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
index 6cba3ef21cc8..62562ce2f9aa 100644
--- a/drivers/resctrl/mpam_devices.c
+++ b/drivers/resctrl/mpam_devices.c
@@ -1029,12 +1029,6 @@ struct mon_read {
 	bool				waited_timeout;
 };
 
-static bool mpam_ris_has_mbwu_long_counter(struct mpam_msc_ris *ris)
-{
-	return (mpam_has_feature(mpam_feat_msmon_mbwu_63counter, &ris->props) ||
-		mpam_has_feature(mpam_feat_msmon_mbwu_44counter, &ris->props));
-}
-
 static u64 mpam_msc_read_mbwu_l(struct mpam_msc *msc)
 {
 	int retry = 3;
@@ -1202,13 +1196,12 @@ static u64 mpam_msmon_overflow_val(enum mpam_device_features type,
 	return overflow_val;
 }
 
-static void __ris_msmon_read(void *arg)
+static void __ris_msmon_read_locked(struct mon_read *m)
 {
 	u64 now;
 	bool nrdy = false;
 	bool config_mismatch;
 	bool overflow = false;
-	struct mon_read *m = arg;
 	struct mon_cfg *ctx = m->ctx;
 	bool reset_on_next_read = false;
 	struct mpam_msc_ris *ris = m->ris;
@@ -1216,10 +1209,8 @@ static void __ris_msmon_read(void *arg)
 	struct mpam_msc *msc = m->ris->vmsc->msc;
 	u32 mon_sel, ctl_val, flt_val, cur_ctl, cur_flt;
 
-	if (!mpam_mon_sel_lock(msc)) {
-		m->err = -EIO;
-		return;
-	}
+	mpam_mon_sel_lock_held(msc);
+
 	mon_sel = FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, ctx->mon) |
 		  FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx);
 	mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel);
@@ -1312,7 +1303,6 @@ static void __ris_msmon_read(void *arg)
 	default:
 		m->err = -EINVAL;
 	}
-	mpam_mon_sel_unlock(msc);
 
 	if (nrdy)
 		m->err = -EBUSY;
@@ -1323,6 +1313,21 @@ static void __ris_msmon_read(void *arg)
 	*m->val += now;
 }
 
+static void __ris_msmon_read(void *arg)
+{
+	struct mon_read *m = arg;
+	struct mpam_msc *msc = m->ris->vmsc->msc;
+
+	if (!mpam_mon_sel_lock(msc)) {
+		m->err = -EIO;
+		return;
+	}
+
+	__ris_msmon_read_locked(m);
+
+	mpam_mon_sel_unlock(msc);
+}
+
 static int _msmon_read(struct mpam_component *comp, struct mon_read *arg)
 {
 	int err, any_err = 0;
@@ -1674,9 +1679,9 @@ static int mpam_restore_mbwu_state(void *_ris)
 
 		mbwu_state->reset_on_next_read = true;
 
-		mpam_mon_sel_unlock(msc);
+		__ris_msmon_read_locked(&mwbu_arg);
 
-		__ris_msmon_read(&mwbu_arg);
+		mpam_mon_sel_unlock(msc);
 	}
 
 	return 0;
@@ -1688,10 +1693,12 @@ static int mpam_save_mbwu_state(void *arg)
 	int i;
 	u64 val;
 	struct mon_cfg *cfg;
+	struct mon_read mbwu_arg;
 	u32 cur_flt, cur_ctl, mon_sel;
 	struct mpam_msc_ris *ris = arg;
 	struct msmon_mbwu_state *mbwu_state;
 	struct mpam_msc *msc = ris->vmsc->msc;
+	struct mpam_class *class = ris->vmsc->comp->class;
 
 	for (i = 0; i < ris->props.num_mbwu_mon; i++) {
 		if (WARN_ON_ONCE(!mpam_mon_sel_lock(msc)))
@@ -1707,17 +1714,31 @@ static int mpam_save_mbwu_state(void *arg)
 		cur_flt = mpam_read_monsel_reg(msc, CFG_MBWU_FLT);
 		cur_ctl = mpam_read_monsel_reg(msc, CFG_MBWU_CTL);
 
-		if (mpam_ris_has_mbwu_long_counter(ris))
-			val = mpam_msc_read_mbwu_l(msc);
-		else
-			val = mpam_read_monsel_reg(msc, MBWU);
-
 		cfg->mon = i;
 		cfg->pmg = FIELD_GET(MSMON_CFG_x_FLT_PMG, cur_flt);
 		cfg->match_pmg = FIELD_GET(MSMON_CFG_x_CTL_MATCH_PMG, cur_ctl);
 		cfg->partid = FIELD_GET(MSMON_CFG_x_FLT_PARTID, cur_flt);
-		mbwu_state->correction += val;
 		mbwu_state->enabled = FIELD_GET(MSMON_CFG_x_CTL_EN, cur_ctl);
+
+		if (!mbwu_state->enabled) {
+			mpam_mon_sel_unlock(msc);
+			continue;
+		}
+
+		val = 0;
+		mbwu_arg = (struct mon_read) {
+			.ris = ris,
+			.ctx = cfg,
+			.type = mpam_msmon_choose_counter(class),
+			.val = &val,
+		};
+
+		__ris_msmon_read_locked(&mbwu_arg);
+
+		mbwu_state->reset_on_next_read = true;
+		if (!mbwu_arg.err)
+			mbwu_state->correction = val;
+
 		mpam_mon_sel_unlock(msc);
 	}
 
-- 
2.43.0



  parent reply	other threads:[~2026-09-17 14:57 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-17 14:56 [PATCH v2 00/12] arm_mpam: minor fixes at v7.2 Ben Horgan
2026-09-17 14:56 ` [PATCH v2 01/12] arm_mpam: Move MPAMF_ECR write helpers to allow reuse Ben Horgan
2026-09-22  5:41   ` Gavin Shan
2026-10-02 14:58   ` James Morse
2026-09-17 14:56 ` [PATCH v2 02/12] arm_mpam: Restore the error interrupt enable from mpam_cpu_online() Ben Horgan
2026-09-22  5:42   ` Gavin Shan
2026-10-02 15:00   ` James Morse
2026-09-17 14:56 ` [PATCH v2 03/12] arm_mpam: Set mpam_feat_msmon_mbwu_31counter when there are bandwidth counters Ben Horgan
2026-09-22  5:42   ` Gavin Shan
2026-10-02 15:01   ` James Morse
2026-09-17 14:56 ` [PATCH v2 04/12] arm_mpam: Add missing mon_sel locking in MBWU save and restore Ben Horgan
2026-10-02 15:01   ` James Morse
2026-10-02 15:28     ` Ben Horgan
2026-09-17 14:56 ` [PATCH v2 05/12] arm_mpam: Ensure MBWU counters are reset on restore Ben Horgan
2026-09-22  5:43   ` Gavin Shan
2026-10-02 15:13   ` James Morse
2026-10-02 15:24     ` Ben Horgan
2026-09-17 14:56 ` Ben Horgan [this message]
2026-10-02 15:15   ` [PATCH v2 06/12] arm_mpam: Use __ris_msmon_read() for saving MBWU state James Morse
2026-10-02 15:22     ` Ben Horgan
2026-10-02 16:21       ` James Morse
2026-09-17 14:56 ` [PATCH v2 07/12] arm_mpam: Initialize all of struct mon_read in mpam_restore_mbwu_state() Ben Horgan
2026-10-02 15:15   ` James Morse
2026-09-17 14:56 ` [PATCH v2 08/12] arm_mpam: resctrl: Correct check that existing class is L3 Ben Horgan
2026-09-22  5:43   ` Gavin Shan
2026-10-02 15:15   ` James Morse
2026-09-17 14:56 ` [PATCH v2 09/12] arm_mpam: resctrl: Make read_mon_cdp_safe() self consistent Ben Horgan
2026-09-22  5:44   ` Gavin Shan
2026-10-02 15:17   ` James Morse
2026-09-17 14:56 ` [PATCH v2 10/12] arm_mpam: Don't loop forever if there is the maximum possible amount of PARTIDs Ben Horgan
2026-09-22  5:44   ` Gavin Shan
2026-10-02 15:18   ` James Morse
2026-09-17 14:56 ` [PATCH v2 11/12] arm_mpam: Switch to kvzmalloc_objs() for allocation of component cfg Ben Horgan
2026-09-22  5:45   ` Gavin Shan
2026-10-02 15:18   ` James Morse
2026-09-17 14:56 ` [PATCH v2 12/12] arm_mpam: resctrl: Don't stop early when tearing down a class Ben Horgan
2026-09-22  5:45   ` Gavin Shan
2026-10-07 23:48 ` [PATCH v2 00/12] arm_mpam: minor fixes at v7.2 Shaopeng Tan (Fujitsu)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260917145617.2202986-7-ben.horgan@arm.com \
    --to=ben.horgan@arm.com \
    --cc=andre.przywara@arm.com \
    --cc=dave.martin@arm.com \
    --cc=fenghuay@nvidia.com \
    --cc=gshan@redhat.com \
    --cc=james.morse@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=reinette.chatre@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox