/* * Apic.hpp * Local APIC (Advanced Programmable Interrupt Controller) * Copyright (c) 2025 Daniel Hammer */ #pragma once #include namespace Hal { namespace LocalApic { // Local APIC register offsets constexpr uint32_t REG_ID = 0x020; constexpr uint32_t REG_VERSION = 0x030; constexpr uint32_t REG_TPR = 0x080; constexpr uint32_t REG_EOI = 0x0B0; constexpr uint32_t REG_SPURIOUS = 0x0F0; constexpr uint32_t REG_ICR_LOW = 0x300; constexpr uint32_t REG_ICR_HIGH = 0x310; constexpr uint32_t REG_TIMER_LVT = 0x320; constexpr uint32_t REG_LINT0_LVT = 0x350; constexpr uint32_t REG_LINT1_LVT = 0x360; constexpr uint32_t REG_ERROR_LVT = 0x370; constexpr uint32_t REG_TIMER_INITIAL = 0x380; constexpr uint32_t REG_TIMER_CURRENT = 0x390; constexpr uint32_t REG_TIMER_DIVIDE = 0x3E0; // Spurious vector number constexpr uint8_t SPURIOUS_VECTOR = 0xFF; // MSR for APIC base constexpr uint32_t MSR_APIC_BASE = 0x1B; void Initialize(uint64_t apicBasePhys); // Initialize the Local APIC on an AP. // Uses the same MMIO base as the BSP (each CPU's APIC is at the same // physical address but routes to its own hardware). void InitializeAP(); // Re-enable the Local APIC after S3 resume. // The MMIO mapping and base address survive (they're in page tables / RAM). // Only the SVR and TPR hardware registers need reprogramming. void Reinitialize(); void SendEOI(); void SendFixedIpi(uint32_t apicId, uint8_t vector); uint32_t GetId(); uint32_t ReadRegister(uint32_t reg); void WriteRegister(uint32_t reg, uint32_t value); }; };