Skip to content

Commit

Permalink
elfloader: arm: stabilize secondary core booting
Browse files Browse the repository at this point in the history
EFI may boot the elfloader with caches disabled on the secondary cores,
we want the value of non_boot_lock to be visible.

Some barriers are added to stabilize SMP booting in the elfloader.

Co-authored-by: Yanyan Shen <[email protected]>
Co-authored-by: Matthias Rosenfelder <[email protected]>
Signed-off-by: Andy Bui <[email protected]>
  • Loading branch information
3 people committed Mar 21, 2024
1 parent 8c660fd commit 7e410f0
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
6 changes: 6 additions & 0 deletions elfloader-tool/src/arch-arm/armv/armv8-a/64/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ void core_entry(uint64_t sp)

int is_core_up(int i)
{
/* Secondary core may be booted with caches disabled,
* this value might be written in memory, invalidate our
* copy and get a new one. */
asm volatile("dc ivac, %0\n\t"
"dmb nsh\n\t"
:: "r"(&core_up[i]));
return core_up[i] == i;
}

Expand Down
9 changes: 8 additions & 1 deletion elfloader-tool/src/arch-arm/drivers/smp-psci.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*
* SPDX-License-Identifier: GPL-2.0-only
*/
#include <autoconf.h>
#include <elfloader_common.h>
#include <devices_gen.h>
#include <drivers/common.h>
Expand All @@ -24,7 +25,13 @@ static int smp_psci_cpu_on(UNUSED struct elfloader_device *dev,
}
secondary_data.entry = entry;
secondary_data.stack = stack;
dmb();
#if defined(CONFIG_ARCH_AARCH64)
/* If the secondary core caches are off, need to make sure that the info
* is clean to the physical memory so that the sedcondary cores can read it.
*/
asm volatile("dc cvac, %0" :: "r"(&secondary_data));
dsb();
#endif
int ret = psci_cpu_on(cpu->cpu_id, (unsigned long)&secondary_startup, 0);
if (ret != PSCI_SUCCESS) {
printf("Failed to bring up core 0x%x with error %d\n", cpu->cpu_id, ret);
Expand Down
25 changes: 23 additions & 2 deletions elfloader-tool/src/arch-arm/smp_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ void non_boot_main(void)
#endif
/* Spin until the first CPU has finished initialisation. */
while (!non_boot_lock) {
#ifndef CONFIG_ARCH_AARCH64
#ifdef CONFIG_ARCH_AARCH64
/* The compiler may optimize this loop away, add a dsb()
* to force a reload. */
dsb();
#else
cpu_idle();
#endif
}
Expand Down Expand Up @@ -117,7 +121,13 @@ WEAK void init_cpus(void)
abort();
}

while (!is_core_up(num_cpus));
while (!is_core_up(num_cpus)) {
#if defined(CONFIG_ARCH_AARCH64)
/* The compiler may optimize this loop away, add a dsb()
* to force a reload. */
dsb();
#endif
}
printf("Core %d is up with logic id %d\n", elfloader_cpus[i].cpu_id, num_cpus);
num_cpus++;
}
Expand All @@ -134,6 +144,17 @@ void smp_boot(void)
arm_disable_dcaches();
#endif
init_cpus();

#if defined(CONFIG_ARCH_AARCH64)
dsb();
#endif

non_boot_lock = 1;

#if defined(CONFIG_ARCH_AARCH64)
/* Secondary CPUs may still run with MMU & caches off. Force the update to be visible. */
asm volatile("dc civac, %0\n\t" :: "r"(&non_boot_lock) : "memory");;
#endif

}
#endif /* CONFIG_MAX_NUM_NODES */

0 comments on commit 7e410f0

Please sign in to comment.