/* * Copyright (c) 2026, Chloe M. * Provided under the BSD-3 clause. * * Description: Multi-processing * Author: Chloe M. */ #include #include #include #include #include #include #include #include #include /* Bring up region */ #define BUA_BASE 0x9000 #define BUA_LENGTH PAGESIZE /* Max processors to bootstrap */ #define CPU_MAX 64 #define DTRACE(Fmt, ...) \ TRACE("[ MP ]: " Fmt, ##__VA_ARGS__) /* Number of processor cores */ static USHORT CoreCount = 0; /* * The multiprocessor trampoline should fit within a single * page and be no larger than such. */ ALIGN(8) SECTION(".mp_trampoline") static UCHAR MpTrampoline[BUA_LENGTH]; /* * Bootstrap a single core * * @LocalApic: Local APIC descriptor of core to bootstrap * * TODO: This is a stub */ static VOID BootstrapCore(ACPI_LOCAL_APIC *LocalApic) { ULONG SelfId; if (LocalApic == NULL) { return; } /* Let's not shoot ourselves in the face */ SelfId = MdLapicId(); if (LocalApic->ApicId == SelfId) { return; } ++CoreCount; } static VOID MpBootstrap(VOID) { ACPI_MADT *Madt; UCHAR *Ptr, *EndPtr; ACPI_APIC_HEADER *Header; ACPI_LOCAL_APIC *LocalApic; Madt = AcpiQuery("APIC"); if (Madt == NULL) { KeBugCheck( BUGCHECK_MISC, "unable to detect ACPI MADT table\n" ); } Ptr = PTR_OFFSET(Madt, sizeof(ACPI_MADT)); EndPtr = PTR_OFFSET(Ptr, Madt->Header.Length); /* Iterate every interrupt controller entry */ while (Ptr < EndPtr) { Header = (ACPI_APIC_HEADER *)Ptr; switch (Header->Type) { case APIC_TYPE_LOCAL_APIC: LocalApic = (ACPI_LOCAL_APIC *)Header; BootstrapCore(LocalApic); break; } Ptr = PTR_OFFSET(Ptr, Header->Length); } DTRACE("detected %d processor core(s)\n", CoreCount); } VOID HalMpBootstrap(VOID) { MMU_VAS Vas; MM_RANGE TrampolineRange; PT_STATUS Status; VOID *BuaDest; /* Map the BUA page */ HalMmuReadVas(&Vas); TrampolineRange.VirtualBase = BUA_BASE; TrampolineRange.PhysicalBase = BUA_BASE; TrampolineRange.Length = BUA_LENGTH; Status = MmMapRange( &Vas, &TrampolineRange, PAGE_READ | PAGE_WRITE | PAGE_EXEC, PAGESIZE_4K ); if (PT_ERROR(Status)) { KeBugCheck( BUGCHECK_MISC, "failed to map mp bringup area\n" ); } /* Copy trampoline to the BUA page */ BuaDest = (VOID *)BUA_BASE; RtlMemCpy(BuaDest, MpTrampoline, BUA_LENGTH); /* Start up the APs */ MpBootstrap(); }