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

Suzuki K Poulose suzuki.poulose at arm.com
Tue Nov 10 07:14:41 EST 2020


On 11/10/20 12:05 PM, Catalin Marinas wrote:
> 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]);

True, I think this would do the trick, provided proper testing is
performed ;-). The issue is, we would advertise the "errata work around" 
(in dmesg) and may not really apply it where it matters. So, if the
testing doesn't really verify this, but instead looks for the message,
then we are back to the problem the original patch was trying to solve.

Cheers
Suzuki



More information about the linux-arm-kernel mailing list