From aa208226f992523865328d4612ae4a7679f57a04 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Wed, 8 Apr 2026 17:17:11 +0200 Subject: kapi: return region pair for MMIO allocation --- arch/x86_64/include/arch/devices/local_apic.hpp | 2 +- arch/x86_64/src/devices/local_apic.cpp | 10 +++++----- kapi/include/kapi/memory.hpp | 12 +++++++----- kernel/kapi/memory.cpp | 25 ++++++++++++++++++------- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/arch/x86_64/include/arch/devices/local_apic.hpp b/arch/x86_64/include/arch/devices/local_apic.hpp index 946e4af..ee1073f 100644 --- a/arch/x86_64/include/arch/devices/local_apic.hpp +++ b/arch/x86_64/include/arch/devices/local_apic.hpp @@ -25,7 +25,7 @@ namespace arch::devices std::uint64_t m_hardware_id{}; kapi::memory::physical_address m_base{}; - kapi::memory::linear_address m_virtual_base{}; + kapi::memory::mmio_region m_mapped_region{}; bool m_is_bsp{}; std::uint8_t m_version{}; std::uint8_t m_highest_lvt_entry_index{}; diff --git a/arch/x86_64/src/devices/local_apic.cpp b/arch/x86_64/src/devices/local_apic.cpp index 54d87a6..4a81de8 100644 --- a/arch/x86_64/src/devices/local_apic.cpp +++ b/arch/x86_64/src/devices/local_apic.cpp @@ -97,7 +97,7 @@ namespace arch::devices is_mapped = true; } - m_virtual_base = shared_virtual_base; + m_mapped_region = shared_virtual_base; if (m_is_bsp) { @@ -108,12 +108,12 @@ namespace arch::devices write_register(registers::spurious_interrupt_vector, lapic_enable_bit | spurious_interrupt_vector); - kstd::println("[x86_64:DEV] LAPIC initialized. version: {#x} | max_lvt_entry: {} | eoi_suppresion: {:s}", + kstd::println("[x86_64:DEV] LAPIC initialized. version: {#x} | max_lvt_entry: {} | eoi_suppression: {:s}", m_version, m_highest_lvt_entry_index, m_supports_eoi_broadcast_suppression); } else { - kstd::println("[x86_64:DEV] LAPIC {} is not on the BSP, deferring intialization.", m_hardware_id); + kstd::println("[x86_64:DEV] LAPIC {} is not on the BSP, deferring initialization.", m_hardware_id); } return true; @@ -121,13 +121,13 @@ namespace arch::devices auto local_apic::read_register(registers id) const -> std::uint32_t { - auto reg = static_cast(m_virtual_base + std::to_underlying(id)); + auto reg = static_cast(m_mapped_region.first + std::to_underlying(id)); return *reg; } auto local_apic::write_register(registers id, std::uint32_t value) -> void { - auto reg = static_cast(m_virtual_base + std::to_underlying(id)); + auto reg = static_cast(m_mapped_region.first + std::to_underlying(id)); *reg = value; } diff --git a/kapi/include/kapi/memory.hpp b/kapi/include/kapi/memory.hpp index ae33904..f5e126a 100644 --- a/kapi/include/kapi/memory.hpp +++ b/kapi/include/kapi/memory.hpp @@ -16,6 +16,8 @@ namespace kapi::memory { + using mmio_region = std::pair; + //! @addtogroup kapi-memory-kernel-defined //! @{ @@ -89,7 +91,7 @@ namespace kapi::memory //! //! @warning This function will panic if the MMIO system has not been initialized! //! @param page_count The number of pages to allocate. - auto allocate_mmio_region(std::size_t page_count) -> linear_address; + auto allocate_mmio_region(std::size_t page_count) -> mmio_region; //! Map a region of Memory-mapped I/O address space to a given hardware address using the given flags. //! @@ -98,16 +100,16 @@ namespace kapi::memory //! //! This function will always set the @p uncached flag. //! - //! @param base The base of the virtual region. + //! @param region The region to map. //! @param hw_base The base of the hardware region. //! @param flags The flags to apply. - auto map_mmio_region(linear_address base, physical_address hw_base, page_mapper::flags flags = {}) -> std::byte *; + auto map_mmio_region(mmio_region region, physical_address hw_base, page_mapper::flags flags = {}) -> std::byte *; //! Release a Memory-mapped I/O region. //! //! @warning This function will panic if the MMIO system has not been initialized! - //! @param base The start address of the region to release. - auto release_mmio_region(linear_address base) -> void; + //! @param region The region to release. + auto release_mmio_region(mmio_region region) -> void; //! @} diff --git a/kernel/kapi/memory.cpp b/kernel/kapi/memory.cpp index b224c50..31cd1f4 100644 --- a/kernel/kapi/memory.cpp +++ b/kernel/kapi/memory.cpp @@ -154,22 +154,33 @@ namespace kapi::memory mmio_allocator.emplace(base, page_count); } - auto allocate_mmio_region(std::size_t page_count) -> linear_address + auto allocate_mmio_region(std::size_t page_count) -> mmio_region { auto region = mmio_allocator->allocate(page_count); - return region; + return {region, page_count}; } - auto map_mmio_region(linear_address base, physical_address hw_base, page_mapper::flags flags) -> std::byte * + auto map_mmio_region(mmio_region region, physical_address hw_base, page_mapper::flags flags) -> std::byte * { - auto start_page = page::containing(base); + auto start_page = page::containing(region.first); auto start_frame = frame::containing(hw_base); - return map(start_page, start_frame, flags | page_mapper::flags::uncached); + + flags |= page_mapper::flags::uncached; + + auto start = map(start_page, start_frame, flags); + + std::ranges::for_each(std::views::iota(1uz, region.second), [&](auto index) { + auto page = page::containing(region.first + index * page::size); + auto frame = frame::containing(hw_base + index * page::size); + map(page, frame, flags); + }); + + return start; } - auto release_mmio_region(linear_address base) -> void + auto release_mmio_region(mmio_region region) -> void { - mmio_allocator->release(base); + mmio_allocator->release(region.first); } } // namespace kapi::memory -- cgit v1.2.3