arm64: errata: match the target implementation CPU's own MIDR
Subsystems (2)
PATCH 1/1 arm64: errata: match the target implementation CPU's own MIDR
__is_affected_midr_range() is handed the MIDR and REVIDR of one target implementation CPU, but tests the erratum's range with is_midr_in_range(), which re-scans all of target_impl_cpus[] and ignores the @midr argument. The range test is thus constant across the per-CPU loop in is_affected_midr_range() and only answers "is any target CPU in range".
Since just the fixed_revs REVIDR check uses the iteration's own registers, an out-of-range target CPU can decide whether a MIDR_FIXED() exemption applies. A VM then enables a workaround whose only in-range CPU is fixed silicon, e.g. erratum 2658417 on a Cortex-A510 r1p1 with REVIDR_EL1[25] set.
Factor the range test into __is_midr_in_range(), which takes an explicit MIDR, and use it in __is_affected_midr_range().
--- arch/arm64/kernel/cpu_errata.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
arch/arm64/kernel/cpu_errata.c +9 -6
@@ -28,18 +28,21 @@ bool cpu_errata_set_target_impl(u64 num, void *impl_cpus)return true; } +static inline bool __is_midr_in_range (u32 midr,struct midr_range const *range) +{ +return midr_is_cpu_model_range (midr, range->model, + range->rv_min, range->rv_max); +} +static inline bool is_midr_in_range (struct midr_range const *range) {int i;if (!target_impl_cpu_num) -return midr_is_cpu_model_range (read_cpuid_id (), range->model, - range->rv_min, range->rv_max); +return __is_midr_in_range (read_cpuid_id (), range);for (i =0 ; i < target_impl_cpu_num; i++) { -if (midr_is_cpu_model_range (target_impl_cpus[i].midr, - range->model, - range->rv_min, range->rv_max)) +if (__is_midr_in_range (target_impl_cpus[i].midr, range))return true; }return false;
@@ -59,7 +62,7 @@ __is_affected_midr_range(const struct arm64_cpu_capabilities *entry, u32 midr, u32 revidr) {const struct arm64_midr_revidr *fix; -if (!is_midr_in_range (&entry->midr_range)) +if (!__is_midr_in_range (midr, &entry->midr_range))return false; midr &=MIDR_REVISION_MASK |MIDR_VARIANT_MASK ;
Signature · 1 line
2.55.0
Quoted 6 lines · David Carlier
__is_affected_midr_range()is handed the MIDR and REVIDR of one target implementation CPU, but tests the erratum's range withis_midr_in_range(), which re-scans all of target_impl_cpus[] and ignores the @midr argument. The range test is thus constant across the per-CPU loop inis_affected_midr_range()and only answers "is any target CPU in range".
Quoted 7 lines
Since just the
fixed_revsREVIDR check uses the iteration's own registers, an out-of-range target CPU can decide whether aMIDR_FIXED()exemption applies. A VM then enables a workaround whose only in-range CPU is fixed silicon, e.g. erratum 2658417 on a Cortex-A510 r1p1 with REVIDR_EL1[25] set.[...]
Applied to arm64 (for-next/fixes), thanks!
[1/1] arm64: errata: match the target implementation CPU's own MIDR
https://git.kernel.org/arm64/c/b7403afb7a5f
Cheers,
Signature · 5 lines
Will https://fixes.arm64.dev https://next.arm64.dev https://will.arm64.dev