| From 7559950aef1ab8792c50797c6c5c7c5150a02460 Mon Sep 17 00:00:00 2001 |
| From: Suzuki K Poulose <suzuki.poulose@arm.com> |
| Date: Mon, 13 Jan 2020 23:30:20 +0000 |
| Subject: arm64: cpufeature: Set the FP/SIMD compat HWCAP bits properly |
| |
| From: Suzuki K Poulose <suzuki.poulose@arm.com> |
| |
| commit 7559950aef1ab8792c50797c6c5c7c5150a02460 upstream. |
| |
| We set the compat_elf_hwcap bits unconditionally on arm64 to |
| include the VFP and NEON support. However, the FP/SIMD unit |
| is optional on Arm v8 and thus could be missing. We already |
| handle this properly in the kernel, but still advertise to |
| the COMPAT applications that the VFP is available. Fix this |
| to make sure we only advertise when we really have them. |
| |
| Fixes: 82e0191a1aa11abf ("arm64: Support systems without FP/ASIMD") |
| Cc: Will Deacon <will@kernel.org> |
| Cc: Mark Rutland <mark.rutland@arm.com> |
| Reviewed-by: Ard Biesheuvel <ardb@kernel.org> |
| Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> |
| Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> |
| Signed-off-by: Will Deacon <will@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/arm64/kernel/cpufeature.c | 37 ++++++++++++++++++++++++++++++++++--- |
| 1 file changed, 34 insertions(+), 3 deletions(-) |
| |
| --- a/arch/arm64/kernel/cpufeature.c |
| +++ b/arch/arm64/kernel/cpufeature.c |
| @@ -32,9 +32,7 @@ static unsigned long elf_hwcap __read_mo |
| #define COMPAT_ELF_HWCAP_DEFAULT \ |
| (COMPAT_HWCAP_HALF|COMPAT_HWCAP_THUMB|\ |
| COMPAT_HWCAP_FAST_MULT|COMPAT_HWCAP_EDSP|\ |
| - COMPAT_HWCAP_TLS|COMPAT_HWCAP_VFP|\ |
| - COMPAT_HWCAP_VFPv3|COMPAT_HWCAP_VFPv4|\ |
| - COMPAT_HWCAP_NEON|COMPAT_HWCAP_IDIV|\ |
| + COMPAT_HWCAP_TLS|COMPAT_HWCAP_IDIV|\ |
| COMPAT_HWCAP_LPAE) |
| unsigned int compat_elf_hwcap __read_mostly = COMPAT_ELF_HWCAP_DEFAULT; |
| unsigned int compat_elf_hwcap2 __read_mostly; |
| @@ -1595,6 +1593,12 @@ static const struct arm64_cpu_capabiliti |
| .match_list = list, \ |
| } |
| |
| +#define HWCAP_CAP_MATCH(match, cap_type, cap) \ |
| + { \ |
| + __HWCAP_CAP(#cap, cap_type, cap) \ |
| + .matches = match, \ |
| + } |
| + |
| #ifdef CONFIG_ARM64_PTR_AUTH |
| static const struct arm64_cpu_capabilities ptr_auth_hwcap_addr_matches[] = { |
| { |
| @@ -1668,8 +1672,35 @@ static const struct arm64_cpu_capabiliti |
| {}, |
| }; |
| |
| +#ifdef CONFIG_COMPAT |
| +static bool compat_has_neon(const struct arm64_cpu_capabilities *cap, int scope) |
| +{ |
| + /* |
| + * Check that all of MVFR1_EL1.{SIMDSP, SIMDInt, SIMDLS} are available, |
| + * in line with that of arm32 as in vfp_init(). We make sure that the |
| + * check is future proof, by making sure value is non-zero. |
| + */ |
| + u32 mvfr1; |
| + |
| + WARN_ON(scope == SCOPE_LOCAL_CPU && preemptible()); |
| + if (scope == SCOPE_SYSTEM) |
| + mvfr1 = read_sanitised_ftr_reg(SYS_MVFR1_EL1); |
| + else |
| + mvfr1 = read_sysreg_s(SYS_MVFR1_EL1); |
| + |
| + return cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDSP_SHIFT) && |
| + cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDINT_SHIFT) && |
| + cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDLS_SHIFT); |
| +} |
| +#endif |
| + |
| static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = { |
| #ifdef CONFIG_COMPAT |
| + HWCAP_CAP_MATCH(compat_has_neon, CAP_COMPAT_HWCAP, COMPAT_HWCAP_NEON), |
| + HWCAP_CAP(SYS_MVFR1_EL1, MVFR1_SIMDFMAC_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv4), |
| + /* Arm v8 mandates MVFR0.FPDP == {0, 2}. So, piggy back on this for the presence of VFP support */ |
| + HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFP), |
| + HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv3), |
| HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL), |
| HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES), |
| HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1), |