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

arm64/cpuinfo: Define HWCAP name arrays per their actual bit definitions

HWCAP name arrays (hwcap_str, compat_hwcap_str, compat_hwcap2_str) that are
scanned for /proc/cpuinfo are detached from their bit definitions making it
vulnerable and difficult to correlate. It is also bit problematic because
during /proc/cpuinfo dump these arrays get traversed sequentially assuming
they reflect and match actual HWCAP bit sequence, to test various features
for a given CPU. This redefines name arrays per their HWCAP bit definitions
. It also warns after detecting any feature which is not expected on arm64.

Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Dave Martin <Dave.Martin@arm.com>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Link: https://lore.kernel.org/r/1599630535-29337-1-git-send-email-anshuman.khandual@arm.com
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Anshuman Khandual and committed by
Will Deacon
4e56de82 f75aef39

+102 -86
+9
arch/arm64/include/asm/hwcap.h
··· 8 8 #include <uapi/asm/hwcap.h> 9 9 #include <asm/cpufeature.h> 10 10 11 + #define COMPAT_HWCAP_SWP (1 << 0) 11 12 #define COMPAT_HWCAP_HALF (1 << 1) 12 13 #define COMPAT_HWCAP_THUMB (1 << 2) 14 + #define COMPAT_HWCAP_26BIT (1 << 3) 13 15 #define COMPAT_HWCAP_FAST_MULT (1 << 4) 16 + #define COMPAT_HWCAP_FPA (1 << 5) 14 17 #define COMPAT_HWCAP_VFP (1 << 6) 15 18 #define COMPAT_HWCAP_EDSP (1 << 7) 19 + #define COMPAT_HWCAP_JAVA (1 << 8) 20 + #define COMPAT_HWCAP_IWMMXT (1 << 9) 21 + #define COMPAT_HWCAP_CRUNCH (1 << 10) 22 + #define COMPAT_HWCAP_THUMBEE (1 << 11) 16 23 #define COMPAT_HWCAP_NEON (1 << 12) 17 24 #define COMPAT_HWCAP_VFPv3 (1 << 13) 25 + #define COMPAT_HWCAP_VFPV3D16 (1 << 14) 18 26 #define COMPAT_HWCAP_TLS (1 << 15) 19 27 #define COMPAT_HWCAP_VFPv4 (1 << 16) 20 28 #define COMPAT_HWCAP_IDIVA (1 << 17) 21 29 #define COMPAT_HWCAP_IDIVT (1 << 18) 22 30 #define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) 31 + #define COMPAT_HWCAP_VFPD32 (1 << 19) 23 32 #define COMPAT_HWCAP_LPAE (1 << 20) 24 33 #define COMPAT_HWCAP_EVTSTRM (1 << 21) 25 34
+93 -86
arch/arm64/kernel/cpuinfo.c
··· 43 43 unsigned long __icache_flags; 44 44 45 45 static const char *const hwcap_str[] = { 46 - "fp", 47 - "asimd", 48 - "evtstrm", 49 - "aes", 50 - "pmull", 51 - "sha1", 52 - "sha2", 53 - "crc32", 54 - "atomics", 55 - "fphp", 56 - "asimdhp", 57 - "cpuid", 58 - "asimdrdm", 59 - "jscvt", 60 - "fcma", 61 - "lrcpc", 62 - "dcpop", 63 - "sha3", 64 - "sm3", 65 - "sm4", 66 - "asimddp", 67 - "sha512", 68 - "sve", 69 - "asimdfhm", 70 - "dit", 71 - "uscat", 72 - "ilrcpc", 73 - "flagm", 74 - "ssbs", 75 - "sb", 76 - "paca", 77 - "pacg", 78 - "dcpodp", 79 - "sve2", 80 - "sveaes", 81 - "svepmull", 82 - "svebitperm", 83 - "svesha3", 84 - "svesm4", 85 - "flagm2", 86 - "frint", 87 - "svei8mm", 88 - "svef32mm", 89 - "svef64mm", 90 - "svebf16", 91 - "i8mm", 92 - "bf16", 93 - "dgh", 94 - "rng", 95 - "bti", 96 - /* reserved for "mte" */ 97 - NULL 46 + [KERNEL_HWCAP_FP] = "fp", 47 + [KERNEL_HWCAP_ASIMD] = "asimd", 48 + [KERNEL_HWCAP_EVTSTRM] = "evtstrm", 49 + [KERNEL_HWCAP_AES] = "aes", 50 + [KERNEL_HWCAP_PMULL] = "pmull", 51 + [KERNEL_HWCAP_SHA1] = "sha1", 52 + [KERNEL_HWCAP_SHA2] = "sha2", 53 + [KERNEL_HWCAP_CRC32] = "crc32", 54 + [KERNEL_HWCAP_ATOMICS] = "atomics", 55 + [KERNEL_HWCAP_FPHP] = "fphp", 56 + [KERNEL_HWCAP_ASIMDHP] = "asimdhp", 57 + [KERNEL_HWCAP_CPUID] = "cpuid", 58 + [KERNEL_HWCAP_ASIMDRDM] = "asimdrdm", 59 + [KERNEL_HWCAP_JSCVT] = "jscvt", 60 + [KERNEL_HWCAP_FCMA] = "fcma", 61 + [KERNEL_HWCAP_LRCPC] = "lrcpc", 62 + [KERNEL_HWCAP_DCPOP] = "dcpop", 63 + [KERNEL_HWCAP_SHA3] = "sha3", 64 + [KERNEL_HWCAP_SM3] = "sm3", 65 + [KERNEL_HWCAP_SM4] = "sm4", 66 + [KERNEL_HWCAP_ASIMDDP] = "asimddp", 67 + [KERNEL_HWCAP_SHA512] = "sha512", 68 + [KERNEL_HWCAP_SVE] = "sve", 69 + [KERNEL_HWCAP_ASIMDFHM] = "asimdfhm", 70 + [KERNEL_HWCAP_DIT] = "dit", 71 + [KERNEL_HWCAP_USCAT] = "uscat", 72 + [KERNEL_HWCAP_ILRCPC] = "ilrcpc", 73 + [KERNEL_HWCAP_FLAGM] = "flagm", 74 + [KERNEL_HWCAP_SSBS] = "ssbs", 75 + [KERNEL_HWCAP_SB] = "sb", 76 + [KERNEL_HWCAP_PACA] = "paca", 77 + [KERNEL_HWCAP_PACG] = "pacg", 78 + [KERNEL_HWCAP_DCPODP] = "dcpodp", 79 + [KERNEL_HWCAP_SVE2] = "sve2", 80 + [KERNEL_HWCAP_SVEAES] = "sveaes", 81 + [KERNEL_HWCAP_SVEPMULL] = "svepmull", 82 + [KERNEL_HWCAP_SVEBITPERM] = "svebitperm", 83 + [KERNEL_HWCAP_SVESHA3] = "svesha3", 84 + [KERNEL_HWCAP_SVESM4] = "svesm4", 85 + [KERNEL_HWCAP_FLAGM2] = "flagm2", 86 + [KERNEL_HWCAP_FRINT] = "frint", 87 + [KERNEL_HWCAP_SVEI8MM] = "svei8mm", 88 + [KERNEL_HWCAP_SVEF32MM] = "svef32mm", 89 + [KERNEL_HWCAP_SVEF64MM] = "svef64mm", 90 + [KERNEL_HWCAP_SVEBF16] = "svebf16", 91 + [KERNEL_HWCAP_I8MM] = "i8mm", 92 + [KERNEL_HWCAP_BF16] = "bf16", 93 + [KERNEL_HWCAP_DGH] = "dgh", 94 + [KERNEL_HWCAP_RNG] = "rng", 95 + [KERNEL_HWCAP_BTI] = "bti", 98 96 }; 99 97 100 98 #ifdef CONFIG_COMPAT 99 + #define COMPAT_KERNEL_HWCAP(x) const_ilog2(COMPAT_HWCAP_ ## x) 101 100 static const char *const compat_hwcap_str[] = { 102 - "swp", 103 - "half", 104 - "thumb", 105 - "26bit", 106 - "fastmult", 107 - "fpa", 108 - "vfp", 109 - "edsp", 110 - "java", 111 - "iwmmxt", 112 - "crunch", 113 - "thumbee", 114 - "neon", 115 - "vfpv3", 116 - "vfpv3d16", 117 - "tls", 118 - "vfpv4", 119 - "idiva", 120 - "idivt", 121 - "vfpd32", 122 - "lpae", 123 - "evtstrm", 124 - NULL 101 + [COMPAT_KERNEL_HWCAP(SWP)] = "swp", 102 + [COMPAT_KERNEL_HWCAP(HALF)] = "half", 103 + [COMPAT_KERNEL_HWCAP(THUMB)] = "thumb", 104 + [COMPAT_KERNEL_HWCAP(26BIT)] = NULL, /* Not possible on arm64 */ 105 + [COMPAT_KERNEL_HWCAP(FAST_MULT)] = "fastmult", 106 + [COMPAT_KERNEL_HWCAP(FPA)] = NULL, /* Not possible on arm64 */ 107 + [COMPAT_KERNEL_HWCAP(VFP)] = "vfp", 108 + [COMPAT_KERNEL_HWCAP(EDSP)] = "edsp", 109 + [COMPAT_KERNEL_HWCAP(JAVA)] = NULL, /* Not possible on arm64 */ 110 + [COMPAT_KERNEL_HWCAP(IWMMXT)] = NULL, /* Not possible on arm64 */ 111 + [COMPAT_KERNEL_HWCAP(CRUNCH)] = NULL, /* Not possible on arm64 */ 112 + [COMPAT_KERNEL_HWCAP(THUMBEE)] = NULL, /* Not possible on arm64 */ 113 + [COMPAT_KERNEL_HWCAP(NEON)] = "neon", 114 + [COMPAT_KERNEL_HWCAP(VFPv3)] = "vfpv3", 115 + [COMPAT_KERNEL_HWCAP(VFPV3D16)] = NULL, /* Not possible on arm64 */ 116 + [COMPAT_KERNEL_HWCAP(TLS)] = "tls", 117 + [COMPAT_KERNEL_HWCAP(VFPv4)] = "vfpv4", 118 + [COMPAT_KERNEL_HWCAP(IDIVA)] = "idiva", 119 + [COMPAT_KERNEL_HWCAP(IDIVT)] = "idivt", 120 + [COMPAT_KERNEL_HWCAP(VFPD32)] = NULL, /* Not possible on arm64 */ 121 + [COMPAT_KERNEL_HWCAP(LPAE)] = "lpae", 122 + [COMPAT_KERNEL_HWCAP(EVTSTRM)] = "evtstrm", 125 123 }; 126 124 125 + #define COMPAT_KERNEL_HWCAP2(x) const_ilog2(COMPAT_HWCAP2_ ## x) 127 126 static const char *const compat_hwcap2_str[] = { 128 - "aes", 129 - "pmull", 130 - "sha1", 131 - "sha2", 132 - "crc32", 133 - NULL 127 + [COMPAT_KERNEL_HWCAP2(AES)] = "aes", 128 + [COMPAT_KERNEL_HWCAP2(PMULL)] = "pmull", 129 + [COMPAT_KERNEL_HWCAP2(SHA1)] = "sha1", 130 + [COMPAT_KERNEL_HWCAP2(SHA2)] = "sha2", 131 + [COMPAT_KERNEL_HWCAP2(CRC32)] = "crc32", 134 132 }; 135 133 #endif /* CONFIG_COMPAT */ 136 134 ··· 164 166 seq_puts(m, "Features\t:"); 165 167 if (compat) { 166 168 #ifdef CONFIG_COMPAT 167 - for (j = 0; compat_hwcap_str[j]; j++) 168 - if (compat_elf_hwcap & (1 << j)) 169 - seq_printf(m, " %s", compat_hwcap_str[j]); 169 + for (j = 0; j < ARRAY_SIZE(compat_hwcap_str); j++) { 170 + if (compat_elf_hwcap & (1 << j)) { 171 + /* 172 + * Warn once if any feature should not 173 + * have been present on arm64 platform. 174 + */ 175 + if (WARN_ON_ONCE(!compat_hwcap_str[j])) 176 + continue; 170 177 171 - for (j = 0; compat_hwcap2_str[j]; j++) 178 + seq_printf(m, " %s", compat_hwcap_str[j]); 179 + } 180 + } 181 + 182 + for (j = 0; j < ARRAY_SIZE(compat_hwcap2_str); j++) 172 183 if (compat_elf_hwcap2 & (1 << j)) 173 184 seq_printf(m, " %s", compat_hwcap2_str[j]); 174 185 #endif /* CONFIG_COMPAT */ 175 186 } else { 176 - for (j = 0; hwcap_str[j]; j++) 187 + for (j = 0; j < ARRAY_SIZE(hwcap_str); j++) 177 188 if (cpu_have_feature(j)) 178 189 seq_printf(m, " %s", hwcap_str[j]); 179 190 }