[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID:
<OSZPR01MB87980DA8A2534414337384608B85A@OSZPR01MB8798.jpnprd01.prod.outlook.com>
Date: Thu, 8 Jan 2026 10:44:54 +0000
From: "Shaopeng Tan (Fujitsu)" <tan.shaopeng@...itsu.com>
To: Ben Horgan <ben.horgan@....com>
CC: "amitsinght@...vell.com" <amitsinght@...vell.com>,
"baisheng.gao@...soc.com" <baisheng.gao@...soc.com>,
"baolin.wang@...ux.alibaba.com" <baolin.wang@...ux.alibaba.com>,
"carl@...amperecomputing.com" <carl@...amperecomputing.com>,
"dave.martin@....com" <dave.martin@....com>, "david@...nel.org"
<david@...nel.org>, "dfustini@...libre.com" <dfustini@...libre.com>,
"fenghuay@...dia.com" <fenghuay@...dia.com>, "gshan@...hat.com"
<gshan@...hat.com>, "james.morse@....com" <james.morse@....com>,
"jonathan.cameron@...wei.com" <jonathan.cameron@...wei.com>,
"kobak@...dia.com" <kobak@...dia.com>, "lcherian@...vell.com"
<lcherian@...vell.com>, "linux-arm-kernel@...ts.infradead.org"
<linux-arm-kernel@...ts.infradead.org>, "linux-kernel@...r.kernel.org"
<linux-kernel@...r.kernel.org>, "peternewman@...gle.com"
<peternewman@...gle.com>, "punit.agrawal@....qualcomm.com"
<punit.agrawal@....qualcomm.com>, "quic_jiles@...cinc.com"
<quic_jiles@...cinc.com>, "reinette.chatre@...el.com"
<reinette.chatre@...el.com>, "rohit.mathew@....com" <rohit.mathew@....com>,
"scott@...amperecomputing.com" <scott@...amperecomputing.com>,
"sdonthineni@...dia.com" <sdonthineni@...dia.com>, "xhao@...ux.alibaba.com"
<xhao@...ux.alibaba.com>, "catalin.marinas@....com"
<catalin.marinas@....com>, "will@...nel.org" <will@...nel.org>,
"corbet@....net" <corbet@....net>, "maz@...nel.org" <maz@...nel.org>,
"oupton@...nel.org" <oupton@...nel.org>, "joey.gouly@....com"
<joey.gouly@....com>, "suzuki.poulose@....com" <suzuki.poulose@....com>,
"kvmarm@...ts.linux.dev" <kvmarm@...ts.linux.dev>
Subject: Re: [PATCH v2 27/45] arm_mpam: resctrl: Add support for csu counters
Hello Ben,
> From: James Morse <james.morse@....com>
>
> resctrl exposes a counter via a file named llc_occupancy. This isn't really
> a counter as its value goes up and down, this is a snapshot of the cache
> storage usage monitor.
>
> Add some picking code to find a cache as close as possible to the L3 that
> supports the CSU monitor.
>
> If there is an L3, but it doesn't have any controls, force the L3 resource
> to exist. The existing topology_matches_l3() and
> mpam_resctrl_domain_hdr_init() code will ensure this looks like the L3,
> even if the class belongs to a later cache.
>
> Signed-off-by: James Morse <james.morse@....com>
> Signed-off-by: Ben Horgan <ben.horgan@....com>
> ---
> Changes since rfc:
> Allow csu counters however many partid or pmg there are
> else if -> if
> reduce scope of local variables
> drop has_csu
> ---
> drivers/resctrl/mpam_internal.h | 6 ++
> drivers/resctrl/mpam_resctrl.c | 148 ++++++++++++++++++++++++++++++++
> 2 files changed, 154 insertions(+)
>
> diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
> index b9a739abb101..9cb9eb97893b 100644
> --- a/drivers/resctrl/mpam_internal.h
> +++ b/drivers/resctrl/mpam_internal.h
> @@ -345,6 +345,12 @@ struct mpam_resctrl_res {
> struct rdt_resource resctrl_res;
> };
>
> +struct mpam_resctrl_mon {
> + struct mpam_class *class;
> +
> + /* per-class data that resctrl needs will live here */
> +};
> +
> static inline int mpam_alloc_csu_mon(struct mpam_class *class)
> {
> struct mpam_props *cprops = &class->props;
> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
> index f8d8c241797a..5fde610cc9d7 100644
> --- a/drivers/resctrl/mpam_resctrl.c
> +++ b/drivers/resctrl/mpam_resctrl.c
> @@ -31,6 +31,16 @@ static struct mpam_resctrl_res mpam_resctrl_controls[RDT_NUM_RESOURCES];
> /* The lock for modifying resctrl's domain lists from cpuhp callbacks. */
> static DEFINE_MUTEX(domain_list_lock);
>
> +/*
> + * The classes we've picked to map to resctrl events.
> + * Resctrl believes all the worlds a Xeon, and these are all on the L3. This
> + * array lets us find the actual class backing the event counters. e.g.
> + * the only memory bandwidth counters may be on the memory controller, but to
> + * make use of them, we pretend they are on L3.
> + * Class pointer may be NULL.
> + */
> +static struct mpam_resctrl_mon mpam_resctrl_counters[QOS_NUM_EVENTS];
> +
> static bool exposed_alloc_capable;
> static bool exposed_mon_capable;
>
> @@ -258,6 +268,28 @@ static bool class_has_usable_mba(struct mpam_props *cprops)
> return mba_class_use_mbw_max(cprops);
> }
>
> +static bool cache_has_usable_csu(struct mpam_class *class)
> +{
> + struct mpam_props *cprops;
> +
> + if (!class)
> + return false;
> +
> + cprops = &class->props;
> +
> + if (!mpam_has_feature(mpam_feat_msmon_csu, cprops))
> + return false;
> +
> + /*
> + * CSU counters settle on the value, so we can get away with
> + * having only one.
> + */
> + if (!cprops->num_csu_mon)
> + return false;
> +
> + return true;
> +}
> +
> /*
> * Calculate the worst-case percentage change from each implemented step
> * in the control.
> @@ -498,6 +530,64 @@ static void mpam_resctrl_pick_mba(void)
> }
> }
>
> +static void counter_update_class(enum resctrl_event_id evt_id,
> + struct mpam_class *class)
> +{
> + struct mpam_class *existing_class = mpam_resctrl_counters[evt_id].class;
> +
> + if (existing_class) {
> + if (class->level == 3) {
> + pr_debug("Existing class is L3 - L3 wins\n");
> + return;
> + }
> +
> + if (existing_class->level < class->level) {
> + pr_debug("Existing class is closer to L3, %u versus %u - closer is better\n",
> + existing_class->level, class->level);
> + return;
> + }
> + }
> +
> + mpam_resctrl_counters[evt_id].class = class;
> + exposed_mon_capable = true;
> +}
> +
> +static void mpam_resctrl_pick_counters(void)
> +{
> + struct mpam_class *class;
> +
> + lockdep_assert_cpus_held();
> +
> + guard(srcu)(&mpam_srcu);
> + list_for_each_entry_srcu(class, &mpam_classes, classes_list,
> + srcu_read_lock_held(&mpam_srcu)) {
> + if (class->level < 3) {
> + pr_debug("class %u is before L3", class->level);
> + continue;
> + }
> +
> + if (!cpumask_equal(&class->affinity, cpu_possible_mask)) {
> + pr_debug("class %u does not cover all CPUs",
> + class->level);
> + continue;
> + }
> +
> + if (cache_has_usable_csu(class) && topology_matches_l3(class)) {
> + pr_debug("class %u has usable CSU, and matches L3 topology",
> + class->level);
> +
> + /* CSU counters only make sense on a cache. */
> + switch (class->type) {
> + case MPAM_CLASS_CACHE:
> + counter_update_class(QOS_L3_OCCUP_EVENT_ID, class);
> + return;
> + default:
> + return;
> + }
> + }
> + }
> +}
> +
> static int mpam_resctrl_control_init(struct mpam_resctrl_res *res,
> enum resctrl_res_level type)
> {
> @@ -577,6 +667,50 @@ static int mpam_resctrl_pick_domain_id(int cpu, struct mpam_component *comp)
> return comp->comp_id;
> }
>
> +static void mpam_resctrl_monitor_init(struct mpam_resctrl_mon *mon,
> + enum resctrl_event_id type)
> +{
> + struct mpam_resctrl_res *res = &mpam_resctrl_controls[RDT_RESOURCE_L3];
> + struct rdt_resource *l3 = &res->resctrl_res;
> +
> + lockdep_assert_cpus_held();
> +
> + /* There also needs to be an L3 cache present */
> + if (get_cpu_cacheinfo_id(smp_processor_id(), 3) == -1)
> + return;
> +
> + /*
> + * If there are no MPAM resources on L3, force it into existence.
> + * topology_matches_l3() already ensures this looks like the L3.
> + * The domain-ids will be fixed up by mpam_resctrl_domain_hdr_init().
> + */
> + if (!res->class) {
> + pr_warn_once("Faking L3 MSC to enable counters.\n");
> + res->class = mpam_resctrl_counters[type].class;
> + }
> +
> + /* Called multiple times!, once per event type */
> + if (exposed_mon_capable) {
> + l3->mon_capable = true;
> +
> + /* Setting name is necessary on monitor only platforms */
> + l3->name = "L3";
> + l3->mon_scope = RESCTRL_L3_CACHE;
> +
> + resctrl_enable_mon_event(type);
> +
> + /*
> + * Unfortunately, num_rmid doesn't mean anything for
> + * mpam, and its exposed to user-space!
> + * num-rmid is supposed to mean the number of groups
> + * that can be created, both control or monitor groups.
> + * For mpam, each control group has its own pmg/rmid
> + * space.
> + */
> + l3->mon.num_rmid = 1;
> + }
> +}
Dave posted the following patch, Will you apply it?
https://lore.kernel.org/lkml/20250820131621.54983-1-Dave.Martin@arm.com/
Best regards,
Shaopeng TAN
> u32 resctrl_arch_get_config(struct rdt_resource *r, struct rdt_ctrl_domain *d,
> u32 closid, enum resctrl_conf_type type)
> {
> @@ -977,6 +1111,20 @@ int mpam_resctrl_setup(void)
> break;
> }
> }
> +
> + /* Find some classes to use for monitors */
> + mpam_resctrl_pick_counters();
> +
> + for (enum resctrl_event_id j = 0; j < QOS_NUM_EVENTS; j++) {
> + struct mpam_resctrl_mon *mon;
> +
> + mon = &mpam_resctrl_counters[j];
> + if (!mon->class)
> + continue; // dummy resource
> +
> + mpam_resctrl_monitor_init(mon, j);
> + }
> +
> cpus_read_unlock();
>
> if (err) {
> --
> 2.43.0
>
>
>
Powered by blists - more mailing lists