#include "kernel/test_support/simulated_memory.hpp" #include "kapi/memory.hpp" #include #include #include #include #include #include #include #include #include namespace kernel::tests { simulated_memory::simulated_memory(kstd::units::bytes physical_size, kstd::units::bytes virtual_size) : m_descriptor{memfd_create("teachos_simulated_memory", 0)} , m_physical_size{physical_size} , m_virtual_size{virtual_size} { if (m_descriptor < 0) { auto error = std::format("Failed to allocate backing memory: {}", strerror(errno)); throw std::runtime_error(error); } if (ftruncate(m_descriptor, static_cast(m_physical_size.value)) < 0) { auto error = std::format("Failed to reserve backing memory: {}", strerror(errno)); throw std::runtime_error(error); } auto physical_storage = mmap(nullptr, m_physical_size.value, PROT_READ | PROT_WRITE, MAP_SHARED, m_descriptor, 0); if (physical_storage == MAP_FAILED) { auto error = std::format("Failed to map backing memory: {}", strerror(errno)); throw std::runtime_error(error); } auto virtual_pointer = mmap(nullptr, virtual_size.value, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (virtual_pointer == MAP_FAILED) { auto error = std::format("Failed to reserve virtual memory: {}", strerror(errno)); throw std::runtime_error(error); } m_physical_base = static_cast(physical_storage); m_virtual_base = static_cast(virtual_pointer); clear(); } simulated_memory::~simulated_memory() { munmap(m_virtual_base, m_virtual_size.value); munmap(m_physical_base, m_physical_size.value); close(m_descriptor); } auto simulated_memory::clear() -> void { std::memset(m_physical_base, 0, m_physical_size.value); } auto simulated_memory::physical_base() noexcept -> std::byte * { return m_physical_base; } auto simulated_memory::physical_base() const noexcept -> std::byte const * { return m_physical_base; } auto simulated_memory::physical_size() const noexcept -> kstd::units::bytes { return m_physical_size; } auto simulated_memory::virtual_base() const noexcept -> kapi::memory::linear_address { return kapi::memory::linear_address{m_virtual_base}; } auto simulated_memory::virtual_size() const noexcept -> kstd::units::bytes { return m_virtual_size; } auto simulated_memory::map(kstd::units::bytes size, std::byte * to, off_t offset) -> std::byte * { auto mapped_ptr = mmap(to, size.value, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, m_descriptor, offset); if (mapped_ptr == MAP_FAILED) { auto error = std::format("Failed to map page: {}", strerror(errno)); throw std::runtime_error(error); } return static_cast(mapped_ptr); } } // namespace kernel::tests