#include "kapi/cpu.hpp" #include "kapi/acpi.hpp" #include "kapi/devices.hpp" #include "kapi/devices/cpu.hpp" #include "kapi/memory.hpp" #include "kapi/system.hpp" #include "arch/cpu/initialization.hpp" #include "arch/devices/local_apic.hpp" #include #include #include #include #include #include namespace kapi::cpu { namespace { constexpr auto candidate_flags = ::acpi::processor_local_apic::flags::processor_enabled // | ::acpi::processor_local_apic::flags::online_capable; } 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 discover_topology() -> bool { auto static const cpu_major = kapi::devices::allocate_major_number(); auto static const core_major = kapi::devices::allocate_major_number(); auto static const interrupt_controller_major = kapi::devices::allocate_major_number(); auto madt = kapi::acpi::get_table<::acpi::madt_table_signature>(); if (!madt) { kstd::println("[x86_64:PLT] Failed to find ACPI APIC table"); return false; } auto lapic_entries = *madt | std::views::filter([](auto const & entry) { return entry.type() == ::acpi::madt_entry::types::processor_local_apic; }) | std::views::transform([](auto const & entry) { return static_cast<::acpi::processor_local_apic const &>(entry); }) | std::views::filter([](auto const & entry) { return static_cast(entry.active_flags() & candidate_flags); }); auto bsp_found = false; auto core_count = 0uz; auto local_apic_address = memory::physical_address{madt->local_interrupt_controller_address()}; auto cpu_bus = kstd::make_unique(cpu_major, 0); for (auto const & apic : lapic_entries) { auto is_bsp = !bsp_found; bsp_found = true; auto core = kstd::make_unique(core_major, core_count, apic.processor_id(), is_bsp); core->add_child(kstd::make_unique(interrupt_controller_major, core_count, apic.apic_id(), local_apic_address, is_bsp)); cpu_bus->add_child(std::move(core)); ++core_count; } devices::get_root_bus().add_child(std::move(cpu_bus)); kstd::println("[x86_64:PLT] Found {} CPU cores", core_count); return core_count > 0; } } // namespace kapi::cpu