opensbi smp同步
特权模式(privilege mode)
/* * Only the HART supporting privilege mode specified in the * scratch->next_mode should be allowed to become the coldboot * HART because the coldboot HART will be directly jumping to * the next booting stage. * * We use a lottery mechanism to select coldboot HART among * HARTs which satisfy above condition. */ if (next_mode_supported && atomic_xchg(&coldboot_lottery, 1) == 0) coldboot = TRUE; if (coldboot) init_coldboot(scratch, hartid); else init_warmboot(scratch, hartid);
wait_for_coldboot wake_coldboot_harts
static void wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid) { unsigned long saved_mie, cmip; /* Save MIE CSR */ saved_mie = csr_read(CSR_MIE); /* Set MSIE bit to receive IPI */ csr_set(CSR_MIE, MIP_MSIP); /* Acquire coldboot lock */ spin_lock(&coldboot_lock); /* Mark current HART as waiting */ sbi_hartmask_set_hart(hartid, &coldboot_wait_hmask); /* Release coldboot lock */ spin_unlock(&coldboot_lock); /* Wait for coldboot to finish using WFI */ while (!__smp_load_acquire(&coldboot_done)) { do { wfi(); cmip = csr_read(CSR_MIP); } while (!(cmip & MIP_MSIP)); }; /* Acquire coldboot lock */ spin_lock(&coldboot_lock); /* Unmark current HART as waiting */ sbi_hartmask_clear_hart(hartid, &coldboot_wait_hmask); /* Release coldboot lock */ spin_unlock(&coldboot_lock); /* Restore MIE CSR */ csr_write(CSR_MIE, saved_mie); /* * The wait for coldboot is common for both warm startup and * warm resume path so clearing IPI here would result in losing * an IPI in warm resume path. * * Also, the sbi_platform_ipi_init() called from sbi_ipi_init() * will automatically clear IPI for current HART. */ } static void wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid) { /* Mark coldboot done */ __smp_store_release(&coldboot_done, 1); /* Acquire coldboot lock */ spin_lock(&coldboot_lock); /* Send an IPI to all HARTs waiting for coldboot */ for (u32 i = 0; i <= sbi_scratch_last_hartid(); i++) { if ((i != hartid) && sbi_hartmask_test_hart(i, &coldboot_wait_hmask)) sbi_ipi_raw_send(i); } /* Release coldboot lock */ spin_unlock(&coldboot_lock); }