diff --git a/blob/fw_common.S b/blob/fw_common.S index db0f7f7..a2685cf 100644 --- a/blob/fw_common.S +++ b/blob/fw_common.S @@ -122,7 +122,10 @@ _start_warm: csrw mie, zero csrw mip, zero - /* HART ID should be within expected limit */ + /* set MSIE bit to receive IPI */ + li a2, MIP_MSIP + csrw mie, a2 + /* HART ID should be withing expected limit */ csrr a6, mhartid li a5, PLAT_HART_COUNT bge a6, a5, _start_hang diff --git a/include/sbi/sbi_hart.h b/include/sbi/sbi_hart.h index 38032ed..c77ffd2 100644 --- a/include/sbi/sbi_hart.h +++ b/include/sbi/sbi_hart.h @@ -36,6 +36,6 @@ struct sbi_scratch *sbi_hart_id_to_scratch(struct sbi_scratch *scratch, void sbi_hart_wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid); -void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch); +void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid); #endif diff --git a/lib/sbi_hart.c b/lib/sbi_hart.c index db833c7..30f4f03 100644 --- a/lib/sbi_hart.c +++ b/lib/sbi_hart.c @@ -264,31 +264,34 @@ struct sbi_scratch *sbi_hart_id_to_scratch(struct sbi_scratch *scratch, } #define NO_HOTPLUG_BITMAP_SIZE __riscv_xlen -static spinlock_t coldboot_holding_pen_lock = SPIN_LOCK_INITIALIZER; -static volatile unsigned long coldboot_holding_pen = 0; void sbi_hart_wait_for_coldboot(struct sbi_scratch *scratch, u32 hartid) { - unsigned long done; + unsigned long mipval; struct sbi_platform *plat = sbi_platform_ptr(scratch); + sbi_printf("%s: In hartid = [%d]\n", __func__, hartid); if ((sbi_platform_hart_count(plat) <= hartid) || (NO_HOTPLUG_BITMAP_SIZE <= hartid)) sbi_hart_hang(); + do { + wfi(); + mipval = csr_read(mip); + /* Make sure the hart woke because of ipi */ + } while (!(mipval && MIP_MSIP) ); - while (1) { - spin_lock(&coldboot_holding_pen_lock); - done = coldboot_holding_pen; - spin_unlock(&coldboot_holding_pen_lock); - if (done) - break; - cpu_relax(); - } + csr_clear(mip, MIP_MSIP); } -void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch) +void sbi_hart_wake_coldboot_harts(struct sbi_scratch *scratch, u32 hartid) { - spin_lock(&coldboot_holding_pen_lock); - coldboot_holding_pen = 1; - spin_unlock(&coldboot_holding_pen_lock); + struct sbi_platform *plat = sbi_platform_ptr(scratch); + int max_hart = sbi_platform_hart_count(plat); + + for(int i = 0; i < max_hart ; i++) { + /* send an IPI to every other hart */ + if (i != hartid) + sbi_platform_ipi_inject(plat, i, hartid); + } + } diff --git a/lib/sbi_init.c b/lib/sbi_init.c index 52c63fa..82384b3 100644 --- a/lib/sbi_init.c +++ b/lib/sbi_init.c @@ -96,7 +96,7 @@ static void __attribute__((noreturn)) init_coldboot(struct sbi_scratch *scratch, sbi_hart_mark_available(hartid); if (!sbi_platform_has_hart_hotplug(plat)) - sbi_hart_wake_coldboot_harts(scratch); + sbi_hart_wake_coldboot_harts(scratch, hartid); sbi_hart_boot_next(hartid, scratch->next_arg1, scratch->next_addr, scratch->next_mode);