From: Andrew Murray andrew.murray@arm.com
mainline inclusion from v5.2-rc1 commit aec0bff757c9 category: feature bugzilla: 30110 CVE: NA
-------------------------------------------------
The introduction of AT_HWCAP2 introduced accessors which ensure that hwcap features are set and tested appropriately.
Let's now mandate access to elf_hwcap via these accessors by making elf_hwcap static within cpufeature.c.
conflict: arch/arm64/include/asm/cpufeature.h arch/arm64/include/asm/hwcap.h arch/arm64/kernel/cpufeature.c
Signed-off-by: Andrew Murray andrew.murray@arm.com Reviewed-by: Dave Martin Dave.Martin@arm.com Reviewed-by: Suzuki K Poulose suzuki.poulose@arm.com Signed-off-by: Will Deacon will.deacon@arm.com Signed-off-by: Hongbo Yao yaohongbo@huawei.com Signed-off-by: Wang Wensheng wangwensheng4@huawei.com Reviewed-by: Xie XiuQi xiexiuqi@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- arch/arm64/include/asm/cpufeature.h | 15 ++++--------- arch/arm64/include/asm/hwcap.h | 7 +++--- arch/arm64/kernel/cpufeature.c | 33 +++++++++++++++++++++++++++-- 3 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index b726966f1bcc..2eed935f0a02 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -400,19 +400,12 @@ extern DECLARE_BITMAP(boot_capabilities, ARM64_NPATCHABLE); for_each_set_bit(cap, cpu_hwcaps, ARM64_NCAPS)
bool this_cpu_has_cap(unsigned int cap); +void cpu_set_feature(unsigned int num); +bool cpu_have_feature(unsigned int num); +unsigned long cpu_get_elf_hwcap(void); +unsigned long cpu_get_elf_hwcap2(void);
-static inline void cpu_set_feature(unsigned int num) -{ - WARN_ON(num >= MAX_CPU_FEATURES); - elf_hwcap |= BIT(num); -} #define cpu_set_named_feature(name) cpu_set_feature(cpu_feature(name)) - -static inline bool cpu_have_feature(unsigned int num) -{ - WARN_ON(num >= MAX_CPU_FEATURES); - return elf_hwcap & BIT(num); -} #define cpu_have_named_feature(name) cpu_have_feature(cpu_feature(name))
/* System capability check for constant caps */ diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h index af868cbe96f8..a843b6efce5b 100644 --- a/arch/arm64/include/asm/hwcap.h +++ b/arch/arm64/include/asm/hwcap.h @@ -17,6 +17,7 @@ #define __ASM_HWCAP_H
#include <uapi/asm/hwcap.h> +#include <asm/cpufeature.h>
#define COMPAT_HWCAP_HALF (1 << 1) #define COMPAT_HWCAP_THUMB (1 << 2) @@ -40,7 +41,6 @@ #define COMPAT_HWCAP2_CRC32 (1 << 4)
#ifndef __ASSEMBLY__ -#include <linux/kernel.h> #include <linux/log2.h>
/* @@ -93,8 +93,8 @@ * This yields a mask that user programs can use to figure out what * instruction set this cpu supports. */ -#define ELF_HWCAP lower_32_bits(elf_hwcap) -#define ELF_HWCAP2 upper_32_bits(elf_hwcap) +#define ELF_HWCAP cpu_get_elf_hwcap() +#define ELF_HWCAP2 cpu_get_elf_hwcap2()
#ifdef CONFIG_COMPAT #define COMPAT_ELF_HWCAP (compat_elf_hwcap) @@ -110,6 +110,5 @@ enum { #endif };
-extern unsigned long elf_hwcap; #endif #endif diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index a9c76ca87047..fc2c18f903e2 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -36,8 +36,8 @@ #include <asm/traps.h> #include <asm/virt.h>
-unsigned long elf_hwcap __read_mostly; -EXPORT_SYMBOL_GPL(elf_hwcap); +/* Kernel representation of AT_HWCAP and AT_HWCAP2 */ +static unsigned long elf_hwcap __read_mostly;
#ifdef CONFIG_COMPAT #define COMPAT_ELF_HWCAP_DEFAULT \ @@ -2161,6 +2161,35 @@ bool this_cpu_has_cap(unsigned int n) return false; }
+void cpu_set_feature(unsigned int num) +{ + WARN_ON(num >= MAX_CPU_FEATURES); + elf_hwcap |= BIT(num); +} +EXPORT_SYMBOL_GPL(cpu_set_feature); + +bool cpu_have_feature(unsigned int num) +{ + WARN_ON(num >= MAX_CPU_FEATURES); + return elf_hwcap & BIT(num); +} +EXPORT_SYMBOL_GPL(cpu_have_feature); + +unsigned long cpu_get_elf_hwcap(void) +{ + /* + * We currently only populate the first 32 bits of AT_HWCAP. Please + * note that for userspace compatibility we guarantee that bits 62 + * and 63 will always be returned as 0. + */ + return lower_32_bits(elf_hwcap); +} + +unsigned long cpu_get_elf_hwcap2(void) +{ + return upper_32_bits(elf_hwcap); +} + /* * This helper function is used in a narrow window when, * - The system wide safe registers are set with all the SMP CPUs and,