/* * ApicInit.cpp * APIC subsystem initialization * Copyright (c) 2025 Daniel Hammer */ #include "ApicInit.hpp" #include "Pic.hpp" #include "Apic.hpp" #include "IoApic.hpp" #include "Interrupts.hpp" #include #include #include #include #include #include using namespace Kt; namespace Hal { static int g_detectedCpuCount = 0; int GetDetectedCpuCount() { return g_detectedCpuCount; } void ApicInitialize(ACPI::CommonSDTHeader* xsdt) { KernelLogStream(INFO, "APIC") << "Initializing APIC subsystem"; // Step 1: Parse MADT MADT::ParsedMADT madt{}; if (!MADT::Parse(xsdt, madt)) { KernelLogStream(ERROR, "APIC") << "Failed to parse MADT, cannot initialize APIC"; return; } g_detectedCpuCount = madt.LocalApicCount; if (madt.IoApicAddress == 0) { KernelLogStream(ERROR, "APIC") << "No IOAPIC found in MADT"; return; } // Step 2: Map APIC MMIO regions into kernel page tables // The HHDM only covers physical RAM; MMIO regions need explicit mapping. if (Memory::VMM::g_paging) { Memory::VMM::g_paging->MapMMIO(madt.LocalApicAddress, Memory::HHDM(madt.LocalApicAddress)); KernelLogStream(DEBUG, "APIC") << "Mapped Local APIC MMIO at phys " << base::hex << madt.LocalApicAddress; Memory::VMM::g_paging->MapMMIO(madt.IoApicAddress, Memory::HHDM(madt.IoApicAddress)); KernelLogStream(DEBUG, "APIC") << "Mapped IOAPIC MMIO at phys " << base::hex << madt.IoApicAddress; } // Step 3: Disable legacy 8259 PIC DisableLegacyPic(); // Step 4: Install IRQ stubs into IDT InitializeIrqHandlers(); IDTReload(); // Step 5: Initialize Local APIC LocalApic::Initialize(madt.LocalApicAddress); // Step 6: Initialize IOAPIC IoApic::Initialize(madt.IoApicAddress, madt.IoApicGsiBase, madt.Overrides, madt.OverrideCount); // Step 7: Route keyboard (IRQ1) and mouse (IRQ12) to BSP uint8_t bspApicId = (uint8_t)LocalApic::GetId(); IoApic::RouteIrq(Arch::IRQ_KEYBOARD, IRQ_VECTOR_BASE + Arch::IRQ_KEYBOARD, bspApicId); IoApic::RouteIrq(Arch::IRQ_MOUSE, IRQ_VECTOR_BASE + Arch::IRQ_MOUSE, bspApicId); // Note: sti is NOT called here. The caller (Main.cpp) enables // interrupts after setting up per-CPU GS base for SMP/SWAPGS. KernelLogStream(OK, "APIC") << "APIC subsystem initialized"; } };