Skip to content

Commit 0b587c8

Browse files
Suzuki K Poulosewildea01
authored andcommitted
arm64: capabilities: Batch cpu_enable callbacks
We use a stop_machine call for each available capability to enable it on all the CPUs available at boot time. Instead we could batch the cpu_enable callbacks to a single stop_machine() call to save us some time. 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 606f8e7 commit 0b587c8

File tree

2 files changed

+47
-26
lines changed

2 files changed

+47
-26
lines changed

arch/arm64/include/asm/cpufeature.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,9 @@ extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
357357
extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
358358
extern struct static_key_false arm64_const_caps_ready;
359359

360+
#define for_each_available_cap(cap) \
361+
for_each_set_bit(cap, cpu_hwcaps, ARM64_NCAPS)
362+
360363
bool this_cpu_has_cap(unsigned int cap);
361364

362365
static inline bool cpu_have_feature(unsigned int num)

arch/arm64/kernel/cpufeature.c

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,33 +1531,57 @@ static void update_cpu_capabilities(u16 scope_mask)
15311531
}
15321532
}
15331533

1534-
static int __enable_cpu_capability(void *arg)
1534+
/*
1535+
* Enable all the available capabilities on this CPU. The capabilities
1536+
* with BOOT_CPU scope are handled separately and hence skipped here.
1537+
*/
1538+
static int cpu_enable_non_boot_scope_capabilities(void *__unused)
15351539
{
1536-
const struct arm64_cpu_capabilities *cap = arg;
1540+
int i;
1541+
u16 non_boot_scope = SCOPE_ALL & ~SCOPE_BOOT_CPU;
1542+
1543+
for_each_available_cap(i) {
1544+
const struct arm64_cpu_capabilities *cap = cpu_hwcaps_ptrs[i];
1545+
1546+
if (WARN_ON(!cap))
1547+
continue;
1548+
1549+
if (!(cap->type & non_boot_scope))
1550+
continue;
15371551

1538-
cap->cpu_enable(cap);
1552+
if (cap->cpu_enable)
1553+
cap->cpu_enable(cap);
1554+
}
15391555
return 0;
15401556
}
15411557

15421558
/*
15431559
* Run through the enabled capabilities and enable() it on all active
15441560
* CPUs
15451561
*/
1546-
static void __init
1547-
__enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
1548-
u16 scope_mask)
1562+
static void __init enable_cpu_capabilities(u16 scope_mask)
15491563
{
1564+
int i;
1565+
const struct arm64_cpu_capabilities *caps;
1566+
bool boot_scope;
1567+
15501568
scope_mask &= ARM64_CPUCAP_SCOPE_MASK;
1551-
for (; caps->matches; caps++) {
1552-
unsigned int num = caps->capability;
1569+
boot_scope = !!(scope_mask & SCOPE_BOOT_CPU);
1570+
1571+
for (i = 0; i < ARM64_NCAPS; i++) {
1572+
unsigned int num;
15531573

1554-
if (!(caps->type & scope_mask) || !cpus_have_cap(num))
1574+
caps = cpu_hwcaps_ptrs[i];
1575+
if (!caps || !(caps->type & scope_mask))
1576+
continue;
1577+
num = caps->capability;
1578+
if (!cpus_have_cap(num))
15551579
continue;
15561580

15571581
/* Ensure cpus_have_const_cap(num) works */
15581582
static_branch_enable(&cpu_hwcap_keys[num]);
15591583

1560-
if (caps->cpu_enable) {
1584+
if (boot_scope && caps->cpu_enable)
15611585
/*
15621586
* Capabilities with SCOPE_BOOT_CPU scope are finalised
15631587
* before any secondary CPU boots. Thus, each secondary
@@ -1566,25 +1590,19 @@ __enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
15661590
* the boot CPU, for which the capability must be
15671591
* enabled here. This approach avoids costly
15681592
* stop_machine() calls for this case.
1569-
*
1570-
* Otherwise, use stop_machine() as it schedules the
1571-
* work allowing us to modify PSTATE, instead of
1572-
* on_each_cpu() which uses an IPI, giving us a PSTATE
1573-
* that disappears when we return.
15741593
*/
1575-
if (scope_mask & SCOPE_BOOT_CPU)
1576-
caps->cpu_enable(caps);
1577-
else
1578-
stop_machine(__enable_cpu_capability,
1579-
(void *)caps, cpu_online_mask);
1580-
}
1594+
caps->cpu_enable(caps);
15811595
}
1582-
}
15831596

1584-
static void __init enable_cpu_capabilities(u16 scope_mask)
1585-
{
1586-
__enable_cpu_capabilities(arm64_errata, scope_mask);
1587-
__enable_cpu_capabilities(arm64_features, scope_mask);
1597+
/*
1598+
* For all non-boot scope capabilities, use stop_machine()
1599+
* as it schedules the work allowing us to modify PSTATE,
1600+
* instead of on_each_cpu() which uses an IPI, giving us a
1601+
* PSTATE that disappears when we return.
1602+
*/
1603+
if (!boot_scope)
1604+
stop_machine(cpu_enable_non_boot_scope_capabilities,
1605+
NULL, cpu_online_mask);
15881606
}
15891607

15901608
/*

0 commit comments

Comments
 (0)