[PATCH v5 2/3] arm64/cpufeature: Store elf_hwcaps as a bitmap rather than unsigned long

Catalin Marinas catalin.marinas at arm.com
Thu Jul 7 04:37:58 PDT 2022


On Thu, Jul 07, 2022 at 11:36:31AM +0100, Mark Brown wrote:
> When we added support for AT_HWCAP2 we took advantage of the fact that we
> have limited hwcaps to the low 32 bits and stored it along with AT_HWCAP
> in a single unsigned integer. Thanks to the ever expanding capabilities of
> the architecture we have now allocated all 64 of the bits in an unsigned
> long so in preparation for adding more hwcaps convert elf_hwcap to be a
> bitmap instead, with 64 bits allocated to each AT_HWCAP.
> 
> There should be no functional change from this patch.
> 
> Signed-off-by: Mark Brown <broonie at kernel.org>
> ---
>  arch/arm64/include/asm/cpufeature.h |  2 +-
>  arch/arm64/include/asm/hwcap.h      |  2 +-
>  arch/arm64/kernel/cpufeature.c      | 12 +++++-------
>  3 files changed, 7 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
> index 14a8f3d93add..7abd6c0fa53d 100644
> --- a/arch/arm64/include/asm/cpufeature.h
> +++ b/arch/arm64/include/asm/cpufeature.h
> @@ -11,7 +11,7 @@
>  #include <asm/hwcap.h>
>  #include <asm/sysreg.h>
>  
> -#define MAX_CPU_FEATURES	64
> +#define MAX_CPU_FEATURES	128

Should this be (32 + 64)? I guess it's easier as you did since we have
128 bits in total, only that we reserved the top 32 in ELF_HWCAP.

>  #define cpu_feature(x)		KERNEL_HWCAP_ ## x
>  
>  #ifndef __ASSEMBLY__
> diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
> index aa443d8f8cfb..9b5fdc114f8c 100644
> --- a/arch/arm64/include/asm/hwcap.h
> +++ b/arch/arm64/include/asm/hwcap.h
> @@ -85,7 +85,7 @@
>  #define KERNEL_HWCAP_PACA		__khwcap_feature(PACA)
>  #define KERNEL_HWCAP_PACG		__khwcap_feature(PACG)
>  
> -#define __khwcap2_feature(x)		(const_ilog2(HWCAP2_ ## x) + 32)
> +#define __khwcap2_feature(x)		(const_ilog2(HWCAP2_ ## x) + 64)
>  #define KERNEL_HWCAP_DCPODP		__khwcap2_feature(DCPODP)
>  #define KERNEL_HWCAP_SVE2		__khwcap2_feature(SVE2)
>  #define KERNEL_HWCAP_SVEAES		__khwcap2_feature(SVEAES)
> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> index 8d88433de81d..5ba226f3721c 100644
> --- a/arch/arm64/kernel/cpufeature.c
> +++ b/arch/arm64/kernel/cpufeature.c
> @@ -91,7 +91,7 @@
>  #include <asm/virt.h>
>  
>  /* Kernel representation of AT_HWCAP and AT_HWCAP2 */
> -static unsigned long elf_hwcap __read_mostly;
> +static DECLARE_BITMAP(elf_hwcap, MAX_CPU_FEATURES) __read_mostly;
>  
>  #ifdef CONFIG_COMPAT
>  #define COMPAT_ELF_HWCAP_DEFAULT	\
> @@ -3098,14 +3098,12 @@ static bool __maybe_unused __system_matches_cap(unsigned int n)
>  
>  void cpu_set_feature(unsigned int num)
>  {
> -	WARN_ON(num >= MAX_CPU_FEATURES);
> -	elf_hwcap |= BIT(num);
> +	set_bit(num, elf_hwcap);
>  }
>  
>  bool cpu_have_feature(unsigned int num)
>  {
> -	WARN_ON(num >= MAX_CPU_FEATURES);
> -	return elf_hwcap & BIT(num);
> +	return test_bit(num, elf_hwcap);
>  }
>  EXPORT_SYMBOL_GPL(cpu_have_feature);
>  
> @@ -3116,12 +3114,12 @@ unsigned long cpu_get_elf_hwcap(void)
>  	 * note that for userspace compatibility we guarantee that bits 62
>  	 * and 63 will always be returned as 0.
>  	 */
> -	return lower_32_bits(elf_hwcap);
> +	return elf_hwcap[0];
>  }
>  
>  unsigned long cpu_get_elf_hwcap2(void)
>  {
> -	return upper_32_bits(elf_hwcap);
> +	return elf_hwcap[1];
>  }

This is fine on the assumption that DECLARE_BITMAP is always an array of
longs. I couldn't see any documentation on this but at least the
set_bit() etc. API only works on 'long *' pointers.

Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>



More information about the linux-arm-kernel mailing list