MCS, SMP: Add clock synchronisation test

Because ksCurTime is compared cross-node now, time across
nodes must be the same. Check this once during boot.

Replace __atomic_signal_fence with the more correct
__atomic_thread_fence, as ksNumCPUs will be changed
cross-node.

Signed-off-by: Indan Zupancic <Indan.Zupancic@mep-info.com>
This commit is contained in:
Indan Zupancic 2022-05-31 12:25:30 +02:00 committed by Gerwin Klein
parent 04c096128b
commit 2a8c9683f3
5 changed files with 51 additions and 5 deletions

View file

@ -135,3 +135,14 @@ 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);
#if defined(CONFIG_DEBUG_BUILD) && defined(ENABLE_SMP_SUPPORT) && defined(CONFIG_KERNEL_MCS)
/* Test whether clocks are synchronised across nodes */
#define ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
#endif
#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
BOOT_CODE void clock_sync_test(void);
#else
#define clock_sync_test()
#endif

View file

@ -274,6 +274,7 @@ BOOT_CODE static bool_t try_init_kernel_secondary_core(void)
#endif /* CONFIG_ARM_HYPERVISOR_SUPPORT */
NODE_LOCK_SYS;
clock_sync_test();
ksNumCPUs++;
init_core_state(SchedulerAction_ResumeCurrentThread);
@ -303,8 +304,11 @@ BOOT_CODE static void release_secondary_cpus(void)
/* Wait until all the secondary cores are done initialising */
while (ksNumCPUs != CONFIG_MAX_NUM_NODES) {
/* perform a memory release+acquire to get new values of ksNumCPUs */
__atomic_signal_fence(__ATOMIC_ACQ_REL);
#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
NODE_STATE(ksCurTime) = getCurrentTime();
#endif
/* perform a memory acquire to get new values of ksNumCPUs, release for ksCurTime */
__atomic_thread_fence(__ATOMIC_ACQ_REL);
}
}
#endif /* ENABLE_SMP_SUPPORT */

View file

@ -159,6 +159,7 @@ BOOT_CODE static bool_t try_init_kernel_secondary_core(word_t hart_id, word_t co
init_cpu();
NODE_LOCK_SYS;
clock_sync_test();
ksNumCPUs++;
init_core_state(SchedulerAction_ResumeCurrentThread);
ifence_local();
@ -171,11 +172,14 @@ BOOT_CODE static void release_secondary_cores(void)
fence_w_r();
while (ksNumCPUs != CONFIG_MAX_NUM_NODES) {
__atomic_signal_fence(__ATOMIC_ACQ_REL);
#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
NODE_STATE(ksCurTime) = getCurrentTime();
#endif
__atomic_thread_fence(__ATOMIC_ACQ_REL);
}
}
#endif /* ENABLE_SMP_SUPPORT */
#endif
/* Main kernel initialisation function. */
static BOOT_CODE bool_t try_init_kernel(

View file

@ -6,6 +6,7 @@
#include <config.h>
#include <arch/machine.h>
#include <arch/machine/timer.h>
#include <arch/kernel/boot_sys.h>
#include <arch/kernel/smp_sys.h>
#include <smp/lock.h>
@ -64,7 +65,12 @@ BOOT_CODE void start_boot_aps(void)
start_cpu(boot_state.cpus[current_ap_index], BOOT_NODE_PADDR);
/* wait for current AP to boot up */
while (smp_aps_index == current_ap_index);
while (smp_aps_index == current_ap_index) {
#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
NODE_STATE(ksCurTime) = getCurrentTime();
__atomic_thread_fence(__ATOMIC_ACQ_REL);
#endif
}
}
}
@ -126,6 +132,7 @@ VISIBLE void boot_node(void)
fail("boot_node failed for some reason :(\n");
}
clock_sync_test();
smp_aps_index++;
/* grab BKL before leaving the kernel */

View file

@ -553,6 +553,26 @@ BOOT_CODE tcb_t *create_initial_thread(cap_t root_cnode_cap, cap_t it_pd_cap, vp
return tcb;
}
#ifdef ENABLE_SMP_CLOCK_SYNC_TEST_ON_BOOT
BOOT_CODE void clock_sync_test(void)
{
ticks_t t, t0;
ticks_t margin = usToTicks(1) + getTimerPrecision();
assert(getCurrentCPUIndex() != 0);
t = NODE_STATE_ON_CORE(ksCurTime, 0);
do {
/* perform a memory acquire to get new values of ksCurTime */
__atomic_thread_fence(__ATOMIC_ACQUIRE);
t0 = NODE_STATE_ON_CORE(ksCurTime, 0);
} while (t0 == t);
t = getCurrentTime();
printf("clock_sync_test[%d]: t0 = %"PRIu64", t = %"PRIu64", td = %"PRIi64"\n",
(int)getCurrentCPUIndex(), t0, t, t - t0);
assert(t0 <= margin + t && t <= t0 + margin);
}
#endif
BOOT_CODE void init_core_state(tcb_t *scheduler_action)
{
#ifdef CONFIG_HAVE_FPU