Skip to content

Commit 4e56de8

Browse files
Anshuman Khandualwilldeacon
authored andcommitted
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>
1 parent f75aef3 commit 4e56de8

2 files changed

Lines changed: 101 additions & 85 deletions

File tree

arch/arm64/include/asm/hwcap.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,27 @@
88
#include <uapi/asm/hwcap.h>
99
#include <asm/cpufeature.h>
1010

11+
#define COMPAT_HWCAP_SWP (1 << 0)
1112
#define COMPAT_HWCAP_HALF (1 << 1)
1213
#define COMPAT_HWCAP_THUMB (1 << 2)
14+
#define COMPAT_HWCAP_26BIT (1 << 3)
1315
#define COMPAT_HWCAP_FAST_MULT (1 << 4)
16+
#define COMPAT_HWCAP_FPA (1 << 5)
1417
#define COMPAT_HWCAP_VFP (1 << 6)
1518
#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)
1623
#define COMPAT_HWCAP_NEON (1 << 12)
1724
#define COMPAT_HWCAP_VFPv3 (1 << 13)
25+
#define COMPAT_HWCAP_VFPV3D16 (1 << 14)
1826
#define COMPAT_HWCAP_TLS (1 << 15)
1927
#define COMPAT_HWCAP_VFPv4 (1 << 16)
2028
#define COMPAT_HWCAP_IDIVA (1 << 17)
2129
#define COMPAT_HWCAP_IDIVT (1 << 18)
2230
#define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
31+
#define COMPAT_HWCAP_VFPD32 (1 << 19)
2332
#define COMPAT_HWCAP_LPAE (1 << 20)
2433
#define COMPAT_HWCAP_EVTSTRM (1 << 21)
2534

arch/arm64/kernel/cpuinfo.c

Lines changed: 92 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -43,94 +43,92 @@ static const char *icache_policy_str[] = {
4343
unsigned long __icache_flags;
4444

4545
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",
9896
};
9997

10098
#ifdef CONFIG_COMPAT
99+
#define COMPAT_KERNEL_HWCAP(x) const_ilog2(COMPAT_HWCAP_ ## x)
101100
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",
125123
};
126124

125+
#define COMPAT_KERNEL_HWCAP2(x) const_ilog2(COMPAT_HWCAP2_ ## x)
127126
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",
134132
};
135133
#endif /* CONFIG_COMPAT */
136134

@@ -166,16 +164,25 @@ static int c_show(struct seq_file *m, void *v)
166164
seq_puts(m, "Features\t:");
167165
if (compat) {
168166
#ifdef CONFIG_COMPAT
169-
for (j = 0; compat_hwcap_str[j]; j++)
170-
if (compat_elf_hwcap & (1 << j))
167+
for (j = 0; j < ARRAY_SIZE(compat_hwcap_str); j++) {
168+
if (compat_elf_hwcap & (1 << j)) {
169+
/*
170+
* Warn once if any feature should not
171+
* have been present on arm64 platform.
172+
*/
173+
if (WARN_ON_ONCE(!compat_hwcap_str[j]))
174+
continue;
175+
171176
seq_printf(m, " %s", compat_hwcap_str[j]);
177+
}
178+
}
172179

173-
for (j = 0; compat_hwcap2_str[j]; j++)
180+
for (j = 0; j < ARRAY_SIZE(compat_hwcap2_str); j++)
174181
if (compat_elf_hwcap2 & (1 << j))
175182
seq_printf(m, " %s", compat_hwcap2_str[j]);
176183
#endif /* CONFIG_COMPAT */
177184
} else {
178-
for (j = 0; hwcap_str[j]; j++)
185+
for (j = 0; j < ARRAY_SIZE(hwcap_str); j++)
179186
if (cpu_have_feature(j))
180187
seq_printf(m, " %s", hwcap_str[j]);
181188
}

0 commit comments

Comments
 (0)