Skip to content

Commit ac31787

Browse files
asahilinajannau
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 <[email protected]>
1 parent 18789c9 commit ac31787

File tree

1 file changed

+31
-3
lines changed

1 file changed

+31
-3
lines changed

arch/arm64/kernel/cpufeature.c

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

33583358
scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
33593359
for (i = 0; i < ARM64_NCAPS; i++) {
3360+
bool matches;
3361+
33603362
caps = cpucap_ptrs[i];
3361-
if (!caps || !(caps->type & scope_mask) ||
3362-
cpus_have_cap(caps->capability) ||
3363-
!caps->matches(caps, cpucap_default_scope(caps)))
3363+
if (!caps || !(caps->type & scope_mask))
3364+
continue;
3365+
3366+
if (!(scope_mask & SCOPE_LOCAL_CPU) && cpus_have_cap(caps->capability))
3367+
continue;
3368+
3369+
matches = caps->matches(caps, cpucap_default_scope(caps));
3370+
3371+
if (matches == cpus_have_cap(caps->capability))
3372+
continue;
3373+
3374+
if (!matches) {
3375+
/*
3376+
* Cap detected on boot CPU but not this CPU,
3377+
* disable it if not optional.
3378+
*/
3379+
if (!cpucap_late_cpu_optional(caps)) {
3380+
__clear_bit(caps->capability, system_cpucaps);
3381+
pr_info("missing on secondary: %s\n", caps->desc);
3382+
}
3383+
continue;
3384+
}
3385+
3386+
if (!(scope_mask & (SCOPE_BOOT_CPU | SCOPE_SYSTEM)) &&
3387+
cpucap_late_cpu_permitted(caps))
3388+
/*
3389+
* Cap detected on this CPU but not boot CPU,
3390+
* skip it if permitted for late CPUs.
3391+
*/
33643392
continue;
33653393

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

0 commit comments

Comments
 (0)