0265810d9a
Signed-off-by: Chloe M <chloe@mensia.org>
134 lines
2.7 KiB
C
134 lines
2.7 KiB
C
/*
|
|
* Copyright (c) 2026, Chloe M.
|
|
* Provided under the BSD-3 clause.
|
|
*
|
|
* Description: Multi-processing
|
|
* Author: Chloe M.
|
|
*/
|
|
|
|
#include <ptdef.h>
|
|
#include <hal/page.h>
|
|
#include <ex/trace.h>
|
|
#include <drivers/acpi/acpi.h>
|
|
#include <drivers/acpi/tables.h>
|
|
#include <ke/bugcheck.h>
|
|
#include <mm/vm.h>
|
|
#include <machine/lapic.h>
|
|
#include <string.h>
|
|
|
|
/* 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();
|
|
}
|