[PATCH] arm64: errata: Fix handling of 1418040 with late CPU onlining

Catalin Marinas catalin.marinas at arm.com
Tue Nov 10 07:05:20 EST 2020


On Tue, Nov 10, 2020 at 10:39:57AM +0000, Suzuki K Poulose wrote:
> Catalin
> 
> On Fri, Nov 06, 2020 at 12:44:00PM +0000, Catalin Marinas wrote:
> > On Fri, Nov 06, 2020 at 12:18:32PM +0000, Suzuki K Poulose wrote:
> > > On 11/6/20 11:49 AM, Will Deacon wrote:
> > +/*
> > + * Test for a capability with a runtime check. This is an alias for
> > + * cpus_have_cap() but with the name chosen to emphasize the applicability to
> > + * late capability setting.
> > + */
> > +static __always_inline bool cpus_have_late_cap(int num)
> > +{
> > +	return cpus_have_cap(num);
> > +}
> > +
> 
> It is quite easy for people to misuse the ubiquitous cpus_have_const_cap().
> So, unless we make sure that we fix that to handle these "caps" we might
> see subtle bugs. How about the following fix on top of your patch, to
> add another (sigh!) set of keys to detect if we can use the const caps
> or not.

I thought about this as well but decided it's not worth the additional
code.

> Untested...
> 
> ---8>---
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 849b2691fadd..84dd43f1f322 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -379,6 +379,7 @@ cpucap_multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry,
>  
>  extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
>  extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
> +extern struct static_key_false cpu_hwcap_const_key[ARM64_NCAPS];
>  extern struct static_key_false arm64_const_caps_ready;
>  
>  /* ARM64 CAPS + alternative_cb */
> @@ -414,6 +415,14 @@ static inline bool cpus_have_cap(unsigned int num)
>  	return test_bit(num, cpu_hwcaps);
>  }
>  
> +static __always_inline bool cpucap_has_const_key(int num)
> +{
> +	if (num >= ARM64_NCAPS)
> +		return false;
> +
> +	return static_branch_unlikely(&cpu_hwcap_const_key[num]);
> +}
> +
>  /*
>   * Test for a capability without a runtime check.
>   *
> @@ -424,7 +433,7 @@ static inline bool cpus_have_cap(unsigned int num)
>   */
>  static __always_inline bool __cpus_have_const_cap(int num)
>  {
> -	if (num >= ARM64_NCAPS)
> +	if (num >= ARM64_NCAPS && WARN_ON(!cpucap_has_const_key(num)))
>  		return false;
>  	return static_branch_unlikely(&cpu_hwcap_keys[num]);
>  }
> @@ -439,7 +448,7 @@ static __always_inline bool __cpus_have_const_cap(int num)
>   */
>  static __always_inline bool cpus_have_const_cap(int num)
>  {
> -	if (system_capabilities_finalized())
> +	if (cpucap_has_const_key(num) && system_capabilities_finalized())
>  		return __cpus_have_const_cap(num);
>  	else
>  		return cpus_have_cap(num);

I don't particularly like that we end up with three static key checks
here but, OTOH, this has the advantage that we don't need a new
cpus_have_late_cap().

Going back to the original problem, we want to allow late cpucap setting
after the system caps have been finalised and, in a addition, we want to
detect API misuse. We solve the former by setting the corresponding
cpu_hwcaps bit late, based on a new capability flag.

For the API, we can use your approach with another static key and that's
pretty foolproof, it gives us warnings. Alternatively (not as
foolproof), we could skip the static key initialisation entirely for a
late feature even if we detect it early and that would allow one to
(hopefully) figure out the wrong API (cpus_have_const_cap() never true):

diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index e346938e9a37..531b7787ee8e 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -2436,7 +2436,8 @@ static void __init enable_cpu_capabilities(u16 scope_mask)
 			continue;
 
 		/* Ensure cpus_have_const_cap(num) works */
-		static_branch_enable(&cpu_hwcap_keys[num]);
+		if (!cpucap_set_for_late_cpu(caps))
+			static_branch_enable(&cpu_hwcap_keys[num]);
 
 		if (boot_scope && caps->cpu_enable)
 			/*

Anyway, either option is fine by me.

-- 
Catalin



More information about the linux-arm-kernel mailing list