1 /* Copyright 2019 SiFive, Inc */
2 /* SPDX-License-Identifier: Apache-2.0 */
4 #include <metal/machine.h>
5 #include <metal/machine/platform.h>
9 #define METAL_REG(base, offset) (((unsigned long)(base) + (offset)))
10 #define METAL_REGW(base, offset) (__METAL_ACCESS_ONCE((__metal_io_u32 *)METAL_REG((base), (offset))))
11 #define METAL_MSIP(base, hart) (METAL_REGW((base),4*(hart)))
14 * _synchronize_harts() is called by crt0.S to cause harts > 0 to wait for
15 * hart 0 to finish copying the datat section, zeroing the BSS, and running
16 * the libc contstructors.
18 void _synchronize_harts() {
19 #if __METAL_DT_MAX_HARTS > 1
21 int hart = metal_cpu_get_current_hartid();
22 uintptr_t msip_base = 0;
24 /* Get the base address of the MSIP registers */
25 #ifdef __METAL_DT_RISCV_CLINT0_HANDLE
26 msip_base = __metal_driver_sifive_clint0_control_base(__METAL_DT_RISCV_CLINT0_HANDLE);
27 msip_base += METAL_RISCV_CLINT0_MSIP_BASE;
28 #elif __METAL_DT_RISCV_CLIC0_HANDLE
29 msip_base = __metal_driver_sifive_clic0_control_base(__METAL_DT_RISCV_CLIC0_HANDLE);
30 msip_base += METAL_RISCV_CLIC0_MSIP_BASE;
32 #warning No handle for CLINT or CLIC found, harts may be unsynchronized after init!
35 /* Disable machine interrupts as a precaution */
36 __asm__ volatile("csrc mstatus, %0" :: "r" (METAL_MSTATUS_MIE));
39 /* Hart 0 waits for all harts to set their MSIP bit */
40 for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
41 while (METAL_MSIP(msip_base, i) == 0) ;
44 /* Hart 0 clears everyone's MSIP bit */
45 for (int i = 1 ; i < __METAL_DT_MAX_HARTS; i++) {
46 METAL_MSIP(msip_base, i) = 0;
49 /* Other harts set their MSIP bit to indicate they're ready */
50 METAL_MSIP(msip_base, hart) = 1;
51 __asm__ volatile ("fence w,rw");
53 /* Wait for hart 0 to clear the MSIP bit */
54 while (METAL_MSIP(msip_base, hart) == 1) ;
57 #endif /* __METAL_DT_MAX_HARTS > 1 */