#include "kernel/test_support/page_mapper.hpp" #include "kapi/memory.hpp" #include #include #include #include #include namespace kernel::tests { page_mapper::page_mapper(kstd::units::bytes memory_size) : memory{memory_size} {} auto page_mapper::map(kapi::memory::page page, kapi::memory::frame frame, flags) -> std::byte * { auto result = page_mappings.insert({page.number(), frame}); if (!result.second) { auto error = std::format("Page {} was already mapped!", page.number()); throw std::invalid_argument{error}; } auto page_address = page.start_address(); auto sandbox_start = memory.heap_base(); auto sandbox_end = sandbox_start + memory.heap_size(); if (page_address >= sandbox_start && page_address < sandbox_end) { auto virtual_target = static_cast(page_address); auto physical_offset = frame.number() * kapi::memory::frame::size; auto mapped_ptr = mmap(virtual_target, kapi::memory::page::size.value, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, memory.memory_descriptor(), physical_offset.value); if (mapped_ptr == MAP_FAILED) { throw std::runtime_error("Failed to map page"); } return static_cast(mapped_ptr); } else if (page_address >= kapi::memory::mmio_base) { throw std::runtime_error("MMIO mapping not yet supported in testing!"); } else if (page_address >= kapi::memory::higher_half_direct_map_base) { auto offset = frame.number() * kapi::memory::frame::size; return memory.ram_base() + offset; } return nullptr; } auto page_mapper::unmap(kapi::memory::page page) -> void { if (!try_unmap(page)) { auto error = std::format("Page {} was never mapped!", page.number()); throw std::invalid_argument{error}; } } auto page_mapper::try_unmap(kapi::memory::page page) noexcept -> bool { if (page_mappings.contains(page.number())) { page_mappings.erase(page.number()); return true; } return false; } } // namespace kernel::tests