From: Jinjie Ruan <ruanjinjie@huawei.com>
To: Reinette Chatre <reinette.chatre@intel.com>, <ben.horgan@arm.com>,
<james.morse@arm.com>, <Dave.Martin@arm.com>,
<fenghuay@nvidia.com>
Cc: <tony.luck@intel.com>, <yu.c.chen@intel.com>,
<babu.moger@amd.com>, <fustini@kernel.org>,
<linux-arm-kernel@lists.infradead.org>,
<linux-kernel@vger.kernel.org>, <patches@lists.linux.dev>
Subject: Re: [RFC PATCH v2 05/10] arm_mpam: resctrl: Give the monitoring domain its own structure
Date: Mon, 26 Oct 2026 20:14:01 +0800 [thread overview]
Message-ID: <52fdd67b-49b6-44b6-8eaa-17b29fd92947@huawei.com> (raw)
In-Reply-To: <2238eab97cc66852d0d0d1a5c6ff191c03ce9e0d.1792443633.git.reinette.chatre@intel.com>
在 2026/10/20 6:07, Reinette Chatre 写道:
> One structure holds both the control domain and the monitoring domain of
> a resource. The two domains are allocated together when the first CPU of
> the domain comes online and freed together once both have lost their
> last CPU. A failure to set up the monitoring domain undoes the control
> domain.
>
> Apart from the code that manages domains, nothing uses both domains of
> the structure. Keeping them in one structure nevertheless ties each
> control domain to a monitoring domain, which does not fit supporting
> multiple controls per resource.
>
> Move the monitoring domain and its components into a new structure,
> struct mpam_resctrl_mon_dom. Manage control and monitoring domains
> separately when CPUs come online and go offline: look up, set up, and
> tear down each domain on its own and free it once it has lost its last
> CPU.
>
> Do not let a failure to set up one type of domain affect the other. Keep
> a control domain that was set up when setting up the monitoring domain
> for the same CPU fails, and set up the monitoring domain even when
> setting up the control domain fails. This is consistent with domain
> setup failures not failing CPU online: only domains that were set up are
> exposed through resctrl.
>
> Look for a component of the resource's class that contains the CPU only
> when setting up a control domain, since that component backs the
> control domain. Setting up a monitoring domain already fails if no
> monitoring class has a component for the CPU.
>
> Look up monitoring domains by L3 cache ID on all systems, as was already
> done on systems without controls. Monitoring domain IDs are always those
> of the L3, so this finds the same domain as looking it up through its
> control domain did.
>
> Drop the debug messages about resources without controls or monitors.
> They reported which of the two domains in the shared structure was left
> unused, which no longer applies now that each domain type has its own
> structure.
>
> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
> ---
> drivers/resctrl/mpam_internal.h | 5 +-
> drivers/resctrl/mpam_resctrl.c | 226 ++++++++++++++++----------------
> 2 files changed, 117 insertions(+), 114 deletions(-)
>
> diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
> index 84c7adbb1a40..1df439ecb055 100644
> --- a/drivers/resctrl/mpam_internal.h
> +++ b/drivers/resctrl/mpam_internal.h
> @@ -434,15 +434,16 @@ struct mpam_msc_ris {
>
> struct mpam_resctrl_dom {
> struct mpam_component *ctrl_comp;
> + struct rdt_ctrl_domain resctrl_ctrl_dom;
> +};
>
> +struct mpam_resctrl_mon_dom {
> /*
> * There is no single mon_comp because different events may be backed
> * by different class/components. mon_comp is indexed by the event
> * number.
> */
> struct mpam_component *mon_comp[QOS_NUM_EVENTS];
> -
> - struct rdt_ctrl_domain resctrl_ctrl_dom;
> struct rdt_l3_mon_domain resctrl_mon_dom;
> };
>
> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
> index 246560247a28..ce5519635c51 100644
> --- a/drivers/resctrl/mpam_resctrl.c
> +++ b/drivers/resctrl/mpam_resctrl.c
> @@ -510,7 +510,7 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr,
> u32 closid, u32 rmid, enum resctrl_event_id eventid,
> void *arch_priv, u64 *val, void *arch_mon_ctx)
> {
> - struct mpam_resctrl_dom *l3_dom;
> + struct mpam_resctrl_mon_dom *l3_dom;
> struct mpam_component *mon_comp;
> u32 mon_idx = *(u32 *)arch_mon_ctx;
> enum mpam_device_features mon_type;
> @@ -524,7 +524,7 @@ int resctrl_arch_rmid_read(struct rdt_resource *r, struct rdt_domain_hdr *hdr,
> if (eventid >= QOS_NUM_EVENTS || !mon->class)
> return -EINVAL;
>
> - l3_dom = container_of(hdr, struct mpam_resctrl_dom, resctrl_mon_dom.hdr);
> + l3_dom = container_of(hdr, struct mpam_resctrl_mon_dom, resctrl_mon_dom.hdr);
> mon_comp = l3_dom->mon_comp[eventid];
>
> if (eventid != QOS_L3_OCCUP_EVENT_ID)
> @@ -542,7 +542,7 @@ int resctrl_arch_cntr_read(struct rdt_resource *r, struct rdt_l3_mon_domain *d,
> enum resctrl_event_id eventid, u64 *val)
> {
> struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[eventid];
> - struct mpam_resctrl_dom *l3_dom;
> + struct mpam_resctrl_mon_dom *l3_dom;
> struct mpam_component *mon_comp;
>
> if (!mpam_is_enabled())
> @@ -551,7 +551,7 @@ int resctrl_arch_cntr_read(struct rdt_resource *r, struct rdt_l3_mon_domain *d,
> if (eventid == QOS_L3_OCCUP_EVENT_ID || !mon->class)
> return -EINVAL;
>
> - l3_dom = container_of(d, struct mpam_resctrl_dom, resctrl_mon_dom);
> + l3_dom = container_of(d, struct mpam_resctrl_mon_dom, resctrl_mon_dom);
> mon_comp = l3_dom->mon_comp[eventid];
Maybe following code could be extracted into a helper
553 >-------if (!mpam_is_enabled())
554 >------->-------return -EINVAL;
555
556 >-------if (eventid == QOS_L3_OCCUP_EVENT_ID || !mon->class)
557 >------->-------return -EINVAL;
558
559 >-------l3_dom = container_of(d, struct mpam_resctrl_dom,
resctrl_mon_dom);
560 >-------mon_comp = l3_dom->mon_comp[eventid];
>
> return read_mon_cdp_safe(mon, mon_comp, mpam_feat_msmon_mbwu,
> @@ -599,7 +599,7 @@ void resctrl_arch_reset_cntr(struct rdt_resource *r, struct rdt_l3_mon_domain *d
> enum resctrl_event_id eventid)
> {
> struct mpam_resctrl_mon *mon = &mpam_resctrl_counters[eventid];
> - struct mpam_resctrl_dom *l3_dom;
> + struct mpam_resctrl_mon_dom *l3_dom;
> struct mpam_component *mon_comp;
>
> if (!mpam_is_enabled())
> @@ -608,7 +608,7 @@ void resctrl_arch_reset_cntr(struct rdt_resource *r, struct rdt_l3_mon_domain *d
> if (eventid == QOS_L3_OCCUP_EVENT_ID || !mon->class)
> return;
>
> - l3_dom = container_of(d, struct mpam_resctrl_dom, resctrl_mon_dom);
> + l3_dom = container_of(d, struct mpam_resctrl_mon_dom, resctrl_mon_dom);
> mon_comp = l3_dom->mon_comp[eventid];
>
> reset_mon_cdp_safe(mon, mon_comp, USE_PRE_ALLOCATED, closid, rmid);
> @@ -1638,7 +1638,7 @@ static int mpam_resctrl_setup_ctrl_domain(unsigned int cpu,
>
> static int mpam_resctrl_setup_mon_domain(unsigned int cpu,
> struct rdt_resource *r,
> - struct mpam_resctrl_dom *dom)
> + struct mpam_resctrl_mon_dom *dom)
> {
> struct rdt_l3_mon_domain *mon_d = &dom->resctrl_mon_dom;
> struct mpam_component *any_mon_comp = NULL;
> @@ -1681,53 +1681,6 @@ static int mpam_resctrl_setup_mon_domain(unsigned int cpu,
> return 0;
> }
>
> -static void mpam_resctrl_alloc_domain(unsigned int cpu,
> - struct mpam_resctrl_res *res)
> -{
> - int err;
> - struct mpam_resctrl_dom *dom;
> - struct mpam_class *class = res->class;
> - struct mpam_component *comp;
> - struct rdt_resource *r = &res->resctrl_res;
> -
> - lockdep_assert_held(&domain_list_lock);
> -
> - comp = find_component(class, cpu);
> - /* class has no component for this CPU */
> - if (WARN_ON_ONCE(!comp))
> - return;
> -
> - dom = kzalloc_node(sizeof(*dom), GFP_KERNEL, cpu_to_node(cpu));
> - if (!dom)
> - return;
> -
> - if (r->alloc_capable) {
> - err = mpam_resctrl_setup_ctrl_domain(cpu, r, comp, dom);
> - if (err)
> - goto free_domain;
> - } else {
> - pr_debug("Skipped control domain online - no controls\n");
> - }
> -
> - if (r->mon_capable) {
> - err = mpam_resctrl_setup_mon_domain(cpu, r, dom);
> - if (err)
> - goto offline_ctrl_domain;
> - } else {
> - pr_debug("Skipped monitor domain online - no monitors\n");
> - }
> -
> - return;
> -
> -offline_ctrl_domain:
> - if (r->alloc_capable) {
> - mpam_resctrl_offline_domain_hdr(cpu, &dom->resctrl_ctrl_dom.hdr);
> - resctrl_offline_ctrl_domain(r, &dom->resctrl_ctrl_dom);
> - }
> -free_domain:
> - kfree(dom);
> -}
> -
> /*
> * We know all the monitors are associated with the L3, even if there are no
> * controls and therefore no control component. Find the cache-id for the CPU
> @@ -1735,10 +1688,10 @@ static void mpam_resctrl_alloc_domain(unsigned int cpu,
> * This relies on mpam_resctrl_pick_domain_id() using the L3 cache-id
> * for anything that is not a cache.
> */
> -static struct mpam_resctrl_dom *mpam_resctrl_get_mon_domain_from_cpu(int cpu)
> +static struct mpam_resctrl_mon_dom *mpam_resctrl_get_mon_domain_from_cpu(int cpu)
> {
> int cache_id;
> - struct mpam_resctrl_dom *dom;
> + struct mpam_resctrl_mon_dom *dom;
> struct mpam_resctrl_res *l3 = &mpam_resctrl_controls[RDT_RESOURCE_L3];
>
> lockdep_assert_cpus_held();
> @@ -1758,7 +1711,7 @@ static struct mpam_resctrl_dom *mpam_resctrl_get_mon_domain_from_cpu(int cpu)
> }
>
> static struct mpam_resctrl_dom *
> -mpam_resctrl_get_domain_from_cpu(int cpu, struct mpam_resctrl_res *res)
> +mpam_resctrl_get_ctrl_domain_from_cpu(int cpu, struct mpam_resctrl_res *res)
> {
> struct mpam_resctrl_dom *dom;
> struct rdt_resource *r = &res->resctrl_res;
> @@ -1770,11 +1723,97 @@ mpam_resctrl_get_domain_from_cpu(int cpu, struct mpam_resctrl_res *res)
> return dom;
> }
>
> - if (r->rid != RDT_RESOURCE_L3)
> - return NULL;
> + return NULL;
LGTM
Reviewed-by: Jinjie Ruan <ruanjinjie@huawei.com>
> +}
> +
> +static void mpam_resctrl_add_cpu_ctrl_domain(unsigned int cpu,
> + struct mpam_resctrl_res *res)
> +{
> + struct rdt_resource *r = &res->resctrl_res;
> + struct mpam_resctrl_dom *dom;
> + struct mpam_component *comp;
> +
> + lockdep_assert_held(&domain_list_lock);
> +
> + dom = mpam_resctrl_get_ctrl_domain_from_cpu(cpu, res);
> + if (dom) {
> + mpam_resctrl_online_domain_hdr(cpu, &dom->resctrl_ctrl_dom.hdr);
> + return;
> + }
> +
> + comp = find_component(res->class, cpu);
> + /* class has no component for this CPU */
> + if (WARN_ON_ONCE(!comp))
> + return;
> +
> + dom = kzalloc_node(sizeof(*dom), GFP_KERNEL, cpu_to_node(cpu));
> + if (!dom)
> + return;
>
> - /* Search the mon domain list too - needed on monitor only platforms. */
> - return mpam_resctrl_get_mon_domain_from_cpu(cpu);
> + if (mpam_resctrl_setup_ctrl_domain(cpu, r, comp, dom))
> + kfree(dom);
> +}
> +
> +static void mpam_resctrl_add_cpu_mon_domain(unsigned int cpu,
> + struct mpam_resctrl_res *res)
> +{
> + struct rdt_resource *r = &res->resctrl_res;
> + struct mpam_resctrl_mon_dom *dom;
> +
> + lockdep_assert_held(&domain_list_lock);
> +
> + dom = mpam_resctrl_get_mon_domain_from_cpu(cpu);
> + if (dom) {
> + mpam_resctrl_online_domain_hdr(cpu, &dom->resctrl_mon_dom.hdr);
> + return;
> + }
> +
> + dom = kzalloc_node(sizeof(*dom), GFP_KERNEL, cpu_to_node(cpu));
> + if (!dom)
> + return;
> +
> + if (mpam_resctrl_setup_mon_domain(cpu, r, dom))
> + kfree(dom);
> +}
> +
> +static void mpam_resctrl_remove_cpu_ctrl_domain(unsigned int cpu,
> + struct mpam_resctrl_res *res)
> +{
> + struct rdt_resource *r = &res->resctrl_res;
> + struct mpam_resctrl_dom *dom;
> +
> + lockdep_assert_held(&domain_list_lock);
> +
> + /* The domain may be missing if its setup failed. */
> + dom = mpam_resctrl_get_ctrl_domain_from_cpu(cpu, res);
> + if (!dom)
> + return;
> +
> + if (!mpam_resctrl_offline_domain_hdr(cpu, &dom->resctrl_ctrl_dom.hdr))
> + return;
> +
> + resctrl_offline_ctrl_domain(r, &dom->resctrl_ctrl_dom);
> + kfree(dom);
> +}
> +
> +static void mpam_resctrl_remove_cpu_mon_domain(unsigned int cpu,
> + struct mpam_resctrl_res *res)
> +{
> + struct rdt_resource *r = &res->resctrl_res;
> + struct mpam_resctrl_mon_dom *dom;
> +
> + lockdep_assert_held(&domain_list_lock);
> +
> + /* The domain may be missing if its setup failed. */
> + dom = mpam_resctrl_get_mon_domain_from_cpu(cpu);
> + if (!dom)
> + return;
> +
> + if (!mpam_resctrl_offline_domain_hdr(cpu, &dom->resctrl_mon_dom.hdr))
> + return;
> +
> + resctrl_offline_mon_domain(r, &dom->resctrl_mon_dom.hdr);
> + kfree(dom);
> }
>
> void mpam_resctrl_online_cpu(unsigned int cpu)
> @@ -1784,33 +1823,21 @@ void mpam_resctrl_online_cpu(unsigned int cpu)
>
> guard(mutex)(&domain_list_lock);
> for_each_mpam_resctrl_control(res, rid) {
> - struct mpam_resctrl_dom *dom;
> struct rdt_resource *r = &res->resctrl_res;
>
> if (!res->class)
> continue; // dummy_resource;
>
> - dom = mpam_resctrl_get_domain_from_cpu(cpu, res);
> - if (!dom) {
> - /*
> - * On failure the CPU is left without a domain for this
> - * resource, which mpam_resctrl_offline_cpu() tolerates.
> - * resctrl_online_cpu() still adds the CPU to the default
> - * group because the CPU is online and runs tasks.
> - */
> - mpam_resctrl_alloc_domain(cpu, res);
> - } else {
> - if (r->alloc_capable) {
> - struct rdt_ctrl_domain *ctrl_d = &dom->resctrl_ctrl_dom;
> -
> - mpam_resctrl_online_domain_hdr(cpu, &ctrl_d->hdr);
> - }
> - if (r->mon_capable) {
> - struct rdt_l3_mon_domain *mon_d = &dom->resctrl_mon_dom;
> -
> - mpam_resctrl_online_domain_hdr(cpu, &mon_d->hdr);
> - }
> - }
> + /*
> + * A domain that fails to be set up leaves the CPU without that
> + * domain, which mpam_resctrl_offline_cpu() tolerates.
> + * resctrl_online_cpu() still adds the CPU to the default group
> + * because the CPU is online and runs tasks.
> + */
> + if (r->alloc_capable)
> + mpam_resctrl_add_cpu_ctrl_domain(cpu, res);
> + if (r->mon_capable)
> + mpam_resctrl_add_cpu_mon_domain(cpu, res);
> }
>
> resctrl_online_cpu(cpu);
> @@ -1825,40 +1852,15 @@ void mpam_resctrl_offline_cpu(unsigned int cpu)
>
> guard(mutex)(&domain_list_lock);
> for_each_mpam_resctrl_control(res, rid) {
> - struct mpam_resctrl_dom *dom;
> - struct rdt_l3_mon_domain *mon_d;
> - struct rdt_ctrl_domain *ctrl_d;
> - bool ctrl_dom_empty, mon_dom_empty;
> struct rdt_resource *r = &res->resctrl_res;
>
> if (!res->class)
> continue; // dummy resource
>
> - /* The domain may be missing if its setup failed. */
> - dom = mpam_resctrl_get_domain_from_cpu(cpu, res);
> - if (!dom)
> - continue;
> -
> - if (r->alloc_capable) {
> - ctrl_d = &dom->resctrl_ctrl_dom;
> - ctrl_dom_empty = mpam_resctrl_offline_domain_hdr(cpu, &ctrl_d->hdr);
> - if (ctrl_dom_empty)
> - resctrl_offline_ctrl_domain(&res->resctrl_res, ctrl_d);
> - } else {
> - ctrl_dom_empty = true;
> - }
> -
> - if (r->mon_capable) {
> - mon_d = &dom->resctrl_mon_dom;
> - mon_dom_empty = mpam_resctrl_offline_domain_hdr(cpu, &mon_d->hdr);
> - if (mon_dom_empty)
> - resctrl_offline_mon_domain(&res->resctrl_res, &mon_d->hdr);
> - } else {
> - mon_dom_empty = true;
> - }
> -
> - if (ctrl_dom_empty && mon_dom_empty)
> - kfree(dom);
> + if (r->alloc_capable)
> + mpam_resctrl_remove_cpu_ctrl_domain(cpu, res);
> + if (r->mon_capable)
> + mpam_resctrl_remove_cpu_mon_domain(cpu, res);
> }
> }
>
--
Best regards,
Jinjie
next prev parent reply other threads:[~2026-10-26 12:15 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 22:07 [RFC PATCH v2 00/10] arm_mpam: resctrl: Separate MPAM domains Reinette Chatre
2026-10-19 22:07 ` [RFC PATCH v2 01/10] arm_mpam: resctrl: Use find_component() when allocating a domain Reinette Chatre
2026-10-23 8:07 ` Jinjie Ruan
2026-10-23 14:52 ` Reinette Chatre
2026-10-19 22:07 ` [RFC PATCH v2 02/10] arm_mpam: resctrl: Rename ctrl_comp in mpam_resctrl_alloc_domain() Reinette Chatre
2026-10-23 8:08 ` Jinjie Ruan
2026-10-23 14:53 ` Reinette Chatre
2026-10-19 22:07 ` [RFC PATCH v2 03/10] arm_mpam: resctrl: Do not fail CPU online when domain setup fails Reinette Chatre
2026-10-26 9:51 ` Jinjie Ruan
2026-10-19 22:07 ` [RFC PATCH v2 04/10] arm_mpam: resctrl: Split control and monitoring domain setup into helpers Reinette Chatre
2026-10-26 11:49 ` Jinjie Ruan
2026-10-19 22:07 ` [RFC PATCH v2 05/10] arm_mpam: resctrl: Give the monitoring domain its own structure Reinette Chatre
2026-10-26 12:14 ` Jinjie Ruan [this message]
2026-10-26 16:55 ` Reinette Chatre
2026-10-27 1:12 ` Jinjie Ruan
2026-10-19 22:07 ` [RFC PATCH v2 06/10] arm_mpam: resctrl: Rename struct mpam_resctrl_dom to mpam_resctrl_ctrl_dom Reinette Chatre
2026-10-26 12:40 ` Jinjie Ruan
2026-10-19 22:07 ` [RFC PATCH v2 07/10] arm_mpam: resctrl: Warn when no monitoring component is found for a CPU Reinette Chatre
2026-10-26 13:14 ` Jinjie Ruan
2026-10-19 22:07 ` [RFC PATCH v2 08/10] arm_mpam: resctrl: Require a component for each monitoring event Reinette Chatre
2026-10-19 22:07 ` [RFC PATCH v2 09/10] arm_mpam: resctrl: Require monitoring components to cover the same CPUs Reinette Chatre
2026-10-19 22:07 ` [RFC PATCH v2 10/10] arm_mpam: resctrl: Update the comment on monitoring domain setup Reinette Chatre
2026-10-22 10:45 ` [RFC PATCH v2 00/10] arm_mpam: resctrl: Separate MPAM domains Ben Horgan
2026-10-22 15:43 ` Reinette Chatre
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=52fdd67b-49b6-44b6-8eaa-17b29fd92947@huawei.com \
--to=ruanjinjie@huawei.com \
--cc=Dave.Martin@arm.com \
--cc=babu.moger@amd.com \
--cc=ben.horgan@arm.com \
--cc=fenghuay@nvidia.com \
--cc=fustini@kernel.org \
--cc=james.morse@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@lists.linux.dev \
--cc=reinette.chatre@intel.com \
--cc=tony.luck@intel.com \
--cc=yu.c.chen@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