Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Pierre Gondois <pierre.gondois@arm.com>
To: Radu Rendec <rrendec@redhat.com>, Sudeep Holla <sudeep.holla@arm.com>
Cc: linux-arm-kernel@lists.infradead.org,
	Adrien Thierry <athierry@redhat.com>,
	Eric Chanudet <echanude@redhat.com>
Subject: Re: [RFC PATCH] arch_topology: Pre-allocate cacheinfo from primary CPU
Date: Fri, 31 Mar 2023 16:49:58 +0200	[thread overview]
Message-ID: <8df69f86-b669-549a-cf04-40a4c2376c68@arm.com> (raw)
In-Reply-To: <334926dc894523f302b09e19138fb9fa7a142f8e.camel@redhat.com>

Hello Radu,

On 3/31/23 01:32, Radu Rendec wrote:
> On Thu, 2023-03-30 at 08:57 +0200, Pierre Gondois wrote:
>> On 3/29/23 23:35, Radu Rendec wrote:
>>> On Wed, 2023-03-29 at 17:39 +0200, Pierre Gondois wrote:
>>>> On 3/29/23 17:03, Sudeep Holla wrote:
>>>>> On Wed, Mar 29, 2023 at 04:42:07PM +0200, Pierre Gondois wrote:
>>>>>>
>>>>>> This would mean that for all architectures, the cacheinfo would come from
>>>>>> ACPI/DT first.....
>>>>>
>>>>> x86 doesn't fall into the above category. So we need to ensure it continues
>>>>> to work with no errors.
>>>>
>>>> Ok, then maybe having a second arch specific function like
>>>> init_cache_level() would work.
>>>>
>>>> This function would be called in fetch_cache_info() after
>>>> init_of_cache_level()/acpi_get_cache_info() fail. It would fetch
>>>> cache info anywhere but in DT/ACPI.
>>>> Archs that don't want it would not implement it, and it would
>>>> allow the others to get the num_leaves/levels during early boot.
>>>
>>> In particular, for arm64 is it possible that CLIDR_EL1 may not look the
>>> same depending on the CPU that reads it? What about SoC's with
>>> asymmetrical CPU cores? (no concrete example here, just assuming this
>>> is a real/possible thing)
>>
>> This would indeed be an issue if all the CPUs don't have the same number/level
>> of caches. In case there is no DT/ACPI, it should be possible to:
>> - from the primary CPU using CLIDR_EL1, allocate the cacheinfo (making the
>>     assumption the platform is symmetrical)
>> - from the secondary CPUs, if we know a pre-allocation has been made,
>>     run init_cache_level() and check the pre-allocation was correct.
>>     If not, re-allocate the cacheinfo (and trigger a warning).
> 
> That makes sense. The question here is how do we know a pre-allocation
> has been made? If we modified fetch_cache_info() the way you proposed,
> then we would always pre-allocate memory, and using the pointer alone
> it would be impossible to tell if the pre-allocation is based on a
> "guessed" size.
> 
> Also I'm not sure about the "trigger a warning" part. If it's an RT
> kernel, it will try to reallocate and that will be a "bug" splat
> anyway. If not, the reallocation will fix the issue automatically.
> Maybe a pr_warn() as opposed to a WARN_ON() (or perhaps that's what you
> had in mind as well).

Sorry I misformulated, I just wanted to say the "BUG: sleeping function
called from invalid context" splat would be triggered.

> 
>> I think this is more or less what was done in the RFC, the only difference
>> being there is no call from smp_prepare_cpus(), or did I miss something ?
> 
> Yes, it's more or less the same thing. The main differences are:
>   * There is no window when the information in struct cpu_cacheinfo (the
>     number of cache levels and leaves) is populated but potentially
>     inaccurate (e.g. in the case of asymmetric CPUs with no DT/ACPI).

In the current code, fetch_cache_info() allocates the memory and populates
num_levels/num_leaves from the primary CPU. The information is populated
later from the secondary CPUs. So there is already a time window when
the information is inaccurate.

>   * The logic in detect_cache_attributes() remains unchanged because the
>     allocated memory is "published" to ci_cpu_cacheinfo only if the size
>     is known to be correct (i.e. it comes from DT/ACPI).

Yes right.

> 
> Based on what you proposed, I hacked away at the code and came up with
> the patch below. It works in my particular test case because the CPUs
> are symmetrical, but doesn't solve the reallocation part.
> 
> I can't think of an elegant way to solve this. One thing that comes to
> mind is change the logic in detect_cache_attributes(). But I am
> reluctant because this code is architecture independent, while the
> "guess first/fix later" strategy is implementation specific (arm64 in
> our case). The main problem is that the call to init_cache_level() is
> skipped altogether if there is a valid pointer value in
> ci_cpu_cacheinfo. In other words, if the memory has been already
> allocated, it is assumed to be correct. This is why I used a separate
> per-cpu variable in my original RFC patch.
> 
> Would it be horrible to add a bool field to struct cpu_cacheinfo that
> tells us if the levels/leaves are based on early detection? The field
> would be set by fetch_cache_info() when it calls early_cache_level() as
> fallback. Then detect_cache_attributes() could avoid skipping the call
> to init_cache_level() when the flag is set. The nice thing about this
> is that it doesn't affect other architectures - if they don't implement
> early_cache_level(), the flag is never set and then the behavior of
> detect_cache_attributes() is basically unchanged.

FWIW I prefer the solution with the bool/flag over the per-cpu variable.
At:
https://lore.kernel.org/all/20230327115953.788244-4-pierre.gondois@arm.com/
I suggested to add a 'bool use_arch_info;' and nobody seemed to complain
about it (so far). I assume the field could be re-used for this purpose.

> 
> Best regards,
> Radu
> 
>  From a79542d43a0ece06e13bfd431abc98299a9747f2 Mon Sep 17 00:00:00 2001
> From: Radu Rendec <rrendec@redhat.com>
> Date: Thu, 30 Mar 2023 18:18:46 -0400
> Subject: [PATCH] Allocate cacheinfo early - WIP #1
> 
> Signed-off-by: Radu Rendec <rrendec@redhat.com>
> ---
>   arch/arm64/kernel/cacheinfo.c | 22 ++++++++++++++++++++++
>   drivers/base/cacheinfo.c | 12 ++++++++++--
>   include/linux/cacheinfo.h | 1 +
>   3 files changed, 33 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c
> index c307f69e9b55..6f5ac5c385f0 100644
> --- a/arch/arm64/kernel/cacheinfo.c
> +++ b/arch/arm64/kernel/cacheinfo.c
> @@ -38,6 +38,27 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
>   this_leaf->type = type;
>   }
> +int early_cache_level(unsigned int cpu)
> +{
> + unsigned int ctype, level, leaves;
> + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
> +
> + for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {
> + ctype = get_cache_type(level);
> + if (ctype == CACHE_TYPE_NOCACHE) {
> + level--;
> + break;
> + }
> + /* Separate instruction and data caches */
> + leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1;
> + }
> +
> + this_cpu_ci->num_levels = level;
> + this_cpu_ci->num_leaves = leaves;
> + return 0;
> +}
> +
> +#if 0
>   int init_cache_level(unsigned int cpu)
>   {
>   unsigned int ctype, level, leaves;
> @@ -76,6 +97,7 @@ int init_cache_level(unsigned int cpu)
>   this_cpu_ci->num_leaves = leaves;
>   return 0;
>   }
> +#endif
>   int populate_cache_leaves(unsigned int cpu)
>   {
> diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
> index f6573c335f4c..4640671b4547 100644
> --- a/drivers/base/cacheinfo.c
> +++ b/drivers/base/cacheinfo.c
> @@ -398,6 +398,11 @@ static void free_cache_attributes(unsigned int cpu)
>   cache_shared_cpu_map_remove(cpu);
>   }
> +int __weak early_cache_level(unsigned int cpu)
> +{
> + return -ENOENT;
> +}
> +
>   int __weak init_cache_level(unsigned int cpu)
>   {
>   return -ENOENT;
> @@ -446,8 +451,11 @@ int fetch_cache_info(unsigned int cpu)
>   */
>   this_cpu_ci->num_leaves = levels + split_levels;
>   }
> - if (!cache_leaves(cpu))
> - return -ENOENT;
> + if (!cache_leaves(cpu)) {
> + ret = early_cache_level(cpu);
> + if (ret < 0)
> + return ret;
> + }

If there are no PPTT, acpi_get_cache_info() should return an error code.
The patch-set at:
https://lore.kernel.org/all/20230327115953.788244-1-pierre.gondois@arm.com/
should make init_of_cache_level() return error code aswell.

I think these error codes should be caught instead of checking:
+ if (!cache_leaves(cpu))

>   return allocate_cache_info(cpu);
>   }
> diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
> index 908e19d17f49..9788100a7d3c 100644
> --- a/include/linux/cacheinfo.h
> +++ b/include/linux/cacheinfo.h
> @@ -79,6 +79,7 @@ struct cpu_cacheinfo {
>   };
>   struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu);
> +int early_cache_level(unsigned int cpu);
>   int init_cache_level(unsigned int cpu);
>   int init_of_cache_level(unsigned int cpu);
>   int populate_cache_leaves(unsigned int cpu);

Regards,
Pierre

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  reply	other threads:[~2023-03-31 14:51 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-03-23 22:42 [RFC PATCH] arch_topology: Pre-allocate cacheinfo from primary CPU Radu Rendec
2023-03-27 12:02 ` Pierre Gondois
2023-03-27 14:23   ` Radu Rendec
2023-03-29 14:42     ` Pierre Gondois
2023-03-29 15:03       ` Sudeep Holla
2023-03-29 15:39         ` Pierre Gondois
2023-03-29 21:35           ` Radu Rendec
2023-03-30  6:57             ` Pierre Gondois
2023-03-30 23:32               ` Radu Rendec
2023-03-31 14:49                 ` Pierre Gondois [this message]
2023-04-03 21:25                   ` Radu Rendec

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=8df69f86-b669-549a-cf04-40a4c2376c68@arm.com \
    --to=pierre.gondois@arm.com \
    --cc=athierry@redhat.com \
    --cc=echanude@redhat.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=rrendec@redhat.com \
    --cc=sudeep.holla@arm.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