Skip to content

Commit

Permalink
boot: remove redundant initialization
Browse files Browse the repository at this point in the history
All architectures run the same generic kernel init.

Signed-off-by: Axel Heider <[email protected]>
  • Loading branch information
axel-h committed Aug 27, 2023
1 parent 8eb6dad commit 1c5cb58
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 125 deletions.
10 changes: 7 additions & 3 deletions include/kernel/boot.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,16 +139,20 @@ static inline BOOT_CODE pptr_t it_alloc_paging(void)
/* return the amount of paging structures required to cover v_reg */
word_t arch_get_n_paging(v_region_t it_veg);

bool_t finalize_init_kernel(void);

#ifdef ENABLE_SMP_SUPPORT
void release_secondary_cores(void);
bool_t finalize_init_kernel_on_secondary_core(void);
#endif

#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
/* Test whether clocks are synchronised across nodes */
void clock_sync_test(void);
void clock_sync_test_evaluation(void);
#define SMP_CLOCK_SYNC_TEST_UPDATE_TIME() \
do { \
NODE_STATE(ksCurTime) = getCurrentTime(); \
__atomic_thread_fence(__ATOMIC_RELEASE); \
} while(0)
#else
#define clock_sync_test()
#define SMP_CLOCK_SYNC_TEST_UPDATE_TIME() ((void)0)
#endif
39 changes: 3 additions & 36 deletions src/arch/arm/kernel/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,20 +285,12 @@ BOOT_CODE static bool_t try_init_kernel_secondary_core(void)
setIRQState(IRQReserved, CORE_IRQ_TO_IRQT(getCurrentCPUIndex(), INTERRUPT_VGIC_MAINTENANCE));
setIRQState(IRQReserved, CORE_IRQ_TO_IRQT(getCurrentCPUIndex(), INTERRUPT_VTIMER_EVENT));
#endif /* CONFIG_ARM_HYPERVISOR_SUPPORT */
NODE_LOCK_SYS;

clock_sync_test();
ksNumCPUs++;

init_core_state(SchedulerAction_ResumeCurrentThread);

return true;
return finalize_init_kernel_on_secondary_core();
}

BOOT_CODE static void release_secondary_cpus(void)
BOOT_CODE void release_secondary_cores(void)
{
SMP_CLOCK_SYNC_TEST_UPDATE_TIME();

/* release the cpus at the same time */
assert(0 == node_boot_lock); /* Sanity check for a proper lock state. */
node_boot_lock = 1;
Expand Down Expand Up @@ -326,10 +318,6 @@ BOOT_CODE static void release_secondary_cpus(void)
/* perform a memory acquire to get new values of ksNumCPUs */
__atomic_thread_fence(__ATOMIC_ACQUIRE);
}

#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
clock_sync_test_evaluation();
#endif
}
#endif /* ENABLE_SMP_SUPPORT */

Expand Down Expand Up @@ -618,21 +606,7 @@ static BOOT_CODE bool_t try_init_kernel(

ksNumCPUs = 1;

/* initialize BKL before booting up other cores */
SMP_COND_STATEMENT(clh_lock_init());
SMP_COND_STATEMENT(release_secondary_cpus());

/* All cores are up now, so there can be concurrency. The kernel booting is
* supposed to be finished before the secondary cores are released, all the
* primary has to do now is schedule the initial thread. Currently there is
* nothing that touches any global data structures, nevertheless we grab the
* BKL here to play safe. It is released when the kernel is left. */
NODE_LOCK_SYS;

printf("Booting all finished, dropped to user space\n");

/* kernel successfully initialized */
return true;
return finalize_init_kernel();
}

BOOT_CODE VISIBLE void init_kernel(
Expand Down Expand Up @@ -671,11 +645,4 @@ BOOT_CODE VISIBLE void init_kernel(
fail("ERROR: kernel init failed");
UNREACHABLE();
}

#ifdef CONFIG_KERNEL_MCS
NODE_STATE(ksCurTime) = getCurrentTime();
NODE_STATE(ksConsumed) = 0;
#endif
schedule();
activateThread();
}
36 changes: 3 additions & 33 deletions src/arch/riscv/kernel/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,19 +166,12 @@ BOOT_CODE static bool_t try_init_kernel_secondary_core(word_t hart_id, word_t co
fence_r_rw();

init_cpu();
NODE_LOCK_SYS;

clock_sync_test();
ksNumCPUs++;
init_core_state(SchedulerAction_ResumeCurrentThread);
ifence_local();
return true;
return finalize_init_kernel_on_secondary_core();
}

BOOT_CODE static void release_secondary_cores(void)
BOOT_CODE void release_secondary_cores(void)
{
SMP_CLOCK_SYNC_TEST_UPDATE_TIME();

assert(0 == node_boot_lock); /* Sanity check for a proper lock state. */
node_boot_lock = 1;
/* At this point in time the primary core (executing this code) already uses
Expand All @@ -194,10 +187,6 @@ BOOT_CODE static void release_secondary_cores(void)
/* perform a memory acquire to get new values of ksNumCPUs */
__atomic_thread_fence(__ATOMIC_ACQUIRE);
}

#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
clock_sync_test_evaluation();
#endif
}
#endif /* ENABLE_SMP_SUPPORT */

Expand Down Expand Up @@ -452,18 +441,7 @@ static BOOT_CODE bool_t try_init_kernel(

ksNumCPUs = 1;

SMP_COND_STATEMENT(clh_lock_init());
SMP_COND_STATEMENT(release_secondary_cores());

/* All cores are up now, so there can be concurrency. The kernel booting is
* supposed to be finished before the secondary cores are released, all the
* primary has to do now is schedule the initial thread. Currently there is
* nothing that touches any global data structures, nevertheless we grab the
* BKL here to play safe. It is released when the kernel is left. */
NODE_LOCK_SYS;

printf("Booting all finished, dropped to user space\n");
return true;
return finalize_init_kernel();
}

BOOT_CODE VISIBLE void init_kernel(
Expand Down Expand Up @@ -506,12 +484,4 @@ BOOT_CODE VISIBLE void init_kernel(
fail("ERROR: kernel init failed");
UNREACHABLE();
}

#ifdef CONFIG_KERNEL_MCS
NODE_STATE(ksCurTime) = getCurrentTime();
NODE_STATE(ksConsumed) = 0;
#endif

schedule();
activateThread();
}
24 changes: 4 additions & 20 deletions src/arch/x86/kernel/boot_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -492,16 +492,7 @@ static BOOT_CODE bool_t try_boot_sys(void)
ioapic_init(1, boot_state.cpus, boot_state.num_ioapic);
}

/* initialize BKL before booting up APs */
SMP_COND_STATEMENT(clh_lock_init());
SMP_COND_STATEMENT(start_boot_aps());

/* grab BKL before leaving the kernel */
NODE_LOCK_SYS;

printf("Booting all finished, dropped to user space\n");

return true;
return finalize_init_kernel();
}

static BOOT_CODE bool_t try_boot_sys_mbi1(
Expand Down Expand Up @@ -702,7 +693,7 @@ BOOT_CODE VISIBLE void boot_sys(
unsigned long multiboot_magic,
void *mbi)
{
switch(multiboot_magic) {
switch (multiboot_magic) {
case MULTIBOOT_MAGIC:
if (!try_boot_sys_mbi1(mbi)) {
fail("try_boot_sys_mbi1 failed\n");
Expand All @@ -718,15 +709,8 @@ BOOT_CODE VISIBLE void boot_sys(
break;
}

if (!try_boot_sys())
if (!try_boot_sys()) {
fail("boot_sys failed for some reason :(\n");
UNREACHABLE();
}

#ifdef CONFIG_KERNEL_MCS
NODE_STATE(ksCurTime) = getCurrentTime();
NODE_STATE(ksConsumed) = 0;
#endif

schedule();
activateThread();
}
41 changes: 10 additions & 31 deletions src/arch/x86/kernel/smp_sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ BOOT_CODE static void start_cpu(cpu_id_t cpu_id, paddr_t boot_fun_paddr)
apic_send_startup_ipi(cpu_id, boot_fun_paddr);
}

BOOT_CODE void start_boot_aps(void)
BOOT_CODE void release_secondary_cores(void)
{
/* update cpu mapping for BSP, cpus[0] is always assumed to be BSP */
cpu_mapping.index_to_cpu_id[getCurrentCPUIndex()] = boot_state.cpus[0];
Expand Down Expand Up @@ -67,11 +67,6 @@ BOOT_CODE void start_boot_aps(void)
SMP_CLOCK_SYNC_TEST_UPDATE_TIME();
}
}

#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
clock_sync_test_evaluation();
#endif

}

BOOT_CODE bool_t copy_boot_code_aps(uint32_t mem_lower)
Expand Down Expand Up @@ -100,46 +95,30 @@ BOOT_CODE bool_t copy_boot_code_aps(uint32_t mem_lower)
return true;
}

static BOOT_CODE bool_t try_boot_node(void)
/* This is the entry function for APs. However, it is not a BOOT_CODE as
* there is a race between exiting this function and root task running on
* node #0 to possibly reallocate this memory */
VISIBLE void boot_node(void)
{
mode_init_tls(ksNumCPUs);

setCurrentVSpaceRoot(kpptr_to_paddr(X86_KERNEL_VSPACE_ROOT), 0);
/* Sync up the compilers view of the world here to force the PD to actually
* be set *right now* instead of delayed */
x86_mfence();

/* initialise the CPU, make sure legacy interrupts are disabled */
if (!init_cpu(1)) {
return false;
fail("init_cpu failed\n");
}

#ifdef CONFIG_USE_LOGICAL_IDS
update_logical_id_mappings();
#endif /* CONFIG_USE_LOGICAL_IDS */
return true;
}

/* This is the entry function for APs. However, it is not a BOOT_CODE as
* there is a race between exiting this function and root task running on
* node #0 to possibly reallocate this memory */
VISIBLE void boot_node(void)
{
mode_init_tls(ksNumCPUs);

if (!try_boot_node()) {
fail("boot_node failed for some reason :(\n");
if (!finalize_init_kernel_on_secondary_core()) {
fail("finalize_init_kernel_on_secondary_core failed for some reason :(\n");
}

clock_sync_test();

ksNumCPUs++;
__atomic_thread_fence(__ATOMIC_RELEASE);

/* grab BKL before leaving the kernel */
NODE_LOCK_SYS;

init_core_state(SchedulerAction_ChooseNewThread);
schedule();
activateThread();
}

#endif /* ENABLE_SMP_SUPPORT */
69 changes: 67 additions & 2 deletions src/kernel/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ struct {
time_t t_primary;
} clock_sync_info[CONFIG_MAX_NUM_NODES - 1];

BOOT_CODE void clock_sync_test(void)
BOOT_CODE static void clock_sync_test(void)
{
/* This must be called on secondary cores only. */
word_t core_idx = getCurrentCPUIndex();
Expand All @@ -595,7 +595,7 @@ BOOT_CODE void clock_sync_test(void)
clock_sync_info[core_idx - 1].t_primary = t_primary;
}

BOOT_CODE void clock_sync_test_evaluation(void)
BOOT_CODE static void clock_sync_test_evaluation(void)
{
bool_t clock_sync_test_passed = true;
ticks_t margin = usToTicks(1) + getTimerPrecision();
Expand Down Expand Up @@ -1104,3 +1104,68 @@ BOOT_CODE bool_t init_freemem(word_t n_available, const p_region_t *available,
"objects, need size/alignment of 2^%"SEL4_PRIu_word"\n", max);
return false;
}

static BOOT_CODE bool_t run_kernel(void)
{
#ifdef CONFIG_KERNEL_MCS
/* Ensure the most recent timestamp is used. */
NODE_STATE(ksCurTime) = getCurrentTime();
#endif
schedule();
activateThread();
return true;
}

BOOT_CODE bool_t finalize_init_kernel()
{
SMP_COND_STATEMENT(clh_lock_init());
/* grab the BKL before releasing the secondary cores, so they cannot
* overtake the primary core
*/
NODE_LOCK_SYS;
SMP_CLOCK_SYNC_TEST_UPDATE_TIME();
SMP_COND_STATEMENT(release_secondary_cores());
#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
clock_sync_test_evaluation();
#endif
printf("Booting all finished, dropped to user space\n");
return run_kernel();
}

#ifdef ENABLE_SMP_SUPPORT

BOOT_CODE bool_t finalize_init_kernel_on_secondary_core(void)
{

#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
clock_sync_test();
#endif

/* The primary core spins waiting for this value to increase. Ensure the
* values is also visible in the primary core. */
ksNumCPUs++;
__atomic_thread_fence(__ATOMIC_RELEASE);

/* Now there can be concurrency, as other secondary cores are also starting
* up. Everything that affects global data should only be done with the
* BLK held.
*/

init_core_state(SchedulerAction_ResumeCurrentThread);


#ifdef CONFIG_ARCH_RISCV
/* ToDo: Is this really needed? Should this be generic? */
ifence_local();
#endif
/* The primary core holds the BKL until is has finished booting, Grabbing
* the BKL here ensure secondary cores will not drop to userland before
* the primary core did this. However, there is a change that userland my
* issues a kernel call that grabs the BLK again before a secondary cores
* finished booting.
*/
NODE_LOCK_SYS;
return run_kernel();
}

#endif /* ENABLE_SMP_SUPPORT */

0 comments on commit 1c5cb58

Please sign in to comment.