/* * Copyright (c) 2026, Chloe M. * Provided under the BSD-3 clause. * * Description: MP bringup * Author: Chloe M. */ #include #include #include #include #include #include #include #include /* Limit used to prevent log spam */ #define MP_LOG_CAP 4 #define MP_DEBUG 1 /* Local APIC flags */ #define LAPIC_ONLINE_CAPABLE BIT(1) #define DTRACE(Fmt, ...) \ TRACE("[ MP ]: " Fmt, ##__VA_ARGS__) #if MP_DEBUG #define MP_DTRACE(...) \ if (ProcessorsUp < MP_LOG_CAP) { \ DTRACE(__VA_ARGS__); \ } #else #define MP_DTRACE(...) (VOID)0 #endif /* MP_DEBUG */ static USIZE ProcessorsUp = 0; /* * Bring up a single application processor * * @Lapic: Local APIC of processor to bring up */ static VOID ApKick(ACPI_LOCAL_APIC *Lapic) { UQUAD UsecCur, UsecGoal; ULONG BspId; if (Lapic == NULL) { return; } /* Don't nuke ourselves */ BspId = MdLapicId(); if (Lapic->ApicId == BspId) { return; } /* * Some processor entries may not be "online capable", if we * encounter such entries, ignore it. */ if (!ISSET(Lapic->Flags, LAPIC_ONLINE_CAPABLE)) { return; } /* Send an INIT IPI to the processor */ MdLapicSendIpi( 0, Lapic->ApicId, 0, IPI_XND_NONE, IPI_DELMOD_INIT ); /* MP spec states to wait 10 usec */ UsecCur = MdHpetTimeUsec(); UsecGoal = UsecCur + (USEC_PER_MSEC * 10); while (MdHpetTimeUsec() < UsecGoal) { HalCpuSpinWait(); } DTRACE("sent init to apic%d\n", Lapic->ApicId); ++ProcessorsUp; } VOID HalMpBringUp(VOID) { ACPI_LOCAL_APIC *LocalApic; USIZE Idx; /* Bring up each AP */ for (Idx = 0;; ++Idx) { LocalApic = MdLapicByIndex(Idx); if (LocalApic == NULL) { break; } ApKick(LocalApic); } }