[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