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

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.com


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent f75aef39
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -8,18 +8,27 @@
#include <uapi/asm/hwcap.h>
#include <asm/cpufeature.h>

#define COMPAT_HWCAP_SWP	(1 << 0)
#define COMPAT_HWCAP_HALF	(1 << 1)
#define COMPAT_HWCAP_THUMB	(1 << 2)
#define COMPAT_HWCAP_26BIT	(1 << 3)
#define COMPAT_HWCAP_FAST_MULT	(1 << 4)
#define COMPAT_HWCAP_FPA	(1 << 5)
#define COMPAT_HWCAP_VFP	(1 << 6)
#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_VFPv3	(1 << 13)
#define COMPAT_HWCAP_VFPV3D16	(1 << 14)
#define COMPAT_HWCAP_TLS	(1 << 15)
#define COMPAT_HWCAP_VFPv4	(1 << 16)
#define COMPAT_HWCAP_IDIVA	(1 << 17)
#define COMPAT_HWCAP_IDIVT	(1 << 18)
#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_EVTSTRM	(1 << 21)

+92 −85
Original line number Diff line number Diff line
@@ -43,94 +43,92 @@ static const char *icache_policy_str[] = {
unsigned long __icache_flags;

static const char *const hwcap_str[] = {
	"fp",
	"asimd",
	"evtstrm",
	"aes",
	"pmull",
	"sha1",
	"sha2",
	"crc32",
	"atomics",
	"fphp",
	"asimdhp",
	"cpuid",
	"asimdrdm",
	"jscvt",
	"fcma",
	"lrcpc",
	"dcpop",
	"sha3",
	"sm3",
	"sm4",
	"asimddp",
	"sha512",
	"sve",
	"asimdfhm",
	"dit",
	"uscat",
	"ilrcpc",
	"flagm",
	"ssbs",
	"sb",
	"paca",
	"pacg",
	"dcpodp",
	"sve2",
	"sveaes",
	"svepmull",
	"svebitperm",
	"svesha3",
	"svesm4",
	"flagm2",
	"frint",
	"svei8mm",
	"svef32mm",
	"svef64mm",
	"svebf16",
	"i8mm",
	"bf16",
	"dgh",
	"rng",
	"bti",
	/* reserved for "mte" */
	NULL
	[KERNEL_HWCAP_FP]		= "fp",
	[KERNEL_HWCAP_ASIMD]		= "asimd",
	[KERNEL_HWCAP_EVTSTRM]		= "evtstrm",
	[KERNEL_HWCAP_AES]		= "aes",
	[KERNEL_HWCAP_PMULL]		= "pmull",
	[KERNEL_HWCAP_SHA1]		= "sha1",
	[KERNEL_HWCAP_SHA2]		= "sha2",
	[KERNEL_HWCAP_CRC32]		= "crc32",
	[KERNEL_HWCAP_ATOMICS]		= "atomics",
	[KERNEL_HWCAP_FPHP]		= "fphp",
	[KERNEL_HWCAP_ASIMDHP]		= "asimdhp",
	[KERNEL_HWCAP_CPUID]		= "cpuid",
	[KERNEL_HWCAP_ASIMDRDM]		= "asimdrdm",
	[KERNEL_HWCAP_JSCVT]		= "jscvt",
	[KERNEL_HWCAP_FCMA]		= "fcma",
	[KERNEL_HWCAP_LRCPC]		= "lrcpc",
	[KERNEL_HWCAP_DCPOP]		= "dcpop",
	[KERNEL_HWCAP_SHA3]		= "sha3",
	[KERNEL_HWCAP_SM3]		= "sm3",
	[KERNEL_HWCAP_SM4]		= "sm4",
	[KERNEL_HWCAP_ASIMDDP]		= "asimddp",
	[KERNEL_HWCAP_SHA512]		= "sha512",
	[KERNEL_HWCAP_SVE]		= "sve",
	[KERNEL_HWCAP_ASIMDFHM]		= "asimdfhm",
	[KERNEL_HWCAP_DIT]		= "dit",
	[KERNEL_HWCAP_USCAT]		= "uscat",
	[KERNEL_HWCAP_ILRCPC]		= "ilrcpc",
	[KERNEL_HWCAP_FLAGM]		= "flagm",
	[KERNEL_HWCAP_SSBS]		= "ssbs",
	[KERNEL_HWCAP_SB]		= "sb",
	[KERNEL_HWCAP_PACA]		= "paca",
	[KERNEL_HWCAP_PACG]		= "pacg",
	[KERNEL_HWCAP_DCPODP]		= "dcpodp",
	[KERNEL_HWCAP_SVE2]		= "sve2",
	[KERNEL_HWCAP_SVEAES]		= "sveaes",
	[KERNEL_HWCAP_SVEPMULL]		= "svepmull",
	[KERNEL_HWCAP_SVEBITPERM]	= "svebitperm",
	[KERNEL_HWCAP_SVESHA3]		= "svesha3",
	[KERNEL_HWCAP_SVESM4]		= "svesm4",
	[KERNEL_HWCAP_FLAGM2]		= "flagm2",
	[KERNEL_HWCAP_FRINT]		= "frint",
	[KERNEL_HWCAP_SVEI8MM]		= "svei8mm",
	[KERNEL_HWCAP_SVEF32MM]		= "svef32mm",
	[KERNEL_HWCAP_SVEF64MM]		= "svef64mm",
	[KERNEL_HWCAP_SVEBF16]		= "svebf16",
	[KERNEL_HWCAP_I8MM]		= "i8mm",
	[KERNEL_HWCAP_BF16]		= "bf16",
	[KERNEL_HWCAP_DGH]		= "dgh",
	[KERNEL_HWCAP_RNG]		= "rng",
	[KERNEL_HWCAP_BTI]		= "bti",
};

#ifdef CONFIG_COMPAT
#define COMPAT_KERNEL_HWCAP(x)	const_ilog2(COMPAT_HWCAP_ ## x)
static const char *const compat_hwcap_str[] = {
	"swp",
	"half",
	"thumb",
	"26bit",
	"fastmult",
	"fpa",
	"vfp",
	"edsp",
	"java",
	"iwmmxt",
	"crunch",
	"thumbee",
	"neon",
	"vfpv3",
	"vfpv3d16",
	"tls",
	"vfpv4",
	"idiva",
	"idivt",
	"vfpd32",
	"lpae",
	"evtstrm",
	NULL
	[COMPAT_KERNEL_HWCAP(SWP)]	= "swp",
	[COMPAT_KERNEL_HWCAP(HALF)]	= "half",
	[COMPAT_KERNEL_HWCAP(THUMB)]	= "thumb",
	[COMPAT_KERNEL_HWCAP(26BIT)]	= NULL,	/* Not possible on arm64 */
	[COMPAT_KERNEL_HWCAP(FAST_MULT)] = "fastmult",
	[COMPAT_KERNEL_HWCAP(FPA)]	= NULL,	/* Not possible on arm64 */
	[COMPAT_KERNEL_HWCAP(VFP)]	= "vfp",
	[COMPAT_KERNEL_HWCAP(EDSP)]	= "edsp",
	[COMPAT_KERNEL_HWCAP(JAVA)]	= NULL,	/* Not possible on arm64 */
	[COMPAT_KERNEL_HWCAP(IWMMXT)]	= NULL,	/* Not possible on arm64 */
	[COMPAT_KERNEL_HWCAP(CRUNCH)]	= NULL,	/* Not possible on arm64 */
	[COMPAT_KERNEL_HWCAP(THUMBEE)]	= NULL,	/* Not possible on arm64 */
	[COMPAT_KERNEL_HWCAP(NEON)]	= "neon",
	[COMPAT_KERNEL_HWCAP(VFPv3)]	= "vfpv3",
	[COMPAT_KERNEL_HWCAP(VFPV3D16)]	= NULL,	/* Not possible on arm64 */
	[COMPAT_KERNEL_HWCAP(TLS)]	= "tls",
	[COMPAT_KERNEL_HWCAP(VFPv4)]	= "vfpv4",
	[COMPAT_KERNEL_HWCAP(IDIVA)]	= "idiva",
	[COMPAT_KERNEL_HWCAP(IDIVT)]	= "idivt",
	[COMPAT_KERNEL_HWCAP(VFPD32)]	= NULL,	/* Not possible on arm64 */
	[COMPAT_KERNEL_HWCAP(LPAE)]	= "lpae",
	[COMPAT_KERNEL_HWCAP(EVTSTRM)]	= "evtstrm",
};

#define COMPAT_KERNEL_HWCAP2(x)	const_ilog2(COMPAT_HWCAP2_ ## x)
static const char *const compat_hwcap2_str[] = {
	"aes",
	"pmull",
	"sha1",
	"sha2",
	"crc32",
	NULL
	[COMPAT_KERNEL_HWCAP2(AES)]	= "aes",
	[COMPAT_KERNEL_HWCAP2(PMULL)]	= "pmull",
	[COMPAT_KERNEL_HWCAP2(SHA1)]	= "sha1",
	[COMPAT_KERNEL_HWCAP2(SHA2)]	= "sha2",
	[COMPAT_KERNEL_HWCAP2(CRC32)]	= "crc32",
};
#endif /* CONFIG_COMPAT */

@@ -166,16 +164,25 @@ static int c_show(struct seq_file *m, void *v)
		seq_puts(m, "Features\t:");
		if (compat) {
#ifdef CONFIG_COMPAT
			for (j = 0; compat_hwcap_str[j]; j++)
				if (compat_elf_hwcap & (1 << j))
			for (j = 0; j < ARRAY_SIZE(compat_hwcap_str); 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]);
				}
			}

			for (j = 0; compat_hwcap2_str[j]; j++)
			for (j = 0; j < ARRAY_SIZE(compat_hwcap2_str); j++)
				if (compat_elf_hwcap2 & (1 << j))
					seq_printf(m, " %s", compat_hwcap2_str[j]);
#endif /* CONFIG_COMPAT */
		} else {
			for (j = 0; hwcap_str[j]; j++)
			for (j = 0; j < ARRAY_SIZE(hwcap_str); j++)
				if (cpu_have_feature(j))
					seq_printf(m, " %s", hwcap_str[j]);
		}