From 044083a8d5b3fe94c4b9f9b066f25c81915fd4c1 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Tue, 28 Jul 2026 14:20:41 +0200 Subject: x86_64: move cpu related drivers --- arch/x86_64/arch/drivers/cpu/lapic.cpp | 167 +++++++++++++++++++++++++++++++++ arch/x86_64/arch/drivers/cpu/lapic.hpp | 45 +++++++++ arch/x86_64/arch/drivers/init.cpp | 4 +- arch/x86_64/arch/drivers/lapic.cpp | 167 --------------------------------- arch/x86_64/arch/drivers/lapic.hpp | 45 --------- 5 files changed, 214 insertions(+), 214 deletions(-) create mode 100644 arch/x86_64/arch/drivers/cpu/lapic.cpp create mode 100644 arch/x86_64/arch/drivers/cpu/lapic.hpp delete mode 100644 arch/x86_64/arch/drivers/lapic.cpp delete mode 100644 arch/x86_64/arch/drivers/lapic.hpp (limited to 'arch') diff --git a/arch/x86_64/arch/drivers/cpu/lapic.cpp b/arch/x86_64/arch/drivers/cpu/lapic.cpp new file mode 100644 index 00000000..2f74abc4 --- /dev/null +++ b/arch/x86_64/arch/drivers/cpu/lapic.cpp @@ -0,0 +1,167 @@ +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace arch::drivers::cpu +{ + + using namespace kstd::units_literals; + + namespace + { + constexpr auto lapic_enable_bit = 0x100u; + constexpr auto spurious_interrupt_vector = 0xFFu; + + constexpr auto offset_of_version = 0u; + constexpr auto offset_of_max_lvt_entry = 16u; + constexpr auto offset_of_eoi_suppression = 24u; + } // namespace + + enum struct lapic::registers : std::ptrdiff_t + { + id = 0x020, + version = 0x030, + task_priority = 0x080, + arbitration_priority = 0x090, + processor_priority = 0x0a0, + eoi = 0x0b0, + remote_read = 0x0c0, + logical_destination = 0x0d0, + destination_format = 0x0e0, + spurious_interrupt_vector = 0x0f0, + in_service_0 = 0x100, + in_service_1 = 0x110, + in_service_2 = 0x120, + in_service_3 = 0x130, + in_service_4 = 0x140, + in_service_5 = 0x150, + in_service_6 = 0x160, + in_service_7 = 0x170, + trigger_mode_0 = 0x180, + trigger_mode_1 = 0x190, + trigger_mode_2 = 0x1a0, + trigger_mode_3 = 0x1b0, + trigger_mode_4 = 0x1c0, + trigger_mode_5 = 0x1d0, + trigger_mode_6 = 0x1e0, + trigger_mode_7 = 0x1f0, + interrupt_request_0 = 0x200, + interrupt_request_1 = 0x210, + interrupt_request_2 = 0x220, + interrupt_request_3 = 0x230, + interrupt_request_4 = 0x240, + interrupt_request_5 = 0x250, + interrupt_request_6 = 0x260, + interrupt_request_7 = 0x270, + error_status = 0x280, + lvt_corrected_machine_check_interrupt = 0x2f0, + interrupt_command_0 = 0x300, + interrupt_command_1 = 0x310, + lvt_timer = 0x320, + lvt_thermal_sensors = 0x330, + lvt_performance_monitoring_counters = 0x340, + lvt_local_interrupt_0 = 0x350, + lvt_local_interrupt_1 = 0x360, + lvt_error = 0x370, + initial_count = 0x380, + current_count = 0x390, + divide_configuration = 0x3e0, + }; + + auto lapic::probe(kapi::devices::device & device) -> kstd::result + { + auto * signature = device.facet(); + if (!signature) + { + return kstd::failure(make_error_code(kstd::errc::invalid_argument)); + } + + auto mmio = device.request_resource(); + if (!mmio) + { + return kstd::failure(mmio.error()); + } + + auto guard = kstd::lock_guard{m_lock}; + + if (!m_is_mapped) + { + auto const page_count = (mmio->size + kapi::memory::page_size - 1_B) / kapi::memory::page_size; + m_mapped_region = kapi::memory::allocate_mmio_region(page_count); + + if (!kapi::memory::map_mmio_region(m_mapped_region, kapi::memory::physical_address{mmio->start}, + kapi::memory::page_mapper::flags::writable)) + { + kstd::println(kstd::print_sink::stderr, "[x86_64:DRV] LAPIC {} MMIO mapping failed!", signature->hardware_id()); + return kstd::failure(make_error_code(kstd::errc::io_error)); + } + + m_is_mapped = true; + } + + if (signature->is_bsp()) + { + auto raw_version = read_register(registers::version); + auto version = (raw_version >> offset_of_version) & 0xff; + auto highest_lvt_entry_index = (raw_version >> offset_of_max_lvt_entry) & 0xff; + auto supports_eoi_broadcast_suppression = bool((raw_version >> offset_of_eoi_suppression) & 0x1); + + write_register(registers::spurious_interrupt_vector, lapic_enable_bit | spurious_interrupt_vector); + + kstd::println("[x86_64:DRV] LAPIC initialized. version: {#x} | max_lvt_entry: {} | eoi_suppression: {:s}", + version, highest_lvt_entry_index, supports_eoi_broadcast_suppression); + } + else + { + kstd::println("[x86_64:DRV] LAPIC {} is not on the BSP, deferring initialization.", signature->hardware_id()); + } + + return kstd::success(); + } + + auto lapic::unbind(kapi::devices::device &) -> void {} + + auto lapic::name() const noexcept -> std::string_view + { + return "Generic x86 Local APIC"; + } + + auto lapic::read_register(registers id) const -> std::uint32_t + { + auto reg = static_cast(m_mapped_region.first + std::to_underlying(id)); + return *reg; + } + + auto lapic::write_register(registers id, std::uint32_t value) -> void + { + auto reg = static_cast(m_mapped_region.first + std::to_underlying(id)); + *reg = value; + } + + auto lapic::query_facet(kapi::capabilities::facet_id facet) -> void * + { + if (facet == arch::bus::lapic_claim::id) + { + return static_cast(this); + } + + return kapi::devices::driver::query_facet(facet); + } + +} // namespace arch::drivers diff --git a/arch/x86_64/arch/drivers/cpu/lapic.hpp b/arch/x86_64/arch/drivers/cpu/lapic.hpp new file mode 100644 index 00000000..f2a8a4e9 --- /dev/null +++ b/arch/x86_64/arch/drivers/cpu/lapic.hpp @@ -0,0 +1,45 @@ +#ifndef TEACHOS_ARCH_X86_64_DRIVERS_LAPIC_HPP +#define TEACHOS_ARCH_X86_64_DRIVERS_LAPIC_HPP + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +namespace arch::drivers::cpu +{ + + //! The driver for a core-local interrupt controller (local APIC). + struct lapic final : kapi::devices::driver, arch::bus::lapic_claim + { + [[nodiscard]] auto probe(kapi::devices::device & device) -> kstd::result override; + + auto unbind(kapi::devices::device & device) -> void override; + + [[nodiscard]] auto name() const noexcept -> std::string_view override; + + protected: + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; + + private: + enum struct registers : std::ptrdiff_t; + + [[nodiscard]] auto read_register(registers id) const -> std::uint32_t; + auto write_register(registers id, std::uint32_t value) -> void; + + mutable kapi::tracked_mutex m_lock{}; + kapi::memory::mmio_region m_mapped_region{}; + bool m_is_mapped{}; + }; + +} // namespace arch::drivers + +#endif diff --git a/arch/x86_64/arch/drivers/init.cpp b/arch/x86_64/arch/drivers/init.cpp index 0027336b..19f45829 100644 --- a/arch/x86_64/arch/drivers/init.cpp +++ b/arch/x86_64/arch/drivers/init.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include #include @@ -23,7 +23,7 @@ namespace arch::drivers auto & driver_registry = kapi::devices::driver_registry::get(); driver_registry.add(kstd::make_shared(pit_frequency_in_hz)); - driver_registry.add(kstd::make_shared()); + driver_registry.add(kstd::make_shared()); } } // namespace arch::drivers diff --git a/arch/x86_64/arch/drivers/lapic.cpp b/arch/x86_64/arch/drivers/lapic.cpp deleted file mode 100644 index 270c04ce..00000000 --- a/arch/x86_64/arch/drivers/lapic.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -namespace arch::drivers -{ - - using namespace kstd::units_literals; - - namespace - { - constexpr auto lapic_enable_bit = 0x100u; - constexpr auto spurious_interrupt_vector = 0xFFu; - - constexpr auto offset_of_version = 0u; - constexpr auto offset_of_max_lvt_entry = 16u; - constexpr auto offset_of_eoi_suppression = 24u; - } // namespace - - enum struct lapic::registers : std::ptrdiff_t - { - id = 0x020, - version = 0x030, - task_priority = 0x080, - arbitration_priority = 0x090, - processor_priority = 0x0a0, - eoi = 0x0b0, - remote_read = 0x0c0, - logical_destination = 0x0d0, - destination_format = 0x0e0, - spurious_interrupt_vector = 0x0f0, - in_service_0 = 0x100, - in_service_1 = 0x110, - in_service_2 = 0x120, - in_service_3 = 0x130, - in_service_4 = 0x140, - in_service_5 = 0x150, - in_service_6 = 0x160, - in_service_7 = 0x170, - trigger_mode_0 = 0x180, - trigger_mode_1 = 0x190, - trigger_mode_2 = 0x1a0, - trigger_mode_3 = 0x1b0, - trigger_mode_4 = 0x1c0, - trigger_mode_5 = 0x1d0, - trigger_mode_6 = 0x1e0, - trigger_mode_7 = 0x1f0, - interrupt_request_0 = 0x200, - interrupt_request_1 = 0x210, - interrupt_request_2 = 0x220, - interrupt_request_3 = 0x230, - interrupt_request_4 = 0x240, - interrupt_request_5 = 0x250, - interrupt_request_6 = 0x260, - interrupt_request_7 = 0x270, - error_status = 0x280, - lvt_corrected_machine_check_interrupt = 0x2f0, - interrupt_command_0 = 0x300, - interrupt_command_1 = 0x310, - lvt_timer = 0x320, - lvt_thermal_sensors = 0x330, - lvt_performance_monitoring_counters = 0x340, - lvt_local_interrupt_0 = 0x350, - lvt_local_interrupt_1 = 0x360, - lvt_error = 0x370, - initial_count = 0x380, - current_count = 0x390, - divide_configuration = 0x3e0, - }; - - auto lapic::probe(kapi::devices::device & device) -> kstd::result - { - auto * signature = device.facet(); - if (!signature) - { - return kstd::failure(make_error_code(kstd::errc::invalid_argument)); - } - - auto mmio = device.request_resource(); - if (!mmio) - { - return kstd::failure(mmio.error()); - } - - auto guard = kstd::lock_guard{m_lock}; - - if (!m_is_mapped) - { - auto const page_count = (mmio->size + kapi::memory::page_size - 1_B) / kapi::memory::page_size; - m_mapped_region = kapi::memory::allocate_mmio_region(page_count); - - if (!kapi::memory::map_mmio_region(m_mapped_region, kapi::memory::physical_address{mmio->start}, - kapi::memory::page_mapper::flags::writable)) - { - kstd::println(kstd::print_sink::stderr, "[x86_64:DRV] LAPIC {} MMIO mapping failed!", signature->hardware_id()); - return kstd::failure(make_error_code(kstd::errc::io_error)); - } - - m_is_mapped = true; - } - - if (signature->is_bsp()) - { - auto raw_version = read_register(registers::version); - auto version = (raw_version >> offset_of_version) & 0xff; - auto highest_lvt_entry_index = (raw_version >> offset_of_max_lvt_entry) & 0xff; - auto supports_eoi_broadcast_suppression = bool((raw_version >> offset_of_eoi_suppression) & 0x1); - - write_register(registers::spurious_interrupt_vector, lapic_enable_bit | spurious_interrupt_vector); - - kstd::println("[x86_64:DRV] LAPIC initialized. version: {#x} | max_lvt_entry: {} | eoi_suppression: {:s}", - version, highest_lvt_entry_index, supports_eoi_broadcast_suppression); - } - else - { - kstd::println("[x86_64:DRV] LAPIC {} is not on the BSP, deferring initialization.", signature->hardware_id()); - } - - return kstd::success(); - } - - auto lapic::unbind(kapi::devices::device &) -> void {} - - auto lapic::name() const noexcept -> std::string_view - { - return "Generic x86 Local APIC"; - } - - auto lapic::read_register(registers id) const -> std::uint32_t - { - auto reg = static_cast(m_mapped_region.first + std::to_underlying(id)); - return *reg; - } - - auto lapic::write_register(registers id, std::uint32_t value) -> void - { - auto reg = static_cast(m_mapped_region.first + std::to_underlying(id)); - *reg = value; - } - - auto lapic::query_facet(kapi::capabilities::facet_id facet) -> void * - { - if (facet == arch::bus::lapic_claim::id) - { - return static_cast(this); - } - - return kapi::devices::driver::query_facet(facet); - } - -} // namespace arch::drivers diff --git a/arch/x86_64/arch/drivers/lapic.hpp b/arch/x86_64/arch/drivers/lapic.hpp deleted file mode 100644 index f9d697f8..00000000 --- a/arch/x86_64/arch/drivers/lapic.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_DRIVERS_LAPIC_HPP -#define TEACHOS_ARCH_X86_64_DRIVERS_LAPIC_HPP - -#include - -#include -#include -#include -#include - -#include - -#include -#include -#include - -namespace arch::drivers -{ - - //! The driver for a core-local interrupt controller (local APIC). - struct lapic final : kapi::devices::driver, arch::bus::lapic_claim - { - [[nodiscard]] auto probe(kapi::devices::device & device) -> kstd::result override; - - auto unbind(kapi::devices::device & device) -> void override; - - [[nodiscard]] auto name() const noexcept -> std::string_view override; - - protected: - auto query_facet(kapi::capabilities::facet_id facet) -> void * override; - - private: - enum struct registers : std::ptrdiff_t; - - [[nodiscard]] auto read_register(registers id) const -> std::uint32_t; - auto write_register(registers id, std::uint32_t value) -> void; - - mutable kapi::tracked_mutex m_lock{}; - kapi::memory::mmio_region m_mapped_region{}; - bool m_is_mapped{}; - }; - -} // namespace arch::drivers - -#endif -- cgit v1.2.3