From nobody Tue Dec 16 14:50:58 2025 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 18C7B2DBF45 for ; Fri, 5 Dec 2025 22:01:06 +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=1764972068; cv=none; b=DFNBpNnKnA40YaGuIcoDs4rjDPvTF6Dy/q7CkYD9X5LSkbYwIvIKAYp+blSgvfGz07fh9Lu+1/yxBwExUvepvA5kLCFyXbM5C2rB+Tz2b6/1qB9N5irS3KlFcYfaLQ/dAtkXHbHLhDRa9j+XBI/C+JW5TObPnCaeagkpwsqhIws= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764972068; c=relaxed/simple; bh=EPm4zXEcn1HNjJPcJWC9poG5x/fikXJNRttL+pN2tqA=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=ED+eF6iMAE2XzElsM3iHogyG9zdrO/91SUg0AHjJF1VSdTj3Ericdiz7c3qE496BLEc4CnovBcUYzef6gJL9ElfPG3CPrMnmTMAgu5RQEEy0miUzN0utcUAkd8zE7xIiMQywDmVs8EQzSwp/6KgvazXotQEbnHUW/ZI+0yP6vnE= 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 B28E21BA8; Fri, 5 Dec 2025 14:00:58 -0800 (PST) Received: from merodach.members.linode.com (usa-sjc-mx-foss1.foss.arm.com [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4E9B53F740; Fri, 5 Dec 2025 14:01:02 -0800 (PST) From: James Morse To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: James Morse , D Scott Phillips OS , carl@os.amperecomputing.com, lcherian@marvell.com, bobo.shaobowang@huawei.com, tan.shaopeng@fujitsu.com, baolin.wang@linux.alibaba.com, Jamie Iles , Xin Hao , peternewman@google.com, dfustini@baylibre.com, amitsinght@marvell.com, David Hildenbrand , Dave Martin , Koba Ko , Shanker Donthineni , fenghuay@nvidia.com, baisheng.gao@unisoc.com, Jonathan Cameron , Gavin Shan , Ben Horgan , rohit.mathew@arm.com, reinette.chatre@intel.com, Punit Agrawal Subject: [RFC PATCH 24/38] arm_mpam: resctrl: Allow resctrl to allocate monitors Date: Fri, 5 Dec 2025 21:58:47 +0000 Message-Id: <20251205215901.17772-25-james.morse@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20251205215901.17772-1-james.morse@arm.com> References: <20251205215901.17772-1-james.morse@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" When resctrl wants to read a domain's 'QOS_L3_OCCUP', it needs to allocate a monitor on the corresponding resource. Monitors are allocated by class instead of component. MBM monitors are much more complicated, if there are enough monitors, they will be pre-allocated and free-running. If ABMC is in use instead then 'some' are pre-allocated in a different way, and need assigning. Add helpers to allocate a CSU monitor. These helper return an out of range value for MBM counters. Allocating a montitor context is expected to block until hardware resources become available. This only makes sense for QOS_L3_OCCUP as unallocated MBM counters are losing data. Signed-off-by: James Morse --- Since ABMC got merged it may be possible to remove the monitor alloc call for MBM counters from resctrl as this work is now done by ABMC's assign call. --- drivers/resctrl/mpam_internal.h | 14 ++++++- drivers/resctrl/mpam_resctrl.c | 68 +++++++++++++++++++++++++++++++++ include/linux/arm_mpam.h | 4 ++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_interna= l.h index 05101186af17..3a68ebd498fa 100644 --- a/drivers/resctrl/mpam_internal.h +++ b/drivers/resctrl/mpam_internal.h @@ -32,6 +32,14 @@ DECLARE_STATIC_KEY_FALSE(mpam_enabled); #define PACKED_FOR_KUNIT #endif =20 +/* + * This 'mon' values must not alias an actual monitor, so must be larger t= han + * U16_MAX, but not be confused with an errno value, so smaller than + * (u32)-SZ_4K. + * USE_PRE_ALLOCATED is used to avoid confusion with an actual monitor. + */ +#define USE_PRE_ALLOCATED (U16_MAX + 1) + static inline bool mpam_is_enabled(void) { return static_branch_likely(&mpam_enabled); @@ -215,7 +223,11 @@ enum mon_filter_options { }; =20 struct mon_cfg { - u16 mon; + /* + * mon must be large enough to hold out of range values like + * USE_RMID_IDX + */ + u32 mon; u8 pmg; bool match_pmg; bool csu_exclude_clean; diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c index 22ad5dd3c383..a2b238d47117 100644 --- a/drivers/resctrl/mpam_resctrl.c +++ b/drivers/resctrl/mpam_resctrl.c @@ -21,6 +21,8 @@ =20 #include "mpam_internal.h" =20 +DECLARE_WAIT_QUEUE_HEAD(resctrl_mon_ctx_waiters); + /* * The classes we've picked to map to resctrl resources, wrapped * in with their resctrl structure. @@ -287,6 +289,72 @@ struct rdt_resource *resctrl_arch_get_resource(enum re= sctrl_res_level l) return &mpam_resctrl_controls[l].resctrl_res; } =20 +static int resctrl_arch_mon_ctx_alloc_no_wait(enum resctrl_event_id evtid) +{ + struct mpam_resctrl_mon *mon =3D &mpam_resctrl_counters[evtid]; + + if (!mon->class) + return -EINVAL; + + switch (evtid) { + case QOS_L3_OCCUP_EVENT_ID: + /* With CDP, one monitor gets used for both code/data reads */ + return mpam_alloc_csu_mon(mon->class); + case QOS_L3_MBM_LOCAL_EVENT_ID: + case QOS_L3_MBM_TOTAL_EVENT_ID: + return USE_PRE_ALLOCATED; + default: + return -EOPNOTSUPP; + } +} + +void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r, + enum resctrl_event_id evtid) +{ + DEFINE_WAIT(wait); + int *ret; + + ret =3D kmalloc(sizeof(*ret), GFP_KERNEL); + if (!ret) + return ERR_PTR(-ENOMEM); + + do { + prepare_to_wait(&resctrl_mon_ctx_waiters, &wait, + TASK_INTERRUPTIBLE); + *ret =3D resctrl_arch_mon_ctx_alloc_no_wait(evtid); + if (*ret =3D=3D -ENOSPC) + schedule(); + } while (*ret =3D=3D -ENOSPC && !signal_pending(current)); + finish_wait(&resctrl_mon_ctx_waiters, &wait); + + return ret; +} + +static void resctrl_arch_mon_ctx_free_no_wait(enum resctrl_event_id evtid, + u32 mon_idx) +{ + struct mpam_resctrl_mon *mon =3D &mpam_resctrl_counters[evtid]; + + if (!mon->class) + return; + + if (evtid =3D=3D QOS_L3_OCCUP_EVENT_ID) + mpam_free_csu_mon(mon->class, mon_idx); + + wake_up(&resctrl_mon_ctx_waiters); +} + +void resctrl_arch_mon_ctx_free(struct rdt_resource *r, + enum resctrl_event_id evtid, void *arch_mon_ctx) +{ + u32 mon_idx =3D *(u32 *)arch_mon_ctx; + + kfree(arch_mon_ctx); + arch_mon_ctx =3D NULL; + + resctrl_arch_mon_ctx_free_no_wait(evtid, mon_idx); +} + static bool cache_has_usable_cpor(struct mpam_class *class) { struct mpam_props *cprops =3D &class->props; diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h index 385554ceb452..e1461e32af75 100644 --- a/include/linux/arm_mpam.h +++ b/include/linux/arm_mpam.h @@ -63,6 +63,10 @@ u32 resctrl_arch_rmid_idx_encode(u32 closid, u32 rmid); void resctrl_arch_rmid_idx_decode(u32 idx, u32 *closid, u32 *rmid); u32 resctrl_arch_system_num_rmid_idx(void); =20 +struct rdt_resource; +void *resctrl_arch_mon_ctx_alloc(struct rdt_resource *r, enum resctrl_even= t_id evtid); +void resctrl_arch_mon_ctx_free(struct rdt_resource *r, enum resctrl_event_= id evtid, void *ctx); + /** * mpam_register_requestor() - Register a requestor with the MPAM driver * @partid_max: The maximum PARTID value the requestor can generate. --=20 2.39.5