Commit e8002e02 authored by Ard Biesheuvel's avatar Ard Biesheuvel Committed by Will Deacon

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: default avatarArd Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: default avatarWill Deacon <will.deacon@arm.com>
parent a257e025
...@@ -105,6 +105,10 @@ struct arm64_cpu_capabilities { ...@@ -105,6 +105,10 @@ struct arm64_cpu_capabilities {
struct { /* To be used for erratum handling only */ struct { /* To be used for erratum handling only */
u32 midr_model; u32 midr_model;
u32 midr_range_min, midr_range_max; 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 */ struct { /* Feature register checking */
......
...@@ -24,10 +24,22 @@ ...@@ -24,10 +24,22 @@
static bool __maybe_unused static bool __maybe_unused
is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope) 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()); WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
return MIDR_IS_CPU_MODEL_RANGE(read_cpuid_id(), entry->midr_model, if (!MIDR_IS_CPU_MODEL_RANGE(midr, entry->midr_model,
entry->midr_range_min, entry->midr_range_min,
entry->midr_range_max); 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 static bool __maybe_unused
...@@ -242,6 +254,9 @@ static int qcom_enable_link_stack_sanitization(void *data) ...@@ -242,6 +254,9 @@ static int qcom_enable_link_stack_sanitization(void *data)
.midr_range_min = 0, \ .midr_range_min = 0, \
.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK) .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[] = { const struct arm64_cpu_capabilities arm64_errata[] = {
#if defined(CONFIG_ARM64_ERRATUM_826319) || \ #if defined(CONFIG_ARM64_ERRATUM_826319) || \
defined(CONFIG_ARM64_ERRATUM_827319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \
......
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