Skip to content

Commit 82a3a21

Browse files
Suzuki K Poulosewildea01
authored andcommitted
arm64: capabilities: Speed up capability lookup
We maintain two separate tables of capabilities, errata and features, which decide the system capabilities. We iterate over each of these tables for various operations (e.g, detection, verification etc.). We do not have a way to map a system "capability" to its entry, (i.e, cap -> struct arm64_cpu_capabilities) which is needed for this_cpu_has_cap(). So we iterate over the table one by one to find the entry and then do the operation. Also, this prevents us from optimizing the way we "enable" the capabilities on the CPUs, where we now issue a stop_machine() for each available capability. One solution is to merge the two tables into a single table, sorted by the capability. But this is has the following disadvantages: - We loose the "classification" of an errata vs. feature - It is quite easy to make a mistake when adding an entry, unless we sort the table at runtime. So we maintain a list of pointers to the capability entry, sorted by the "cap number" in a separate array, initialized at boot time. The only restriction is that we can have one "entry" per capability. While at it, remove the duplicate declaration of arm64_errata table. Reviewed-by: Vladimir Murzin <[email protected]> Tested-by: Vladimir Murzin <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Signed-off-by: Will Deacon <[email protected]>
1 parent a3dcea2 commit 82a3a21

File tree

1 file changed

+30
-2
lines changed

1 file changed

+30
-2
lines changed

arch/arm64/kernel/cpufeature.c

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ unsigned int compat_elf_hwcap2 __read_mostly;
5252

5353
DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
5454
EXPORT_SYMBOL(cpu_hwcaps);
55+
static struct arm64_cpu_capabilities const __ro_after_init *cpu_hwcaps_ptrs[ARM64_NCAPS];
5556

5657
/*
5758
* Flag to indicate if we have computed the system wide
@@ -518,6 +519,29 @@ static void __init init_cpu_ftr_reg(u32 sys_reg, u64 new)
518519
}
519520

520521
extern const struct arm64_cpu_capabilities arm64_errata[];
522+
static const struct arm64_cpu_capabilities arm64_features[];
523+
524+
static void __init
525+
init_cpu_hwcaps_indirect_list_from_array(const struct arm64_cpu_capabilities *caps)
526+
{
527+
for (; caps->matches; caps++) {
528+
if (WARN(caps->capability >= ARM64_NCAPS,
529+
"Invalid capability %d\n", caps->capability))
530+
continue;
531+
if (WARN(cpu_hwcaps_ptrs[caps->capability],
532+
"Duplicate entry for capability %d\n",
533+
caps->capability))
534+
continue;
535+
cpu_hwcaps_ptrs[caps->capability] = caps;
536+
}
537+
}
538+
539+
static void __init init_cpu_hwcaps_indirect_list(void)
540+
{
541+
init_cpu_hwcaps_indirect_list_from_array(arm64_features);
542+
init_cpu_hwcaps_indirect_list_from_array(arm64_errata);
543+
}
544+
521545
static void __init setup_boot_cpu_capabilities(void);
522546

523547
void __init init_cpu_features(struct cpuinfo_arm64 *info)
@@ -563,6 +587,12 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
563587
sve_init_vq_map();
564588
}
565589

590+
/*
591+
* Initialize the indirect array of CPU hwcaps capabilities pointers
592+
* before we handle the boot CPU below.
593+
*/
594+
init_cpu_hwcaps_indirect_list();
595+
566596
/*
567597
* Detect and enable early CPU capabilities based on the boot CPU,
568598
* after we have initialised the CPU feature infrastructure.
@@ -1750,8 +1780,6 @@ static void __init mark_const_caps_ready(void)
17501780
static_branch_enable(&arm64_const_caps_ready);
17511781
}
17521782

1753-
extern const struct arm64_cpu_capabilities arm64_errata[];
1754-
17551783
bool this_cpu_has_cap(unsigned int cap)
17561784
{
17571785
return (__this_cpu_has_cap(arm64_features, cap) ||

0 commit comments

Comments
 (0)