Skip to content

Commit b986558

Browse files
hoshinolinajannau
authored andcommitted
arm64: cpufeature: Unify SCOPE_LOCAL_CPU early & late behavior
SCOPE_LOCAL_CPU is mostly used for CPU errata. The early feature logic prior to this patch will enable a feature if any secondary matches it, but will not do anything once the feature is already enabled. However, the late CPU verification logic is more flexible, with flags: - ARM64_CPUCAP_OPTIONAL_FOR_LATE_CPU means "any cpu" logic applies - ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU means "all cpus" logic applies This means the early secondary feature code right now behaves as if OPTIONAL && !PERMITTED was specified (it ignores secondaries missing the feature and forces the system state to active if any secondary has the feature). Change this so that the early feature detection code inspects the flags too and applies the logic to make feature state consistent: - If a feature is NOT OPTIONAL and missing on a secondary, remove it from the system set (we can do this before finalization) - If a feature is PERMITTED and missing on the boot CPU, don't enable it but rather leave it off. This allows SCOPE_LOCAL_CPU to be used for feature detection as well as CPU errata. Signed-off-by: Asahi Lina <lina@asahilina.net>
1 parent 262e239 commit b986558

1 file changed

Lines changed: 31 additions & 3 deletions

File tree

arch/arm64/kernel/cpufeature.c

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3308,10 +3308,38 @@ static void update_cpu_capabilities(u16 scope_mask)
33083308

33093309
scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
33103310
for (i = 0; i < ARM64_NCAPS; i++) {
3311+
bool matches;
3312+
33113313
caps = cpucap_ptrs[i];
3312-
if (!caps || !(caps->type & scope_mask) ||
3313-
cpus_have_cap(caps->capability) ||
3314-
!caps->matches(caps, cpucap_default_scope(caps)))
3314+
if (!caps || !(caps->type & scope_mask))
3315+
continue;
3316+
3317+
if (!(scope_mask & SCOPE_LOCAL_CPU) && cpus_have_cap(caps->capability))
3318+
continue;
3319+
3320+
matches = caps->matches(caps, cpucap_default_scope(caps));
3321+
3322+
if (matches == cpus_have_cap(caps->capability))
3323+
continue;
3324+
3325+
if (!matches) {
3326+
/*
3327+
* Cap detected on boot CPU but not this CPU,
3328+
* disable it if not optional.
3329+
*/
3330+
if (!cpucap_late_cpu_optional(caps)) {
3331+
__clear_bit(caps->capability, system_cpucaps);
3332+
pr_info("missing on secondary: %s\n", caps->desc);
3333+
}
3334+
continue;
3335+
}
3336+
3337+
if (!(scope_mask & (SCOPE_BOOT_CPU | SCOPE_SYSTEM)) &&
3338+
cpucap_late_cpu_permitted(caps))
3339+
/*
3340+
* Cap detected on this CPU but not boot CPU,
3341+
* skip it if permitted for late CPUs.
3342+
*/
33153343
continue;
33163344

33173345
if (caps->desc && !caps->cpus)

0 commit comments

Comments
 (0)