From nobody Mon Feb 9 17:22:54 2026 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id ADF0337E2FB; Tue, 3 Feb 2026 21:46:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770155212; cv=none; b=bC+5TMA04gqGfAxOuBM90JkwzGt0gsRy6uY7DA8jQtdGGLFbDmdc1FgPpoOzvOPLMcX28/hp0Ma4s6fZ4dtkCbIToerA/uQdfmaJbscHHRFxKwtWQ7u3tuVa5o3VKRHMLosKuiyfIG0rulO9kMfojeir0wqO9iivWLK5/+LdG/8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1770155212; c=relaxed/simple; bh=hVW+Gzy6Nt+9kz6rJBw0MnzzsyIskH0otuTwEcCX1vc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KUwBsgV/8hYcXNynfVPdbHvYDJu59d38YSBG4cMdvYbHGmfKgPYnH7iwarMHnhxd0kQbBF3qmNiI7cDA6bH6JPRVbCO1dR5ehnaY/jpSu4Tg84py+FG0GjrEgCqXpY7B+sM2KSExH4nVIEHeNfjzOIUA0sWr61VcqfKZqVDQ2IY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id DAAB9339; Tue, 3 Feb 2026 13:46:43 -0800 (PST) Received: from e134344.cambridge.arm.com (e134344.arm.com [10.1.196.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id B05EC3F778; Tue, 3 Feb 2026 13:46:44 -0800 (PST) From: Ben Horgan To: ben.horgan@arm.com Cc: amitsinght@marvell.com, baisheng.gao@unisoc.com, baolin.wang@linux.alibaba.com, carl@os.amperecomputing.com, dave.martin@arm.com, david@kernel.org, dfustini@baylibre.com, fenghuay@nvidia.com, gshan@redhat.com, james.morse@arm.com, jonathan.cameron@huawei.com, kobak@nvidia.com, lcherian@marvell.com, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, peternewman@google.com, punit.agrawal@oss.qualcomm.com, quic_jiles@quicinc.com, reinette.chatre@intel.com, rohit.mathew@arm.com, scott@os.amperecomputing.com, sdonthineni@nvidia.com, tan.shaopeng@fujitsu.com, xhao@linux.alibaba.com, catalin.marinas@arm.com, will@kernel.org, corbet@lwn.net, maz@kernel.org, oupton@kernel.org, joey.gouly@arm.com, suzuki.poulose@arm.com, kvmarm@lists.linux.dev, zengheng4@huawei.com, linux-doc@vger.kernel.org, Shaopeng Tan Subject: [PATCH v4 29/41] arm_mpam: resctrl: Pre-allocate free running monitors Date: Tue, 3 Feb 2026 21:43:30 +0000 Message-ID: <20260203214342.584712-30-ben.horgan@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260203214342.584712-1-ben.horgan@arm.com> References: <20260203214342.584712-1-ben.horgan@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: James Morse When there are enough monitors, the resctrl mbm local and total files can be exposed. These need all the monitors that resctrl may use to be allocated up front. Add helpers to do this. If a different candidate class is discovered, the old array should be free'd and the allocated monitors returned to the driver. Tested-by: Gavin Shan Tested-by: Shaopeng Tan Tested-by: Peter Newman Signed-off-by: James Morse Reviewed-by: Jonathan Cameron Signed-off-by: Ben Horgan --- Changes since v2: Code flow tidying (Jonathan) --- drivers/resctrl/mpam_internal.h | 3 +- drivers/resctrl/mpam_resctrl.c | 81 ++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_interna= l.h index bab6eea60dae..5f4ac4fabc0d 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -356,7 +356,8 @@ struct mpam_resctrl_res { struct mpam_resctrl_mon { struct mpam_class *class; =20 - /* per-class data that resctrl needs will live here */ + /* Array of allocated MBWU monitors, indexed by (closid, rmid). */ + int *mbwu_idx_to_mon; }; =20 static inline int mpam_alloc_csu_mon(struct mpam_class *class) diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c index c96c434c9454..8c57fd48e560 100644 --- a/drivers/resctrl/mpam_resctrl.c +++ b/drivers/resctrl/mpam_resctrl.c @@ -645,10 +645,58 @@ static void mpam_resctrl_pick_mba(void) } } =20 +static void __free_mbwu_mon(struct mpam_class *class, int *array, + u16 num_mbwu_mon) +{ + for (int i =3D 0; i < num_mbwu_mon; i++) { + if (array[i] < 0) + continue; + + mpam_free_mbwu_mon(class, array[i]); + array[i] =3D ~0; + } +} + +static int __alloc_mbwu_mon(struct mpam_class *class, int *array, + u16 num_mbwu_mon) +{ + for (int i =3D 0; i < num_mbwu_mon; i++) { + int mbwu_mon =3D mpam_alloc_mbwu_mon(class); + + if (mbwu_mon < 0) { + __free_mbwu_mon(class, array, num_mbwu_mon); + return mbwu_mon; + } + array[i] =3D mbwu_mon; + } + + return 0; +} + +static int *__alloc_mbwu_array(struct mpam_class *class, u16 num_mbwu_mon) +{ + int err; + size_t array_size =3D num_mbwu_mon * sizeof(int); + int *array __free(kfree) =3D kmalloc(array_size, GFP_KERNEL); + + if (!array) + return ERR_PTR(-ENOMEM); + + memset(array, -1, array_size); + + err =3D __alloc_mbwu_mon(class, array, num_mbwu_mon); + if (err) + return ERR_PTR(err); + return_ptr(array); +} + static void counter_update_class(enum resctrl_event_id evt_id, struct mpam_class *class) { - struct mpam_class *existing_class =3D mpam_resctrl_counters[evt_id].class; + struct mpam_resctrl_mon *mon =3D &mpam_resctrl_counters[evt_id]; + struct mpam_class *existing_class =3D mon->class; + u16 num_mbwu_mon =3D class->props.num_mbwu_mon; + int *new_array, *existing_array =3D mon->mbwu_idx_to_mon; =20 if (existing_class) { if (class->level =3D=3D 3) { @@ -663,8 +711,37 @@ static void counter_update_class(enum resctrl_event_id= evt_id, } } =20 - mpam_resctrl_counters[evt_id].class =3D class; + pr_debug("Updating event %u to use class %u\n", evt_id, class->level); + + /* Might not need all the monitors */ + num_mbwu_mon =3D __mpam_monitors_free_running(num_mbwu_mon); + + if (evt_id !=3D QOS_L3_OCCUP_EVENT_ID && num_mbwu_mon) { + /* + * This is the pre-allocated free-running monitors path. It always + * allocates one monitor per PARTID * PMG. + */ + WARN_ON_ONCE(num_mbwu_mon !=3D resctrl_arch_system_num_rmid_idx()); + + new_array =3D __alloc_mbwu_array(class, num_mbwu_mon); + if (IS_ERR(new_array)) { + pr_debug("Failed to allocate MBWU array\n"); + return; + } + mon->mbwu_idx_to_mon =3D new_array; + + if (existing_array) { + pr_debug("Releasing previous class %u's monitors\n", + existing_class->level); + __free_mbwu_mon(existing_class, existing_array, num_mbwu_mon); + kfree(existing_array); + } + } else if (evt_id !=3D QOS_L3_OCCUP_EVENT_ID) { + pr_debug("Not pre-allocating free-running counters\n"); + } + exposed_mon_capable =3D true; + mon->class =3D class; } =20 static void mpam_resctrl_pick_counters(void) --=20 2.43.0