/* * Copyright (c) 2026, Chloe M. * Provided under the BSD-3 clause. * * Description: Local APIC driver * Author: Chloe M. */ #include #include #include #include #include #include #include #include #include #include /* * Trace only on the bootstrap processor but not on any others * to avoid log spam... */ #define DTRACE_BSP(Fmt, ...) do { \ ULONG ApicBase; \ \ ApicBase = MdRdmsr(IA32_APIC_BASE_MSR); \ if (ISSET(ApicBase, BIT(8))) { \ TRACE("[ LAPIC ]: " Fmt, ##__VA_ARGS__); \ } \ } while (0); /* * Returns true if the Local APIC unit is supported on the * current processor. */ static BOOLEAN LapicIsSupported(VOID) { ULONG Edx, Unused; CPUID(1, Unused, Unused, Unused, Edx); return ISSET(Edx, BIT(9)) != 0; } /* * Returns true if the CPU can operate its Local APIC unit * in the newer x2APIC mode. */ static BOOLEAN LapicHasX2Apic(VOID) { ULONG Ecx, Unused; CPUID(1, Unused, Unused, Ecx, Unused); return ISSET(Ecx, BIT(21)) != 0; } /* * Enable the Local APIC unit */ static VOID LapicEnable(VOID) { UQUAD ApicBase; /* Hardware enable the Local APIC unit */ ApicBase = MdRdmsr(IA32_APIC_BASE_MSR); ApicBase |= LAPIC_HW_ENABLE; MdWrmsr(IA32_APIC_BASE_MSR, ApicBase); } VOID MdLapicInit(KPCR *Kpcr) { ACPI_MADT *Madt; MCB *Mcb; if (Kpcr == NULL) { KeKnot( KNOT_MISC, "lapic: failed to initialize lapic driver\n" ); } if (!LapicIsSupported()) { KeKnot( KNOT_MISSING_HARDWARE, "lapic: local apic not supported\n" ); } /* Obtain the ACPI MADT table */ Madt = AcpiQuery("APIC"); if (Madt == NULL) { KeKnot(KNOT_MISC, "lapic: could not obtain MADT\n"); } Mcb = &Kpcr->Mcb; Mcb->LapicBase = PMA_TO_VMA((UPTR)Madt->LapicAddr); Mcb->HasX2Apic = LapicHasX2Apic(); /* Enable the Local APIC */ LapicEnable(); }