diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2018-03-06 18:15:34 +0100 |
---|---|---|
committer | Will Deacon <will.deacon@arm.com> | 2018-03-09 14:23:08 +0100 |
commit | e8002e02abf052c07bb87b867789034bc79aac10 (patch) | |
tree | dc8c80d2d0f704cde4b20a9c6e0fb3cc270bc406 | |
parent | arm64/kernel: don't ban ADRP to work around Cortex-A53 erratum #843419 (diff) | |
download | linux-e8002e02abf052c07bb87b867789034bc79aac10.tar.xz linux-e8002e02abf052c07bb87b867789034bc79aac10.zip |
arm64/errata: add REVIDR handling to framework
In some cases, core variants that are affected by a certain erratum
also exist in versions that have the erratum fixed, and this fact is
recorded in a dedicated bit in system register REVIDR_EL1.
Since the architecture does not require that a certain bit retains
its meaning across different variants of the same model, each such
REVIDR bit is tightly coupled to a certain revision/variant value,
and so we need a list of revidr_mask/midr pairs to carry this
information.
So add the struct member and the associated macros and handling to
allow REVIDR fixes to be taken into account.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Will Deacon <will.deacon@arm.com>
-rw-r--r-- | arch/arm64/include/asm/cpufeature.h | 4 | ||||
-rw-r--r-- | arch/arm64/kernel/cpu_errata.c | 21 |
2 files changed, 22 insertions, 3 deletions
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 060e3a4008ab..fbf0aab94d67 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -105,6 +105,10 @@ struct arm64_cpu_capabilities { struct { /* To be used for erratum handling only */ u32 midr_model; u32 midr_range_min, midr_range_max; + const struct arm64_midr_revidr { + u32 midr_rv; /* revision/variant */ + u32 revidr_mask; + } * const fixed_revs; }; struct { /* Feature register checking */ diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 52f15cd896e1..b161abdd6e27 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -24,10 +24,22 @@ static bool __maybe_unused is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope) { + const struct arm64_midr_revidr *fix; + u32 midr = read_cpuid_id(), revidr; + WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); - return MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(), entry->midr_model, - entry->midr_range_min, - entry->midr_range_max); + if (!MIDR_IS_CPU_MODEL_RANGE(midr, entry->midr_model, + entry->midr_range_min, + entry->midr_range_max)) + return false; + + midr &= MIDR_REVISION_MASK | MIDR_VARIANT_MASK; + revidr = read_cpuid(REVIDR_EL1); + for (fix = entry->fixed_revs; fix && fix->revidr_mask; fix++) + if (midr == fix->midr_rv && (revidr & fix->revidr_mask)) + return false; + + return true; } static bool __maybe_unused @@ -242,6 +254,9 @@ static int qcom_enable_link_stack_sanitization(void *data) .midr_range_min = 0, \ .midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK) +#define MIDR_FIXED(rev, revidr_mask) \ + .fixed_revs = (struct arm64_midr_revidr[]){{ (rev), (revidr_mask) }, {}} + const struct arm64_cpu_capabilities arm64_errata[] = { #if defined(CONFIG_ARM64_ERRATUM_826319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \ |