[PATCH v4 2/4] arm64: cpufeature: Modify address authentication cpufeature to exact

Suzuki K Poulose suzuki.poulose at arm.com
Wed Jul 29 13:09:39 EDT 2020


On 07/29/2020 03:31 PM, Dave Martin wrote:
> On Wed, Jul 29, 2020 at 01:28:06PM +0100, Suzuki K Poulose wrote:
>> On 07/29/2020 11:36 AM, Dave Martin wrote:
>>> On Fri, Jul 10, 2020 at 01:30:08PM +0530, Amit Daniel Kachhap wrote:
>>>> The current address authentication cpufeature levels are set as LOWER_SAFE
>>>> which is not compatible with the different configurations added for Armv8.3
>>>> ptrauth enhancements as the different levels have different behaviour and
>>>> there is no tunable to enable the lower safe versions. This is rectified
>>>> by setting those cpufeature type as EXACT.
>>>>
>>>> The current cpufeature framework also does not interfere in the booting of
>>>> non-exact secondary cpus but rather marks them as tainted. As a workaround
>>>> this is fixed by replacing the generic match handler with a new handler
>>>> specific to ptrauth.
>>>>
>>>> After this change, if there is any variation in ptrauth configurations in
>>>> secondary cpus from boot cpu then those mismatched cpus are parked in an
>>>> infinite loop.
>>>>
>>>> Signed-off-by: Amit Daniel Kachhap <amit.kachhap at arm.com>
>>>> [Suzuki: Introduce new matching function for address authentication]
>>>> Suggested-by: Suzuki K Poulose <suzuki.poulose at arm.com>
>>>> ---
>>>> Changes since v3:
>>>>   * Commit logs cleanup.
>>>>
>>>>   arch/arm64/kernel/cpufeature.c | 56 ++++++++++++++++++++++++++++------
>>>>   1 file changed, 47 insertions(+), 9 deletions(-)
>>>>
>>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>>> index 9fae0efc80c1..8ac8c18f70c9 100644
>>>> --- a/arch/arm64/kernel/cpufeature.c
>>>> +++ b/arch/arm64/kernel/cpufeature.c
>>>> @@ -210,9 +210,9 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
>>>>   	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_FCMA_SHIFT, 4, 0),
>>>>   	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_JSCVT_SHIFT, 4, 0),
>>>>   	ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
>>>> -		       FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_API_SHIFT, 4, 0),
>>>> +		       FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_API_SHIFT, 4, 0),
>>>>   	ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
>>>> -		       FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_APA_SHIFT, 4, 0),
>>>> +		       FTR_STRICT, FTR_EXACT, ID_AA64ISAR1_APA_SHIFT, 4, 0),
>>>>   	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64ISAR1_DPB_SHIFT, 4, 0),
>>>>   	ARM64_FTR_END,
>>>>   };
>>>> @@ -1605,11 +1605,49 @@ static void cpu_clear_disr(const struct arm64_cpu_capabilities *__unused)
>>>>   #endif /* CONFIG_ARM64_RAS_EXTN */
>>>>   #ifdef CONFIG_ARM64_PTR_AUTH
>>>> -static bool has_address_auth(const struct arm64_cpu_capabilities *entry,
>>>> -			     int __unused)
>>>> +static bool has_address_auth_cpucap(const struct arm64_cpu_capabilities *entry, int scope)
>>>>   {
>>>> -	return __system_matches_cap(ARM64_HAS_ADDRESS_AUTH_ARCH) ||
>>>> -	       __system_matches_cap(ARM64_HAS_ADDRESS_AUTH_IMP_DEF);
>>>> +	int local_cpu_auth;
>>>> +	static int boot_cpu_auth_arch;
>>>> +	static int boot_cpu_auth_imp_def;
>>>
>>> I guess having static variables here is probably safe, provided that
>>> calls to this function are strictly serialised with sufficiently
>>> heavyweight synchronisation.
>>>
>>
>> These are initialised with the primary boot CPU. And later on called
>> from CPU bring up. So they are serialized, except when
>> this_cpu_has_cap() could be called. But this is fine, as it is a read
>> operation.
> 
> To guarantee that any update to those variables is visible to a booting
> CPU, we'd probably need a DSB and/or DMB somewhere.  For now I don't see
> anything explicity, though it's likely we're getting them as a side
> effect of something else.
> 
> In any case, I guess we've been managing for some time without this
> being strictly correct.
> 

That is a good point. In fact we need this for init_cpu_features() and 
update_cpu_features() too.


> 
>>> Might be worth a comment.
>>>
>>> Coming up with a cleaner approach using locks or atomics might be
>>> overkill, but other folks might take a stronger view on this.
>>>
>>>> +
>>>> +	/* We don't expect to be called with SCOPE_SYSTEM */
>>>> +	WARN_ON(scope == SCOPE_SYSTEM);
>>>> +
>>>> +	local_cpu_auth = cpuid_feature_extract_field(__read_sysreg_by_encoding(entry->sys_reg),
>>>> +						     entry->field_pos, entry->sign);
>>>> +	/*
>>>> +	 * The ptr-auth feature levels are not intercompatible with
>>>> +	 * lower levels. Hence we must match all the CPUs with that
>>>> +	 * of the boot CPU. So cache the level of boot CPU and compare
>>>> +	 * it against the secondary CPUs.
>>>> +	 */
>>>> +	if (scope & SCOPE_BOOT_CPU) {
>>>> +		if (entry->capability == ARM64_HAS_ADDRESS_AUTH_IMP_DEF) {
>>>> +			boot_cpu_auth_imp_def = local_cpu_auth;
> 
> Actually, can we make use of read_sanitised_ftr_reg() here rather than
> having to cache the values in static variables?

Thats actually a good idea ! However the only catch is if there is a
case where the values become compatible. e.g, APA >= 3 are all
compatible, in which case the sanitised value would indicate 0.
If we decide not support such cases, then we could go ahead with  the
sanitised_ftr value.

Suzuki



More information about the linux-arm-kernel mailing list