Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64/sve: Detect SVE and activate runtime support

This patch enables detection of hardware SVE support via the
cpufeatures framework, and reports its presence to the kernel and
userspace via the new ARM64_SVE cpucap and HWCAP_SVE hwcap
respectively.

Userspace can also detect SVE using ID_AA64PFR0_EL1, using the
cpufeatures MRS emulation.

When running on hardware that supports SVE, this enables runtime
kernel support for SVE, and allows user tasks to execute SVE
instructions and make of the of the SVE-specific user/kernel
interface extensions implemented by this series.

Signed-off-by: Dave Martin <Dave.Martin@arm.com>
Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>

authored by

Dave Martin and committed by
Will Deacon
43994d82 07d79fe7

+36 -6
+5 -1
Documentation/arm64/cpu-feature-registers.txt
··· 142 142 x--------------------------------------------------x 143 143 | Name | bits | visible | 144 144 |--------------------------------------------------| 145 - | RES0 | [63-28] | n | 145 + | RES0 | [63-36] | n | 146 + |--------------------------------------------------| 147 + | SVE | [35-32] | y | 148 + |--------------------------------------------------| 149 + | RES0 | [31-28] | n | 146 150 |--------------------------------------------------| 147 151 | GIC | [27-24] | n | 148 152 |--------------------------------------------------|
+4
Documentation/arm64/elf_hwcaps.txt
··· 154 154 HWCAP_SHA512 155 155 156 156 Functionality implied by ID_AA64ISAR0_EL1.SHA2 == 0b0002. 157 + 158 + HWCAP_SVE 159 + 160 + Functionality implied by ID_AA64PFR0_EL1.SVE == 0b0001.
+2 -1
arch/arm64/include/asm/cpucaps.h
··· 40 40 #define ARM64_WORKAROUND_858921 19 41 41 #define ARM64_WORKAROUND_CAVIUM_30115 20 42 42 #define ARM64_HAS_DCPOP 21 43 + #define ARM64_SVE 22 43 44 44 - #define ARM64_NCAPS 22 45 + #define ARM64_NCAPS 23 45 46 46 47 #endif /* __ASM_CPUCAPS_H */
+2 -1
arch/arm64/include/asm/cpufeature.h
··· 273 273 274 274 static inline bool system_supports_sve(void) 275 275 { 276 - return false; 276 + return IS_ENABLED(CONFIG_ARM64_SVE) && 277 + cpus_have_const_cap(ARM64_SVE); 277 278 } 278 279 279 280 /*
+1
arch/arm64/include/uapi/asm/hwcap.h
··· 41 41 #define HWCAP_SM4 (1 << 19) 42 42 #define HWCAP_ASIMDDP (1 << 20) 43 43 #define HWCAP_SHA512 (1 << 21) 44 + #define HWCAP_SVE (1 << 22) 44 45 45 46 #endif /* _UAPI__ASM_HWCAP_H */
+17
arch/arm64/kernel/cpufeature.c
··· 145 145 }; 146 146 147 147 static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { 148 + ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0), 148 149 ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0), 149 150 S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI), 150 151 S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI), ··· 949 948 .min_field_value = 1, 950 949 }, 951 950 #endif 951 + #ifdef CONFIG_ARM64_SVE 952 + { 953 + .desc = "Scalable Vector Extension", 954 + .capability = ARM64_SVE, 955 + .def_scope = SCOPE_SYSTEM, 956 + .sys_reg = SYS_ID_AA64PFR0_EL1, 957 + .sign = FTR_UNSIGNED, 958 + .field_pos = ID_AA64PFR0_SVE_SHIFT, 959 + .min_field_value = ID_AA64PFR0_SVE, 960 + .matches = has_cpuid_feature, 961 + .enable = sve_kernel_enable, 962 + }, 963 + #endif /* CONFIG_ARM64_SVE */ 952 964 {}, 953 965 }; 954 966 ··· 999 985 HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_JSCVT_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_JSCVT), 1000 986 HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_FCMA_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_FCMA), 1001 987 HWCAP_CAP(SYS_ID_AA64ISAR1_EL1, ID_AA64ISAR1_LRCPC_SHIFT, FTR_UNSIGNED, 1, CAP_HWCAP, HWCAP_LRCPC), 988 + #ifdef CONFIG_ARM64_SVE 989 + HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_SVE_SHIFT, FTR_UNSIGNED, ID_AA64PFR0_SVE, CAP_HWCAP, HWCAP_SVE), 990 + #endif 1002 991 {}, 1003 992 }; 1004 993
+1
arch/arm64/kernel/cpuinfo.c
··· 75 75 "sm4", 76 76 "asimddp", 77 77 "sha512", 78 + "sve", 78 79 NULL 79 80 }; 80 81
+4 -3
arch/arm64/kernel/entry.S
··· 867 867 mov wscno, w8 // syscall number in w8 868 868 mov wsc_nr, #__NR_syscalls 869 869 870 - #ifndef CONFIG_ARM64_SVE 870 + #ifdef CONFIG_ARM64_SVE 871 + alternative_if_not ARM64_SVE 871 872 b el0_svc_naked 872 - #else 873 + alternative_else_nop_endif 873 874 tbz x16, #TIF_SVE, el0_svc_naked // Skip unless TIF_SVE set: 874 875 bic x16, x16, #_TIF_SVE // discard SVE state 875 876 str x16, [tsk, #TSK_TI_FLAGS] ··· 885 884 mrs x9, cpacr_el1 886 885 bic x9, x9, #CPACR_EL1_ZEN_EL0EN // disable SVE for el0 887 886 msr cpacr_el1, x9 // synchronised by eret to el0 888 - #endif /* CONFIG_ARM64_SVE */ 887 + #endif 889 888 890 889 el0_svc_naked: // compat entry point 891 890 stp x0, xscno, [sp, #S_ORIG_X0] // save the original x0 and syscall number