All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chen Yu <chen.yu@linux.dev>
To: Reinette Chatre <reinette.chatre@intel.com>
Cc: Chen Yu <yu.c.chen@intel.com>,
	tony.luck@intel.com, tglx@kernel.org, bp@alien8.de,
	mingo@redhat.com, dave.hansen@linux.intel.com, hpa@zytor.com,
	fenghuay@nvidia.com, babu.moger@amd.com, x86@kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH v6 3/9] x86/resctrl: Parse ACPI ERDT table and save CACD cpumask for RMDD domains
Date: Tue, 25 Aug 2026 16:06:41 +0800	[thread overview]
Message-ID: <ao1NEdfiUt5OYMQ0@three-body> (raw)
In-Reply-To: <9a86b245-916a-43ed-9bee-897aa3432a89@intel.com>

Hi Reinette,

On Wed, Aug 19, 2026 at 04:01:33PM -0700, Reinette Chatre wrote:
> 
> Hi Chenyu,
> 
> On 7/25/26 2:22 AM, Chen Yu wrote:
> > From: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
> > 
> > Parse the RMDD subtables within the ERDT ACPI table and their nested
> > CACD entries to construct per-domain CPU masks.
> 
> The changelog always needs to start with context. Please see "Changelog"
> in Documentation/process/maintainer-tip.rst for complete expectations.
>

OK, I will first add some background information (including what ERDT and CACD are).

> > 
> > There is one ERDT table per platform. Each RMDD describes one resource
> 
> I do not think what "RMDD" stands for has been introduced at this point yet.
> 
> > management domain (RMD), also known as an L3 domain, and carries MMIO
> > base information for later monitoring support.
> > 
> > For each RMDD, parse the associated CACD, map its x2APIC IDs to logical
> 
> What is "CACD"? Please always expand acronym before its first use.
> 
> > CPUs, and save the resulting CPU mask. This mask associates each ERDT
> > domain with the CPUs that belong to it and is used later when attaching
> > ERDT data to resctrl monitoring domains.
> 
> Please let each patch description stand on its own without referring to later
> patches in series. If a patch provides capability in preparation for
> future changes then you can use language like, 
> "Associate every ERDT domain with the CPUs that belong to it to prepare
>  for attaching ERDT data to resctrl monitoring domains."
>

Thanks for the guidance, will adjust it.
 
> >  static __init bool get_rdt_resources(void)
> >  {
> > +	erdt_init();
> >  	rdt_alloc_capable = get_rdt_alloc_resources();
> >  	rdt_mon_capable = get_rdt_mon_resources();
> >  
> 
> Functions are not expected to leave dangling state when they return failure. get_rdt_resources()
> returning false is considered a failure and now the caller is left to clean up the dangling
> state which is not a familiar pattern to use and thus something that can/will trip people.
> 
> On top of this this implementation pushes the cleanup very far from even the caller making
> this unfamiliar pattern even harder to recognize.
> 
> Please let get_rdt_resources() clean up after itself on failure to find any resources. 
>

The original intent was to encapsulate the cleanup logic as a helper function (erdt_exit()), 
since it is needed in multiple places across the code. All other call sites invoke this function
when necessary. If we place the cleanup call directly inside resctrl_arch_late_init(), it would
only execute erdt_exit() once within that function. Alternatively, if we let get_rdt_resources()
handle cleanup via erdt_exit(), then we would need to add explicit erdt_exit() calls in 
__resctrl_arch_late_init() for each failure path - for example, when cpuhp_setup_state() fails or
when resctrl_init() fails. Anyway, if code readability is a priority, I'll change the logic
as suggested.

> > @@ -1114,7 +1115,7 @@ void resctrl_cpu_detect(struct cpuinfo_x86 *c)
> >  	}
> >  }
> >  
> > -static int __init resctrl_arch_late_init(void)
> > +static int __init __resctrl_arch_late_init(void)
> >  {
> >  	struct rdt_resource *r;
> >  	int state, ret, i;
> > @@ -1157,6 +1158,15 @@ static int __init resctrl_arch_late_init(void)
> >  	return 0;
> >  }
> >  
> > +static int __init resctrl_arch_late_init(void)
> > +{
> > +	int ret = __resctrl_arch_late_init();
> > +
> > +	if (ret)
> > +		erdt_exit();
> > +	return ret;
> > +}
> 
> Related to earlier comment on cleanup I find this cleanup to be asymmentrical
> and inconsistent with how resctrl usually does cleanup. Why not do cleanup in
> (original) resctrl_arch_late_init() to be consistent with other cleanup when
> failures are encountered during initialization, for example, cpuhp_remove_state()?
> I find that having the cleanup handled where error is encountered is easier to understand.
>

Thomas previously suggested this approach to avoid using goto.
https://lore.kernel.org/lkml/871pem5jnh.ffs@fw13/
However, I agree that we can adopt the individual cleanup strategy instead, as it
will improve code readability.
 
> > +
> >  late_initcall(resctrl_arch_late_init);
> >  
> >  static void __exit resctrl_arch_exit(void)
> > @@ -1166,6 +1176,8 @@ static void __exit resctrl_arch_exit(void)
> >  	cpuhp_remove_state(rdt_online);
> >  
> >  	resctrl_exit();
> > +
> > +	erdt_exit();
> 
> 
> Here the cleanup is indeed done in the same place as cleanup of
> other init work (cpuhp_remove_state()).
>

Understood. I will ensure consistency whenever cpuhp_remove_state() is called, erdt_exit()
will also be invoked in the original resctrl_arch_late_init().

> >  }
> > +/* True when the ERDT ACPI table describes at least one domain with at least one CPU. */
> > +static bool erdt_enabled;
> > +
> > +#define ERDT_VALID_VERSION		1
> > +#define RMDD_FLAG_CPU_L3_DOMAIN		BIT(0)
> > +
> > +/* Bitmask of valid sub-tables found in the first RMDD, used to ensure all RMDDs match. */
> > +static u32 valid_subtbl_mask;
> > +
> > +/* Domain ID of the first RMDD that established @valid_subtbl_mask, for diagnostics. */
> > +static u16 first_rmdd_domain_id;
> > +
> > +static int erdt_max_rmid;
> 
> Could this ever be negative? Could this instead be of same type as the value it is
> initialized with? Looks like this will improve type safety with the min_t() usage then
> using the accurate and consistent type of both parameters?
>

It should not be negative, let me convert it into u32 and use min() directly.
 
> I also think a comment describing erdt_max_rmid will be helpful, especially considering
> that it has "max" in its name but then its value is determined using the *minimum* of
> all domains' RMID?
>

OK, let me add the following comment when Tony also raised this question.
resctrl_rmid_realloc_threshold is a single global value,
and resctrl_arch_round_mon_val() takes no domain argument, so a
single scale has to be derived from the per-domain cmrc->up_scale.
max() was chosen because the rounding is a floor: a larger scale
yields a slightly lower threshold, i.e. an RMID has to drop to
a slightly lower occupancy before it is reused.

https://lore.kernel.org/all/3053f498-1eb8-4c64-8d52-847829f48a1b@intel.com/
 
> > +
> > +int erdt_get_max_rmid(void)
> > +{
> > +	return erdt_max_rmid;
> > +}
> > +
> > +static void __iomem *erdt_ioremap(phys_addr_t base, u32 num_pages, const char *desc)
> > +{
> > +	void __iomem *addr;
> > +	size_t size;
> > +
> > +	if (check_mul_overflow(num_pages, SZ_4K, &size))
> > +		return NULL;
> > +
> > +	addr = ioremap(base, size);
> 
> The types seem to target a function with prototype ioremap(phys_addr_t base, size_t size)
> but I find arch/x86/include/asm/io.h to declare:
> void __iomem *ioremap(resource_size_t offset, unsigned long size);
> 
> Since it is this code that determines the type it could just use matching accurate type
> from the beginning?
>

OK, let me switch it to unsigned long to be consistent with x86 declaration.
 
> > +	if (!addr)
> > +		pr_warn(FW_BUG "ERDT: Failed to map %s at phys addr %pa (size: %u pages)\n",
> > +		       desc, &base, num_pages);
> 
> Please align to open parenthesis. 
>

OK.
 
> > +static __init int cacd_init(struct acpi_subtbl_hdr_16 *subtbl,
> > +			    struct erdt_domain_info *domain_info)
> > +{
> > +	struct acpi_erdt_cacd *cacd = (struct acpi_erdt_cacd *)subtbl;
> > +	int num_ids, cpu;
> 
> Can num_ids ever be negative? If not, please use unsigned type.
>

It will not be negative, let me switch it to unsigned int.
 
> > +static __init bool parse_rmdd_table(struct acpi_subtbl_hdr_16 *rmdd_hdr)
> > +{
> > +	struct erdt_domain_info *domain_info;
> > +	struct acpi_subtbl_hdr_16 *subtbl;
> > +	struct acpi_erdt_rmdd *rmdd;
> > +	u32 subtbl_mask = 0;
> > +
> > +	if (rmdd_hdr->length < sizeof(*rmdd)) {
> > +		pr_warn(FW_BUG "Invalid RMDD length %u bytes\n", rmdd_hdr->length);
> > +		return false;
> > +	}
> > +
> > +	rmdd = (struct acpi_erdt_rmdd *)rmdd_hdr;
> 
> Could this initialization be done at time of declaration to be consistent with the other
> functions parsing tables? The length comparison could then use rmdd->header.length to
> match how this check is done in all the other places. Being consistent makes the
> code much easier to understand.
> 
>

OK, will modify the code.
 
> > +
> > +	/* Quietly ignore non-CPU-based L3 domains */
> > +	if (!(rmdd->flags & RMDD_FLAG_CPU_L3_DOMAIN))
> > +		return true;
> > +
> > +	domain_info = kzalloc_obj(*domain_info, GFP_KERNEL);
> > +	if (!domain_info)
> > +		return false;
> > +
> > +	domain_info->dom_id = -1;
> > +
> > +	domain_info->base[ERDT_MMIO_RMDD_CREG] =
> > +		erdt_ioremap(rmdd->creg_base, rmdd->creg_size, "RMDD ctrl base");
> > +	if (!domain_info->base[ERDT_MMIO_RMDD_CREG])
> > +		goto cleanup;
> > +
> > +	for (subtbl = rmdd_subtbl(rmdd);
> > +	     subtbl_valid((void *)rmdd + rmdd->header.length, subtbl);
> > +	     subtbl = next_subtbl(subtbl)) {
> 
> I find it curious how the implementation varies in how the tables are parsed. For example, here
> it uses a for () loop to cycle through the tables while enumerate_erdt_table() uses a while()
> loop for what appears to be the same flow. Are they actually different? Why are the two different
> patterns needed?
>

Let me switch them both to "for" loop to keep consistence.
 
> > +void erdt_exit(void)
> > +{
> > +	struct erdt_domain_info *d, *tmp;
> > +
> > +	list_for_each_entry_safe(d, tmp, &domain_info_list, entry) {
> > +		list_del(&d->entry);
> > +		cleanup_one_domain(d);
> > +	}
> > +	erdt_enabled = false;
> > +	valid_subtbl_mask = 0;
> > +	first_rmdd_domain_id = 0;
> 
> Should erdt_max_rmid be reset also?
>

Yes, let me fix this.
 
> > +
> > +	if (erdt->header.length < sizeof(*erdt)) {
> > +		pr_warn(FW_BUG "ERDT: Invalid table length %u bytes\n", erdt->header.length);
> > +		return -EINVAL;
> > +	}
> > +
> > +	subtbl = (void *)erdt + sizeof(struct acpi_table_erdt);
> 
> Please use sizeof(*erdt)
>

OK, will do.
 
> > +enum erdt_mmio_type {
> > +	ERDT_MMIO_RMDD_CREG,
> > +	ERDT_MMIO_LAST = ERDT_MMIO_RMDD_CREG
> > +};
> > +
> > +#define ERDT_MMIO_NUM_TYPES	(ERDT_MMIO_LAST + 1)
> > +
> > +/**
> > + * struct erdt_domain_info - Per-domain ERDT information
> > + * @base:	Array of ioremapped MMIO region base addresses, indexed by ERDT_MMIO_* type
> 
> I think "type" can be dropped? The enum is already implicitly an "MMIO type"?
>

Got it, will remove this "type".

thanks,
Chenyu 

  reply	other threads:[~2026-08-24  8:07 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-25  9:20 [PATCH v6 0/9] Introduce MMIO-based CMT access for Enhanced RDT Chen Yu
2026-07-25  9:22 ` [PATCH v6 1/9] x86/topology: Export topo_lookup_cpuid() for resctrl use Chen Yu
2026-08-19 22:55   ` Reinette Chatre
2026-08-22  4:16     ` Chen Yu
2026-07-25  9:22 ` [PATCH v6 2/9] x86/resctrl: Require 64-bit x86 for resctrl support Chen Yu
2026-08-19 22:55   ` Reinette Chatre
2026-08-20 15:20     ` Luck, Tony
2026-08-20 15:54       ` Reinette Chatre
2026-08-20 17:01         ` Luck, Tony
2026-08-20 17:12           ` Dave Hansen
2026-08-20 17:48             ` Reinette Chatre
2026-08-21  2:37               ` Borislav Petkov
2026-08-21 15:47                 ` Reinette Chatre
2026-08-21 15:54                   ` Borislav Petkov
2026-08-25 13:12                   ` Chen Yu
2026-08-24 14:18                     ` Dave Hansen
2026-08-24 15:15                       ` Chen, Yu C
2026-08-21 11:28             ` Peter Zijlstra
2026-08-21 15:52               ` Borislav Petkov
2026-08-21 16:58                 ` Luck, Tony
2026-08-22  0:04                   ` Borislav Petkov
2026-07-25  9:22 ` [PATCH v6 3/9] x86/resctrl: Parse ACPI ERDT table and save CACD cpumask for RMDD domains Chen Yu
2026-08-19 23:01   ` Reinette Chatre
2026-08-25  8:06     ` Chen Yu [this message]
2026-08-24 15:54       ` Reinette Chatre
2026-07-25  9:23 ` [PATCH v6 4/9] x86/resctrl: Attach ACPI ERDT information to L3 mon domain on CPU online Chen Yu
2026-08-19 23:04   ` Reinette Chatre
2026-07-25  9:23 ` [PATCH v6 5/9] x86/resctrl: Parse ACPI CMRC table Chen Yu
2026-08-19 23:06   ` Reinette Chatre
2026-07-25  9:23 ` [PATCH v6 6/9] x86/resctrl: Refactor the monitor read function Chen Yu
2026-08-19 23:07   ` Reinette Chatre
2026-07-25  9:23 ` [PATCH v6 7/9] fs/resctrl: Do not invoke smp_processor_id() in preemptible context Chen Yu
2026-08-19 23:08   ` Reinette Chatre
2026-07-25  9:23 ` [PATCH v6 8/9] x86/resctrl: Introduce erdt_cpu_has() and erdt_support() Chen Yu
2026-08-19 23:08   ` Reinette Chatre
2026-07-25  9:23 ` [PATCH v6 9/9] x86/resctrl: Add MMIO-based LLC occupancy monitoring support Chen Yu
2026-08-19 23:10   ` Reinette Chatre
2026-08-13  6:43 ` [PATCH v6 0/9] Introduce MMIO-based CMT access for Enhanced RDT Chen Yu

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=ao1NEdfiUt5OYMQ0@three-body \
    --to=chen.yu@linux.dev \
    --cc=babu.moger@amd.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=fenghuay@nvidia.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=reinette.chatre@intel.com \
    --cc=tglx@kernel.org \
    --cc=tony.luck@intel.com \
    --cc=x86@kernel.org \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.