Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f32a2439 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Gerrit - the friendly Code Review server
Browse files

ARM: 8318/1: treat CPU feature register fields as signed quantities



The various CPU feature registers consist of 4-bit blocks that
represent signed quantities, whose positive values represent
incremental features, and whose negative values are reserved.

To improve forward compatibility, update the feature detection
code to take possible future higher values into account, but
ignore negative values.

Change-Id: I7f1de53f80f2319dd6170beb4d119d5f4f2232bb
Signed-off-by: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Git-commit: b8c9592b4a6c93211c8163888a97880d608503b5
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git


Signed-off-by: default avatarNeeraj Upadhyay <neeraju@codeaurora.org>
parent 52a8c7f8
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -253,4 +253,20 @@ static inline int cpu_is_pj4(void)
#else
#define cpu_is_pj4()	0
#endif

static inline int __attribute_const__ cpuid_feature_extract_field(u32 features,
								  int field)
{
	int feature = (features >> field) & 15;

	/* feature registers are signed values */
	if (feature > 8)
		feature -= 16;

	return feature;
}

#define cpuid_feature_extract(reg, field) \
	cpuid_feature_extract_field(read_cpuid_ext(reg), field)

#endif
+9 −13
Original line number Diff line number Diff line
@@ -383,30 +383,26 @@ void __init early_print(const char *str, ...)

static void __init cpuid_init_hwcaps(void)
{
	unsigned int divide_instrs, vmsa;
	int block;

	if (cpu_architecture() < CPU_ARCH_ARMv7)
		return;

	divide_instrs = (read_cpuid_ext(CPUID_EXT_ISAR0) & 0x0f000000) >> 24;

	switch (divide_instrs) {
	case 2:
	block = cpuid_feature_extract(CPUID_EXT_ISAR0, 24);
	if (block >= 2)
		elf_hwcap |= HWCAP_IDIVA;
	case 1:
	if (block >= 1)
		elf_hwcap |= HWCAP_IDIVT;
	}

	/* LPAE implies atomic ldrd/strd instructions */
	vmsa = (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xf) >> 0;
	if (vmsa >= 5)
	block = cpuid_feature_extract(CPUID_EXT_MMFR0, 0);
	if (block >= 5)
		elf_hwcap |= HWCAP_LPAE;
}

static void __init elf_hwcap_fixup(void)
{
	unsigned id = read_cpuid_id();
	unsigned sync_prim;

	/*
	 * HWCAP_TLS is available only on 1136 r1p0 and later,
@@ -427,9 +423,9 @@ static void __init elf_hwcap_fixup(void)
	 * avoid advertising SWP; it may not be atomic with
	 * multiprocessing cores.
	 */
	sync_prim = ((read_cpuid_ext(CPUID_EXT_ISAR3) >> 8) & 0xf0) |
		    ((read_cpuid_ext(CPUID_EXT_ISAR4) >> 20) & 0x0f);
	if (sync_prim >= 0x13)
	if (cpuid_feature_extract(CPUID_EXT_ISAR3, 12) > 1 ||
	    (cpuid_feature_extract(CPUID_EXT_ISAR3, 12) == 1 &&
	     cpuid_feature_extract(CPUID_EXT_ISAR3, 20) >= 3))
		elf_hwcap &= ~HWCAP_SWP;
}