#include "kapi/cpu.hpp" #include "kapi/system.hpp" #include "arch/cpu/initialization.hpp" #include #include #include #include #include namespace kapi::cpu { namespace { constexpr auto irq_offset = 32uz; auto constinit interrupt_handlers = std::array, 256 - irq_offset>{}; } // namespace auto init() -> void { auto static constinit is_initialized = std::atomic_flag{}; if (is_initialized.test_and_set()) { system::panic("[x86_64] CPU has already been initialized."); } arch::cpu::initialize_descriptors(); arch::cpu::initialize_legacy_interrupts(); } auto halt() -> void { asm volatile("1: hlt\njmp 1b"); __builtin_unreachable(); } auto enable_interrupts() -> void { asm volatile("sti"); } auto disable_interrupts() -> void { asm volatile("cli"); } auto register_interrupt_handler(std::uint32_t irq_number, interrupt_handler & handler) -> void { if (irq_number < irq_offset) { system::panic("[x86_64:CPU] IRQ number must be in range [32, 255]."); } interrupt_handlers[irq_number - irq_offset].push_back(&handler); } auto unregister_interrupt_handler(std::uint32_t irq_number, [[maybe_unused]] interrupt_handler & handler) -> void { if (irq_number < irq_offset) { system::panic("[x86_64:CPU] IRQ number must be in range [32, 255]."); } kstd::println("[x86_64:CPU] TODO: support erasure from vector."); } auto dispatch_interrupt(std::uint32_t irq_number) -> status { if (irq_number < irq_offset) { return status::unhandled; } for (auto handler : interrupt_handlers[irq_number - irq_offset]) { if (handler && handler->handle_interrupt(irq_number) == status::handled) { return status::handled; } } return status::unhandled; } } // namespace kapi::cpu