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);
}
原文地址:https://www.cnblogs.com/dream397/p/15508985.html