Commit 4e56de82 authored by Anshuman Khandual's avatar Anshuman Khandual Committed by Will Deacon

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: default avatarAnshuman Khandual <anshuman.khandual@arm.com>
Acked-by: default avatarCatalin 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.comSigned-off-by: default avatarWill Deacon <will@kernel.org>
parent f75aef39
...@@ -8,18 +8,27 @@ ...@@ -8,18 +8,27 @@
#include <uapi/asm/hwcap.h> #include <uapi/asm/hwcap.h>
#include <asm/cpufeature.h> #include <asm/cpufeature.h>
#define COMPAT_HWCAP_SWP (1 << 0)
#define COMPAT_HWCAP_HALF (1 << 1) #define COMPAT_HWCAP_HALF (1 << 1)
#define COMPAT_HWCAP_THUMB (1 << 2) #define COMPAT_HWCAP_THUMB (1 << 2)
#define COMPAT_HWCAP_26BIT (1 << 3)
#define COMPAT_HWCAP_FAST_MULT (1 << 4) #define COMPAT_HWCAP_FAST_MULT (1 << 4)
#define COMPAT_HWCAP_FPA (1 << 5)
#define COMPAT_HWCAP_VFP (1 << 6) #define COMPAT_HWCAP_VFP (1 << 6)
#define COMPAT_HWCAP_EDSP (1 << 7) #define COMPAT_HWCAP_EDSP (1 << 7)
#define COMPAT_HWCAP_JAVA (1 << 8)
#define COMPAT_HWCAP_IWMMXT (1 << 9)
#define COMPAT_HWCAP_CRUNCH (1 << 10)
#define COMPAT_HWCAP_THUMBEE (1 << 11)
#define COMPAT_HWCAP_NEON (1 << 12) #define COMPAT_HWCAP_NEON (1 << 12)
#define COMPAT_HWCAP_VFPv3 (1 << 13) #define COMPAT_HWCAP_VFPv3 (1 << 13)
#define COMPAT_HWCAP_VFPV3D16 (1 << 14)
#define COMPAT_HWCAP_TLS (1 << 15) #define COMPAT_HWCAP_TLS (1 << 15)
#define COMPAT_HWCAP_VFPv4 (1 << 16) #define COMPAT_HWCAP_VFPv4 (1 << 16)
#define COMPAT_HWCAP_IDIVA (1 << 17) #define COMPAT_HWCAP_IDIVA (1 << 17)
#define COMPAT_HWCAP_IDIVT (1 << 18) #define COMPAT_HWCAP_IDIVT (1 << 18)
#define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT) #define COMPAT_HWCAP_IDIV (COMPAT_HWCAP_IDIVA|COMPAT_HWCAP_IDIVT)
#define COMPAT_HWCAP_VFPD32 (1 << 19)
#define COMPAT_HWCAP_LPAE (1 << 20) #define COMPAT_HWCAP_LPAE (1 << 20)
#define COMPAT_HWCAP_EVTSTRM (1 << 21) #define COMPAT_HWCAP_EVTSTRM (1 << 21)
......
...@@ -43,94 +43,92 @@ static const char *icache_policy_str[] = { ...@@ -43,94 +43,92 @@ static const char *icache_policy_str[] = {
unsigned long __icache_flags; unsigned long __icache_flags;
static const char *const hwcap_str[] = { static const char *const hwcap_str[] = {
"fp", [KERNEL_HWCAP_FP] = "fp",
"asimd", [KERNEL_HWCAP_ASIMD] = "asimd",
"evtstrm", [KERNEL_HWCAP_EVTSTRM] = "evtstrm",
"aes", [KERNEL_HWCAP_AES] = "aes",
"pmull", [KERNEL_HWCAP_PMULL] = "pmull",
"sha1", [KERNEL_HWCAP_SHA1] = "sha1",
"sha2", [KERNEL_HWCAP_SHA2] = "sha2",
"crc32", [KERNEL_HWCAP_CRC32] = "crc32",
"atomics", [KERNEL_HWCAP_ATOMICS] = "atomics",
"fphp", [KERNEL_HWCAP_FPHP] = "fphp",
"asimdhp", [KERNEL_HWCAP_ASIMDHP] = "asimdhp",
"cpuid", [KERNEL_HWCAP_CPUID] = "cpuid",
"asimdrdm", [KERNEL_HWCAP_ASIMDRDM] = "asimdrdm",
"jscvt", [KERNEL_HWCAP_JSCVT] = "jscvt",
"fcma", [KERNEL_HWCAP_FCMA] = "fcma",
"lrcpc", [KERNEL_HWCAP_LRCPC] = "lrcpc",
"dcpop", [KERNEL_HWCAP_DCPOP] = "dcpop",
"sha3", [KERNEL_HWCAP_SHA3] = "sha3",
"sm3", [KERNEL_HWCAP_SM3] = "sm3",
"sm4", [KERNEL_HWCAP_SM4] = "sm4",
"asimddp", [KERNEL_HWCAP_ASIMDDP] = "asimddp",
"sha512", [KERNEL_HWCAP_SHA512] = "sha512",
"sve", [KERNEL_HWCAP_SVE] = "sve",
"asimdfhm", [KERNEL_HWCAP_ASIMDFHM] = "asimdfhm",
"dit", [KERNEL_HWCAP_DIT] = "dit",
"uscat", [KERNEL_HWCAP_USCAT] = "uscat",
"ilrcpc", [KERNEL_HWCAP_ILRCPC] = "ilrcpc",
"flagm", [KERNEL_HWCAP_FLAGM] = "flagm",
"ssbs", [KERNEL_HWCAP_SSBS] = "ssbs",
"sb", [KERNEL_HWCAP_SB] = "sb",
"paca", [KERNEL_HWCAP_PACA] = "paca",
"pacg", [KERNEL_HWCAP_PACG] = "pacg",
"dcpodp", [KERNEL_HWCAP_DCPODP] = "dcpodp",
"sve2", [KERNEL_HWCAP_SVE2] = "sve2",
"sveaes", [KERNEL_HWCAP_SVEAES] = "sveaes",
"svepmull", [KERNEL_HWCAP_SVEPMULL] = "svepmull",
"svebitperm", [KERNEL_HWCAP_SVEBITPERM] = "svebitperm",
"svesha3", [KERNEL_HWCAP_SVESHA3] = "svesha3",
"svesm4", [KERNEL_HWCAP_SVESM4] = "svesm4",
"flagm2", [KERNEL_HWCAP_FLAGM2] = "flagm2",
"frint", [KERNEL_HWCAP_FRINT] = "frint",
"svei8mm", [KERNEL_HWCAP_SVEI8MM] = "svei8mm",
"svef32mm", [KERNEL_HWCAP_SVEF32MM] = "svef32mm",
"svef64mm", [KERNEL_HWCAP_SVEF64MM] = "svef64mm",
"svebf16", [KERNEL_HWCAP_SVEBF16] = "svebf16",
"i8mm", [KERNEL_HWCAP_I8MM] = "i8mm",
"bf16", [KERNEL_HWCAP_BF16] = "bf16",
"dgh", [KERNEL_HWCAP_DGH] = "dgh",
"rng", [KERNEL_HWCAP_RNG] = "rng",
"bti", [KERNEL_HWCAP_BTI] = "bti",
/* reserved for "mte" */
NULL
}; };
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
#define COMPAT_KERNEL_HWCAP(x) const_ilog2(COMPAT_HWCAP_ ## x)
static const char *const compat_hwcap_str[] = { static const char *const compat_hwcap_str[] = {
"swp", [COMPAT_KERNEL_HWCAP(SWP)] = "swp",
"half", [COMPAT_KERNEL_HWCAP(HALF)] = "half",
"thumb", [COMPAT_KERNEL_HWCAP(THUMB)] = "thumb",
"26bit", [COMPAT_KERNEL_HWCAP(26BIT)] = NULL, /* Not possible on arm64 */
"fastmult", [COMPAT_KERNEL_HWCAP(FAST_MULT)] = "fastmult",
"fpa", [COMPAT_KERNEL_HWCAP(FPA)] = NULL, /* Not possible on arm64 */
"vfp", [COMPAT_KERNEL_HWCAP(VFP)] = "vfp",
"edsp", [COMPAT_KERNEL_HWCAP(EDSP)] = "edsp",
"java", [COMPAT_KERNEL_HWCAP(JAVA)] = NULL, /* Not possible on arm64 */
"iwmmxt", [COMPAT_KERNEL_HWCAP(IWMMXT)] = NULL, /* Not possible on arm64 */
"crunch", [COMPAT_KERNEL_HWCAP(CRUNCH)] = NULL, /* Not possible on arm64 */
"thumbee", [COMPAT_KERNEL_HWCAP(THUMBEE)] = NULL, /* Not possible on arm64 */
"neon", [COMPAT_KERNEL_HWCAP(NEON)] = "neon",
"vfpv3", [COMPAT_KERNEL_HWCAP(VFPv3)] = "vfpv3",
"vfpv3d16", [COMPAT_KERNEL_HWCAP(VFPV3D16)] = NULL, /* Not possible on arm64 */
"tls", [COMPAT_KERNEL_HWCAP(TLS)] = "tls",
"vfpv4", [COMPAT_KERNEL_HWCAP(VFPv4)] = "vfpv4",
"idiva", [COMPAT_KERNEL_HWCAP(IDIVA)] = "idiva",
"idivt", [COMPAT_KERNEL_HWCAP(IDIVT)] = "idivt",
"vfpd32", [COMPAT_KERNEL_HWCAP(VFPD32)] = NULL, /* Not possible on arm64 */
"lpae", [COMPAT_KERNEL_HWCAP(LPAE)] = "lpae",
"evtstrm", [COMPAT_KERNEL_HWCAP(EVTSTRM)] = "evtstrm",
NULL
}; };
#define COMPAT_KERNEL_HWCAP2(x) const_ilog2(COMPAT_HWCAP2_ ## x)
static const char *const compat_hwcap2_str[] = { static const char *const compat_hwcap2_str[] = {
"aes", [COMPAT_KERNEL_HWCAP2(AES)] = "aes",
"pmull", [COMPAT_KERNEL_HWCAP2(PMULL)] = "pmull",
"sha1", [COMPAT_KERNEL_HWCAP2(SHA1)] = "sha1",
"sha2", [COMPAT_KERNEL_HWCAP2(SHA2)] = "sha2",
"crc32", [COMPAT_KERNEL_HWCAP2(CRC32)] = "crc32",
NULL
}; };
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
...@@ -166,16 +164,25 @@ static int c_show(struct seq_file *m, void *v) ...@@ -166,16 +164,25 @@ static int c_show(struct seq_file *m, void *v)
seq_puts(m, "Features\t:"); seq_puts(m, "Features\t:");
if (compat) { if (compat) {
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
for (j = 0; compat_hwcap_str[j]; j++) for (j = 0; j < ARRAY_SIZE(compat_hwcap_str); j++) {
if (compat_elf_hwcap & (1 << j)) if (compat_elf_hwcap & (1 << j)) {
/*
* Warn once if any feature should not
* have been present on arm64 platform.
*/
if (WARN_ON_ONCE(!compat_hwcap_str[j]))
continue;
seq_printf(m, " %s", compat_hwcap_str[j]); seq_printf(m, " %s", compat_hwcap_str[j]);
}
}
for (j = 0; compat_hwcap2_str[j]; j++) for (j = 0; j < ARRAY_SIZE(compat_hwcap2_str); j++)
if (compat_elf_hwcap2 & (1 << j)) if (compat_elf_hwcap2 & (1 << j))
seq_printf(m, " %s", compat_hwcap2_str[j]); seq_printf(m, " %s", compat_hwcap2_str[j]);
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
} else { } else {
for (j = 0; hwcap_str[j]; j++) for (j = 0; j < ARRAY_SIZE(hwcap_str); j++)
if (cpu_have_feature(j)) if (cpu_have_feature(j))
seq_printf(m, " %s", hwcap_str[j]); seq_printf(m, " %s", hwcap_str[j]);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment