boot/risc-v: improve SMP boot documentation

Improve the documentation to describe about the potential pitfall in SMP
boot and the non-recommended barrier that is used.

Signed-off-by: Axel Heider <axel.heider@hensoldt.net>
This commit is contained in:
Axel Heider
2022-04-06 12:06:54 +02:00
committed by Kent McLeod
parent 9b039f8e37
commit cd1fbafbb7
2 changed files with 23 additions and 9 deletions

View File

@@ -284,20 +284,22 @@ BOOT_CODE static bool_t try_init_kernel_secondary_core(void)
BOOT_CODE static void release_secondary_cpus(void)
{
/* release the cpus at the same time */
node_boot_lock = 1;
#ifndef CONFIG_ARCH_AARCH64
/* At this point in time the other CPUs do *not* have the seL4 global pd set.
* However, they still have a PD from the elfloader (which is mapping memory
* as strongly ordered uncached, as a result we need to explicitly clean
* the cache for it to see the update of node_boot_lock
/*
* At this point in time the primary core (executing this code) already uses
* the seL4 MMU/cache setup. However, the secondary cores are still using
* the elfloader's MMU/cache setup, and thus any memory updates may not
* be visible there.
*
* For ARMv8, the elfloader sets the page table entries as inner shareable
* (so is the attribute of the seL4 global PD) when SMP is enabled, and
* turns on the cache. Thus, we do not need to clean and invalidate the cache.
* On AARCH64, both elfloader and seL4 map memory inner shareable and have
* the caches enabled, so no explicit cache maintenance is necessary.
*
* On AARCH32 the elfloader uses strongly ordered uncached memory, but seL4
* has caching enabled, thus explicit cache cleaning is required.
*/
#ifndef CONFIG_ARCH_AARCH64
cleanInvalidateL1Caches();
plat_cleanInvalidateL2Cache();
#endif

View File

@@ -169,6 +169,18 @@ BOOT_CODE static bool_t try_init_kernel_secondary_core(word_t hart_id, word_t co
BOOT_CODE static void release_secondary_cores(void)
{
node_boot_lock = 1;
/* At this point in time the primary core (executing this code) already uses
* the seL4 MMU/cache setup. However, the secondary cores are still using
* the elfloader's MMU/cache setup, and thus the update of node_boot_lock
* may not be visible there if the setups differ. Currently, the mappings
* match, so a write-before-read fence below is all that is needed. It acts
* as a barrier to ensure the write really happens and becomes globally
* visible to make the secondary harts boot before we start the polling loop
* that checks ksNumCPUs to determine when all nodes are up. However, the
* RISC-V Unprivileged ISA spec (V20191214-draft, section A.3.6 "Fences")
* states that "fence w,r" is one of the uncommon combination and thus not
* recommended to be used.
*/
fence_w_r();
while (ksNumCPUs != CONFIG_MAX_NUM_NODES) {