aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2026-03-16 19:03:53 +0100
committerFelix Morgner <felix.morgner@ost.ch>2026-03-16 19:03:53 +0100
commit69a92ce3077f01ce43daef5681db298594a4badc (patch)
treede3a97018853d453c550bba7a1507211ae28fd31 /arch
parentcc5f6ef95acb7a0024c43eba314eb1f3563b41b8 (diff)
downloadteachos-69a92ce3077f01ce43daef5681db298594a4badc.tar.xz
teachos-69a92ce3077f01ce43daef5681db298594a4badc.zip
x86_64/memory: remove recursive mapping
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/CMakeLists.txt3
-rw-r--r--arch/x86_64/include/arch/cpu/control_register.hpp3
-rw-r--r--arch/x86_64/include/arch/memory/page_table.hpp127
-rw-r--r--arch/x86_64/include/arch/memory/paging_root.hpp27
-rw-r--r--arch/x86_64/include/arch/memory/recursive_page_mapper.hpp22
-rw-r--r--arch/x86_64/include/arch/memory/scoped_mapping.hpp68
-rw-r--r--arch/x86_64/kapi/memory.cpp147
-rw-r--r--arch/x86_64/src/boot/boot32.S4
-rw-r--r--arch/x86_64/src/memory/paging_root.cpp19
-rw-r--r--arch/x86_64/src/memory/recursive_page_mapper.cpp121
-rw-r--r--arch/x86_64/src/memory/scoped_mapping.cpp69
11 files changed, 63 insertions, 547 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt
index 9ea10e9..7bcf7c2 100644
--- a/arch/x86_64/CMakeLists.txt
+++ b/arch/x86_64/CMakeLists.txt
@@ -30,10 +30,7 @@ target_sources("x86_64" PRIVATE
"src/memory/kernel_mapper.cpp"
"src/memory/mmu.cpp"
"src/memory/page_table.cpp"
- "src/memory/paging_root.cpp"
- "src/memory/recursive_page_mapper.cpp"
"src/memory/region_allocator.cpp"
- "src/memory/scoped_mapping.cpp"
# VGA text mode
"src/vga/text/buffer.cpp"
diff --git a/arch/x86_64/include/arch/cpu/control_register.hpp b/arch/x86_64/include/arch/cpu/control_register.hpp
index 681dc5f..fafbfc7 100644
--- a/arch/x86_64/include/arch/cpu/control_register.hpp
+++ b/arch/x86_64/include/arch/cpu/control_register.hpp
@@ -183,7 +183,8 @@ namespace arch::cpu
//! @return The physical address of the root page map.
[[nodiscard]] constexpr auto address() const -> kapi::memory::physical_address
{
- return kapi::memory::physical_address{m_address};
+ constexpr auto address_shift = 12uz;
+ return kapi::memory::physical_address{m_address << address_shift};
}
//! Encode the frame aligned physical address of the root page map into this value.
diff --git a/arch/x86_64/include/arch/memory/page_table.hpp b/arch/x86_64/include/arch/memory/page_table.hpp
index e00e0a4..2889d38 100644
--- a/arch/x86_64/include/arch/memory/page_table.hpp
+++ b/arch/x86_64/include/arch/memory/page_table.hpp
@@ -3,17 +3,13 @@
#include "kapi/memory.hpp"
-#include "arch/memory/page_utilities.hpp"
-
#include <kstd/ext/bitfield_enum>
#include <array>
-#include <bit>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <type_traits>
-#include <utility>
namespace arch::memory
{
@@ -22,8 +18,9 @@ namespace arch::memory
//!
//! Page tables exist in a multi-level hierarchy and are used to map pages (virtual memory) onto frames (physical
//! memory). Conceptually, pages represent the data found in a virtual address space, while frames represent their
- //! storage. Only a level 1 page table maps an actual page onto a frame. All other page tables on higher levels do not
- //! map payload pages, but rather their subordinate page tables.
+ //! storage. In most cases, only a level 1 page table maps an actual page onto a frame. All other page tables on
+ //! higher levels do not map payload pages, but rather their subordinate page tables. The only exception to that rule
+ //! is the use of huge pages.
struct page_table
{
//! An entry in a page table.
@@ -146,124 +143,6 @@ namespace arch::memory
std::array<entry, entry_count> m_entries{};
};
- //! A recursively mapped page table.
- //!
- //! A page table in which at least one entry maps the same table. Recursive page tables allow for easy access to other
- //! tables within the page mapping hierarchy, without having to map them prior to access, through careful construction
- //! of linear addresses that pass through the same index multiple times.
- template<std::size_t Level>
- requires(Level > 0uz && Level < 5uz)
- struct recursive_page_table : page_table
- {
- constexpr auto static next_level = Level - 1uz;
- constexpr auto static recursive_index = 0776uz;
-
- //! Get the next lower lever table.
- //!
- //! @param self The object type of this object.
- //! @param index The index corresponding to the desired page map.
- //! @return An engaged std::optional holding a pointer to the next lower page table iff. the next lower page table
- //! at the desired index is present, std::nullopt otherwise.
- [[nodiscard]] auto next(this auto && self, std::size_t index) noexcept
- requires(next_level > 1)
- {
- return self.next_address(index).transform([](auto address) -> auto {
- auto table_pointer = std::bit_cast<recursive_page_table<next_level> *>(address);
- return &std::forward_like<decltype(self)>(*table_pointer);
- });
- }
-
- //! @copydoc recursive_page_table::next
- //!
- //! @note This overload returns a non-hierarchical, or leaf, page table
- [[nodiscard]] auto next(this auto && self, std::size_t index) noexcept
- requires(next_level == 1)
- {
- return self.next_address(index).transform([](auto address) -> auto {
- auto table_pointer = std::bit_cast<page_table *>(address);
- return &std::forward_like<decltype(self)>(*table_pointer);
- });
- }
-
- [[nodiscard]] auto translate(kapi::memory::linear_address address) const
- -> std::optional<kapi::memory::physical_address>
- requires(Level == 4)
- {
- auto offset = address % kapi::memory::page::size;
- return translate(kapi::memory::page::containing(address)).transform([offset](auto frame) -> auto {
- return frame.start_address() + offset;
- });
- }
-
- [[nodiscard]] auto translate(kapi::memory::page page) const -> std::optional<kapi::memory::frame>
- requires(Level == 4)
- {
- auto pml3 = next(pml_index<4>(page));
-
- if (!pml3)
- {
- return std::nullopt;
- }
-
- auto handle_huge_page = [&] -> std::optional<kapi::memory::frame> {
- auto pml3_entry = pml3.transform([&](auto pml3) -> auto { return (*pml3)[pml_index<3>(page)]; });
- if (!pml3_entry)
- {
- return std::nullopt;
- }
- else if (pml3_entry->huge())
- {
- auto pml3_entry_frame = *pml3_entry->frame();
- return kapi::memory::frame{pml3_entry_frame.number() + pml_index<2>(page) * entry_count + pml_index<1>(page)};
- }
-
- auto pml2 = (*pml3)->next(pml_index<3>(page));
- auto pml2_entry = pml2.transform([&](auto pml2) -> auto { return (*pml2)[pml_index<2>(page)]; });
- if (!pml2_entry)
- {
- return std::nullopt;
- }
- else if (pml2_entry->huge())
- {
- auto pml2_entry_frame = *pml2_entry->frame();
- return kapi::memory::frame{pml2_entry_frame.number() + pml_index<1>(page)};
- }
-
- return std::nullopt;
- };
-
- return pml3.and_then([&](auto pml3) -> auto { return pml3->next(pml_index<3>(page)); })
- .and_then([&](auto pml2) -> auto { return pml2->next(pml_index<2>(page)); })
- .and_then([&](auto pml1) -> auto { return (*pml1)[pml_index<1>(page)].frame(); })
- .or_else(handle_huge_page);
- }
-
- private:
- //! The number of address bits used to represent the page index per level.
- constexpr auto static level_bits = 9;
- //! The highest address bit.
- constexpr auto static high_bit = 48;
- //! The number of bits representing the offset into a page.
- constexpr auto static offset_bits = 12;
-
- //! Calculate the recursive address of the next lower page table.
- //!
- //! @param index The index of the desired page table.
- //! @return An engaged std::optional holding the address of the new lower page table iff. the next lower page table
- //! at the desired index is present, std::nullopt otherwise.
- [[nodiscard]] auto next_address(std::size_t index) const noexcept -> std::optional<std::uintptr_t>
- {
- if (auto entry = (*this)[index]; entry.present() && !entry.huge())
- {
- auto this_address = std::bit_cast<std::uintptr_t>(this);
- auto next_address = (this_address << level_bits) | 1uz << high_bit | (index << offset_bits);
- return next_address;
- }
-
- return std::nullopt;
- }
- };
-
} // namespace arch::memory
namespace kstd::ext
diff --git a/arch/x86_64/include/arch/memory/paging_root.hpp b/arch/x86_64/include/arch/memory/paging_root.hpp
deleted file mode 100644
index febbb11..0000000
--- a/arch/x86_64/include/arch/memory/paging_root.hpp
+++ /dev/null
@@ -1,27 +0,0 @@
-#ifndef TEACHOS_X86_64_PAGING_ROOT_HPP
-#define TEACHOS_X86_64_PAGING_ROOT_HPP
-
-#include "arch/memory/page_table.hpp"
-
-namespace arch::memory
-{
-
- //! The active, recursively mapped, root map (e.g. PML4)
- struct paging_root : recursive_page_table<4>
- {
- auto static get() -> paging_root *;
-
- paging_root(paging_root const &) = delete;
- paging_root(paging_root &&) = delete;
- auto operator=(paging_root const &) -> paging_root & = delete;
- auto operator=(paging_root &&) -> paging_root & = delete;
-
- ~paging_root() = delete;
-
- private:
- paging_root() = default;
- };
-
-} // namespace arch::memory
-
-#endif \ No newline at end of file
diff --git a/arch/x86_64/include/arch/memory/recursive_page_mapper.hpp b/arch/x86_64/include/arch/memory/recursive_page_mapper.hpp
deleted file mode 100644
index a0c290a..0000000
--- a/arch/x86_64/include/arch/memory/recursive_page_mapper.hpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef TEACHOS_X86_64_RECURSIVE_PAGE_MAPPER_HPP
-#define TEACHOS_X86_64_RECURSIVE_PAGE_MAPPER_HPP
-
-#include "kapi/memory.hpp"
-
-#include <cstddef>
-
-namespace arch::memory
-{
-
- struct recursive_page_mapper : kapi::memory::page_mapper
- {
- explicit recursive_page_mapper();
-
- auto map(kapi::memory::page page, kapi::memory::frame frame, flags flags) -> std::byte * override;
- auto unmap(kapi::memory::page page) -> void override;
- auto try_unmap(kapi::memory::page page) noexcept -> bool override;
- };
-
-} // namespace arch::memory
-
-#endif \ No newline at end of file
diff --git a/arch/x86_64/include/arch/memory/scoped_mapping.hpp b/arch/x86_64/include/arch/memory/scoped_mapping.hpp
deleted file mode 100644
index c713e03..0000000
--- a/arch/x86_64/include/arch/memory/scoped_mapping.hpp
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef TEACHOS_X86_64_SCOPED_MAPPING_HPP
-#define TEACHOS_X86_64_SCOPED_MAPPING_HPP
-
-#include "kapi/memory.hpp"
-
-#include "arch/memory/page_table.hpp"
-
-#include <cstddef>
-
-namespace arch::memory
-{
-
- //! A page mapping that, if established, maps a given frame to a given unused page, unmapping it on destruction. It
- //! allows for an easy way to quickly map a page that is not required to be mapped forever. When mapping a frame, new
- //! page tables may be allocated. On destruction, these pages tables, or rather their respective frames, will be
- //! released again.
- struct scoped_mapping
- {
- //! Copying a scoped mapping would be meaningless.
- scoped_mapping(scoped_mapping const &) noexcept = delete;
-
- //! Adopt an existing scoped mapping, transferring mapping ownership to this new object.
- scoped_mapping(scoped_mapping &&) noexcept;
-
- //! Construct a new scoped mapping, which can be used to map a frame to the given unused page.
- //! @param page An unused page. If the page is already mapped, this constructor will panic.
- //! @param mapper The page mapper to use for mapping and unmapping of the page.
- explicit scoped_mapping(kapi::memory::page page, kapi::memory::page_mapper & mapper);
-
- //! Unmap the mapped frame if one was mapped.
- //! @note Any page tables that were allocated to support the mapping will be released.
- ~scoped_mapping() noexcept;
-
- //! Copying a scoped mapping would be meaningless.
- auto operator=(scoped_mapping const &) -> scoped_mapping = delete;
-
- //! Adopt an existing scoped mapping, swapping mapping ownerships between the objects.
- auto operator=(scoped_mapping &&) noexcept -> scoped_mapping &;
-
- //! Map the given frame with the given flags.
- //! @note If a mapping has already been established, this function will panic
- //! @param frame A frame to map.
- //! @param flags The flags, besides the present flag, to apply to the mapping.
- //! @return A pointer to the first byte of the mapped frame.
- auto map(kapi::memory::frame frame, page_table::entry::flags flags) -> std::byte *;
-
- //! Map the given frame, returning a typed pointer.
- template<typename DataType>
- auto map_as(kapi::memory::frame frame, page_table::entry::flags flags) -> DataType *
- {
- return std::bit_cast<DataType *>(map(frame, flags));
- }
-
- //! Unmap the mapped frame.
- //! @note If no frame was ever mapped, this function will panic.
- auto unmap() -> void;
-
- friend auto swap(scoped_mapping & lhs, scoped_mapping & rhs) -> void;
-
- private:
- kapi::memory::page m_page;
- kapi::memory::page_mapper * m_mapper;
- bool m_mapped;
- };
-
-} // namespace arch::memory
-
-#endif \ No newline at end of file
diff --git a/arch/x86_64/kapi/memory.cpp b/arch/x86_64/kapi/memory.cpp
index 11bc69c..f74eea6 100644
--- a/arch/x86_64/kapi/memory.cpp
+++ b/arch/x86_64/kapi/memory.cpp
@@ -1,7 +1,6 @@
#include "kapi/memory.hpp"
#include "kapi/boot.hpp"
-#include "kapi/memory/buffered_allocator.hpp"
#include "kapi/system.hpp"
#include "arch/boot/boot.hpp"
@@ -10,11 +9,7 @@
#include "arch/memory/kernel_mapper.hpp"
#include "arch/memory/mmu.hpp"
#include "arch/memory/page_table.hpp"
-#include "arch/memory/page_utilities.hpp"
-#include "arch/memory/paging_root.hpp"
-#include "arch/memory/recursive_page_mapper.hpp"
#include "arch/memory/region_allocator.hpp"
-#include "arch/memory/scoped_mapping.hpp"
#include <kstd/print>
@@ -26,7 +21,6 @@
#include <bit>
#include <cstddef>
#include <cstdint>
-#include <memory>
#include <optional>
#include <ranges>
#include <span>
@@ -37,12 +31,7 @@ namespace kapi::memory
namespace
{
- constexpr auto static unused_page_address = linear_address{0x0000'7fff'cafe'faceuz};
- constexpr auto static recursive_page_map_index = arch::memory::page_table::entry_count - 2;
-
auto constinit region_based_allocator = std::optional<arch::memory::region_allocator>{};
- auto constinit allocation_buffer = std::optional<buffered_allocator<4>>{};
- auto constinit recursive_page_mapper = std::optional<arch::memory::recursive_page_mapper>{};
//! Instantiate a basic, memory region based, early frame allocator for remapping.
auto collect_memory_information()
@@ -71,65 +60,13 @@ namespace kapi::memory
arch::cpu::i32_efer::set(arch::cpu::i32_efer::flags::execute_disable_bit_enable);
}
- //! Inject, or graft, a faux recursive PML4 into the active page mapping structure.
- auto inject_faux_pml4(frame_allocator & allocator, page_mapper & mapper)
- {
- using arch::memory::page_table;
- using arch::memory::paging_root;
- using arch::memory::pml_index;
- using entry_flags = arch::memory::page_table::entry::flags;
-
- auto page = page::containing(unused_page_address);
-
- auto temporary_mapper = arch::memory::scoped_mapping{page, mapper};
- auto new_pml4_frame = allocator.allocate();
-
- auto pml4 = std::construct_at(temporary_mapper.map_as<page_table>(*new_pml4_frame, entry_flags::writable));
- (*pml4)[recursive_page_map_index].frame(new_pml4_frame.value(), entry_flags::present | entry_flags::writable);
-
- auto pml4_index = pml_index<4>(page);
- auto old_pml4 = paging_root::get();
- auto pml4_entry = (*old_pml4)[pml4_index];
-
- auto pml3_index = pml_index<3>(page);
- auto old_pml3 = old_pml4->next(pml4_index);
- auto pml3_entry = (**old_pml3)[pml3_index];
-
- auto pml2_index = pml_index<2>(page);
- auto old_pml2 = (**old_pml3).next(pml3_index);
- auto pml2_entry = (**old_pml2)[pml2_index];
-
- auto pml1_index = pml_index<1>(page);
- auto old_pml1 = (**old_pml2).next(pml2_index);
- auto pml1_entry = (**old_pml1)[pml1_index];
-
- (*paging_root::get())[recursive_page_map_index].frame(new_pml4_frame.value(),
- entry_flags::present | entry_flags::writable);
-
- arch::memory::tlb_flush_all();
-
- auto new_pml4 = paging_root::get();
- (*new_pml4)[pml4_index] = pml4_entry;
-
- auto new_pml3 = new_pml4->next(pml4_index);
- (**new_pml3)[pml3_index] = pml3_entry;
-
- auto new_pml2 = (**new_pml3).next(pml3_index);
- (**new_pml2)[pml2_index] = pml2_entry;
-
- auto new_pml1 = (**new_pml2).next(pml2_index);
- (**new_pml1)[pml1_index] = pml1_entry;
-
- return *new_pml4_frame;
- }
-
- auto remap_kernel(page_mapper & mapper) -> void
+ [[maybe_unused]] auto remap_kernel(page_mapper & mapper) -> void
{
auto kernel_mapper = arch::memory::kernel_mapper{boot::bootstrap_information.mbi};
kernel_mapper.remap_kernel(mapper);
}
- auto remap_vga_text_mode_buffer(page_mapper & mapper) -> void
+ [[maybe_unused]] auto remap_vga_text_mode_buffer(page_mapper & mapper) -> void
{
constexpr auto vga_base = std::uintptr_t{0xb8000};
auto vga_physical_start = physical_address{vga_base};
@@ -141,7 +78,7 @@ namespace kapi::memory
mapper.map(page, frame, page_mapper::flags::writable | page_mapper::flags::supervisor_only);
}
- auto remap_multiboot_information(page_mapper & mapper) -> void
+ [[maybe_unused]] auto remap_multiboot_information(page_mapper & mapper) -> void
{
auto mbi_base = std::bit_cast<std::uintptr_t>(boot::bootstrap_information.mbi);
auto mbi_size = boot::bootstrap_information.mbi->size_bytes();
@@ -157,7 +94,7 @@ namespace kapi::memory
}
}
- auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void
+ [[maybe_unused]] auto handoff_to_kernel_pmm(frame_allocator & new_allocator) -> void
{
auto memory_map = boot::bootstrap_information.mbi->memory_map();
@@ -196,6 +133,39 @@ namespace kapi::memory
std::ranges::for_each(std::views::iota(mbi_start, mbi_end), [&](auto frame) { new_allocator.mark_used(frame); });
}
+ auto establish_higher_half_direct_mapping() -> void
+ {
+ auto hhdm_frame = kapi::memory::allocate_frame();
+ auto hhdm_pml3 = static_cast<arch::memory::page_table *>(hhdm_frame->start_address());
+ hhdm_pml3->clear();
+
+ std::ranges::for_each(std::views::iota(0uz, 512uz), [&](auto index) {
+ auto frame = kapi::memory::frame{(1024uz * 1024uz * 1024uz * index)};
+ auto & entry = (*hhdm_pml3)[index];
+ entry.frame(frame, arch::memory::page_table::entry::flags::present |
+ arch::memory::page_table::entry::flags::writable |
+ arch::memory::page_table::entry::flags::huge_page);
+ });
+
+ auto current_cr3 = arch::cpu::cr3::read();
+ auto pml4_address = linear_address{current_cr3.address().raw()};
+ auto pml4 = static_cast<arch::memory::page_table *>(pml4_address);
+ (*pml4)[256].frame(*hhdm_frame, arch::memory::page_table::entry::flags::present |
+ arch::memory::page_table::entry::flags::writable |
+ arch::memory::page_table::entry::flags::global);
+ }
+
+ auto clear_lower_address_space() -> void
+ {
+ auto current_cr3 = arch::cpu::cr3::read();
+ auto pml4_address = memory::higher_half_direct_map_base + current_cr3.address().raw();
+ auto pml4 = static_cast<arch::memory::page_table *>(pml4_address);
+
+ std::ranges::for_each(std::views::iota(0uz, 1uz), [&](auto index) { (*pml4)[index].clear(); });
+
+ arch::memory::tlb_flush_all();
+ }
+
} // namespace
auto init() -> void
@@ -212,37 +182,36 @@ namespace kapi::memory
enable_cpu_protections();
region_based_allocator.emplace(collect_memory_information());
- allocation_buffer.emplace(&*region_based_allocator);
- set_frame_allocator(*allocation_buffer);
+ set_frame_allocator(*region_based_allocator);
- recursive_page_mapper.emplace();
- set_page_mapper(*recursive_page_mapper);
+ kstd::println("[x86_64:MEM] Establishing higher-half direct mapping.");
- kstd::println("[x86_64:MEM] Preparing new paging hierarchy.");
+ establish_higher_half_direct_mapping();
+ clear_lower_address_space();
- auto new_pml4_frame = inject_faux_pml4(*allocation_buffer, *recursive_page_mapper);
+ kstd::println("[x86_64:MEM] Preparing new paging hierarchy.");
- remap_kernel(*recursive_page_mapper);
- remap_vga_text_mode_buffer(*recursive_page_mapper);
- remap_multiboot_information(*recursive_page_mapper);
+ // remap_kernel(*recursive_page_mapper);
+ // remap_vga_text_mode_buffer(*recursive_page_mapper);
+ // remap_multiboot_information(*recursive_page_mapper);
- kstd::println("[x86_64:MEM] Switching to new paging hierarchy.");
+ // kstd::println("[x86_64:MEM] Switching to new paging hierarchy.");
- auto cr3 = arch::cpu::cr3::read();
- cr3.frame(new_pml4_frame);
- arch::cpu::cr3::write(cr3);
+ // auto cr3 = arch::cpu::cr3::read();
+ // cr3.frame(new_pml4_frame);
+ // arch::cpu::cr3::write(cr3);
- auto memory_map = boot::bootstrap_information.mbi->memory_map();
- auto highest_byte = std::ranges::max(std::views::transform(
- std::views::filter(memory_map.regions(),
- [](auto const & region) { return region.type == multiboot2::memory_type::available; }),
- [](auto const & region) { return region.base + region.size_in_B; }));
+ // auto memory_map = boot::bootstrap_information.mbi->memory_map();
+ // auto highest_byte = std::ranges::max(std::views::transform(
+ // std::views::filter(memory_map.regions(),
+ // [](auto const & region) { return region.type == multiboot2::memory_type::available; }),
+ // [](auto const & region) { return region.base + region.size_in_B; }));
- init_pmm(frame::containing(physical_address{highest_byte}).number() + 1, handoff_to_kernel_pmm);
+ // init_pmm(frame::containing(physical_address{highest_byte}).number() + 1, handoff_to_kernel_pmm);
- kstd::println("[x86_64:MEM] Releasing bootstrap memory allocators.");
- allocation_buffer.reset();
- region_based_allocator.reset();
+ // kstd::println("[x86_64:MEM] Releasing bootstrap memory allocators.");
+ // allocation_buffer.reset();
+ // region_based_allocator.reset();
}
} // namespace kapi::memory
diff --git a/arch/x86_64/src/boot/boot32.S b/arch/x86_64/src/boot/boot32.S
index 056cd8e..694b8b7 100644
--- a/arch/x86_64/src/boot/boot32.S
+++ b/arch/x86_64/src/boot/boot32.S
@@ -319,10 +319,6 @@ _prepare_page_maps:
call _clear_page_map_memory
lea (page_map_level_4 - 0b)(%esi), %edi
- mov %edi, %eax
- or $0b11, %eax
- mov %eax, (510 * 8)(%edi)
-
lea (page_map_level_3_low - 0b)(%esi), %eax
or $0b11, %eax
mov %eax, (%edi)
diff --git a/arch/x86_64/src/memory/paging_root.cpp b/arch/x86_64/src/memory/paging_root.cpp
deleted file mode 100644
index 41f40ed..0000000
--- a/arch/x86_64/src/memory/paging_root.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-#include "arch/memory/paging_root.hpp"
-
-#include <bit>
-#include <cstdint>
-
-namespace arch::memory
-{
-
- namespace
- {
- constexpr auto recursive_base = std::uintptr_t{0177777'776'776'776'776'0000uz};
- } // namespace
-
- auto paging_root::get() -> paging_root *
- {
- return std::bit_cast<paging_root *>(recursive_base);
- }
-
-} // namespace arch::memory \ No newline at end of file
diff --git a/arch/x86_64/src/memory/recursive_page_mapper.cpp b/arch/x86_64/src/memory/recursive_page_mapper.cpp
deleted file mode 100644
index c7c5341..0000000
--- a/arch/x86_64/src/memory/recursive_page_mapper.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#include "arch/memory/recursive_page_mapper.hpp"
-
-#include "kapi/memory.hpp"
-#include "kapi/system.hpp"
-
-#include "arch/memory/page_table.hpp"
-#include "arch/memory/page_utilities.hpp"
-#include "arch/memory/paging_root.hpp"
-
-#include <cstddef>
-#include <optional>
-
-namespace arch::memory
-{
- namespace
- {
- //! Perform the actual mapping of the page, via the recursive page map.
- //!
- //! On any level above PML1, the entries need to not be no_execute, because the image is densely packed. The entries
- //! also need to be writable, since the mapping is being performed through the recursive page map hierarchy. When
- //! setting the final entry in the PML1, the actually desired flags are set as is, with the present bit
- //! added, thus still enforcing non-writability and non-execution of the affected page.
- template<std::size_t Level>
- requires(Level > 1uz && Level <= PLATFORM_PAGING_LEVELS)
- auto do_map(recursive_page_table<Level> * pml, kapi::memory::page page, kapi::memory::frame_allocator & allocator,
- kapi::memory::page_mapper::flags flags)
- {
- auto index = pml_index<Level>(page);
- auto entry_flags = to_table_flags(flags);
-
- entry_flags = entry_flags & ~page_table::entry::flags::no_execute;
- entry_flags = entry_flags | page_table::entry::flags::writable;
- if (!(*pml)[index].present())
- {
- auto new_table_frame = allocator.allocate();
- (*pml)[index].frame(new_table_frame.value(), page_table::entry::flags::present | entry_flags);
- auto new_table = std::optional{std::construct_at(*pml->next(index))};
- return new_table;
- }
- (*pml)[index] |= entry_flags;
- return pml->next(index);
- }
-
- //! Perform the actual PML1 update.
- auto do_map(page_table * pml, kapi::memory::page page, kapi::memory::frame frame,
- kapi::memory::page_mapper::flags flags) -> std::optional<std::byte *>
- {
- auto index = pml_index<1>(page);
- if ((*pml)[index].present())
- {
- kapi::system::panic("[x86_64:MEM] Tried to map a page that is already mapped");
- }
- (*pml)[index].frame(frame, page_table::entry::flags::present | to_table_flags(flags));
- return std::optional{static_cast<std::byte *>(page.start_address())};
- }
-
- } // namespace
-
- recursive_page_mapper::recursive_page_mapper() {}
-
- auto recursive_page_mapper::map(kapi::memory::page page, kapi::memory::frame frame, flags flags) -> std::byte *
- {
- auto pml4 = static_cast<recursive_page_table<4> *>((paging_root::get()));
- auto & allocator = kapi::memory::get_frame_allocator();
-
- return std::optional{pml4}
- .and_then([&](auto pml) -> auto { return do_map(pml, page, allocator, flags); })
- .and_then([&](auto pml) -> auto { return do_map(pml, page, allocator, flags); })
- .and_then([&](auto pml) -> auto { return do_map(pml, page, allocator, flags); })
- .and_then([&](auto pml) -> auto { return do_map(pml, page, frame, flags); })
- .value_or(nullptr);
- }
-
- auto recursive_page_mapper::unmap(kapi::memory::page page) -> void
- {
- if (!try_unmap(page))
- {
- kapi::system::panic("[x86_64:MEM] Tried to unmap a page that was not mapped.");
- }
- }
-
- auto recursive_page_mapper::try_unmap(kapi::memory::page page) noexcept -> bool
- {
- if (!paging_root::get()->translate(page))
- {
- return false;
- }
-
- auto pml4 = paging_root::get();
- auto pml3 = pml4->next(pml_index<4>(page)).value();
- auto pml2 = pml3->next(pml_index<3>(page)).value();
- auto pml1 = pml2->next(pml_index<2>(page)).value();
- auto & allocator = kapi::memory::get_frame_allocator();
-
- (*pml1)[pml_index<1>(page)].clear();
-
- if (pml1->empty())
- {
- auto pml1_frame = (*pml2)[pml_index<2>(page)].frame().value();
- allocator.release(pml1_frame);
- (*pml2)[pml_index<2>(page)].clear();
- }
-
- if (pml2->empty())
- {
- auto pml2_frame = (*pml3)[pml_index<3>(page)].frame().value();
- allocator.release(pml2_frame);
- (*pml3)[pml_index<3>(page)].clear();
- }
-
- if (pml3->empty())
- {
- auto pml3_frame = (*pml4)[pml_index<4>(page)].frame().value();
- allocator.release(pml3_frame);
- (*pml4)[pml_index<4>(page)].clear();
- }
-
- return true;
- }
-
-} // namespace arch::memory \ No newline at end of file
diff --git a/arch/x86_64/src/memory/scoped_mapping.cpp b/arch/x86_64/src/memory/scoped_mapping.cpp
deleted file mode 100644
index dde1dda..0000000
--- a/arch/x86_64/src/memory/scoped_mapping.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-#include "arch/memory/scoped_mapping.hpp"
-
-#include "kapi/memory.hpp"
-#include "kapi/system.hpp"
-
-#include "arch/memory/mmu.hpp"
-#include "arch/memory/page_table.hpp"
-#include "arch/memory/paging_root.hpp"
-
-#include <cstddef>
-#include <utility>
-
-namespace arch::memory
-{
-
- scoped_mapping::scoped_mapping(scoped_mapping && other) noexcept
- : m_page{std::exchange(other.m_page, kapi::memory::page{})}
- , m_mapper{std::exchange(other.m_mapper, nullptr)}
- , m_mapped{std::exchange(other.m_mapped, false)}
- {}
-
- scoped_mapping::scoped_mapping(kapi::memory::page page, kapi::memory::page_mapper & mapper)
- : m_page{page}
- , m_mapper{&mapper}
- , m_mapped{false}
- {
- if (paging_root::get()->translate(page))
- {
- kapi::system::panic("[MEM] Tried to map a page that is already mapped!");
- }
- }
-
- scoped_mapping::~scoped_mapping() noexcept
- {
- if (m_mapped)
- {
- unmap();
- tlb_flush(m_page.start_address());
- }
- }
-
- auto scoped_mapping::operator=(scoped_mapping && other) noexcept -> scoped_mapping &
- {
- swap(*this, other);
- return *this;
- }
-
- auto scoped_mapping::map(kapi::memory::frame frame, page_table::entry::flags flags) -> std::byte *
- {
- auto result = m_mapper->map(m_page, frame, to_mapper_flags(flags));
- m_mapped = true;
- return result;
- }
-
- auto scoped_mapping::unmap() -> void
- {
- m_mapper->unmap(m_page);
- m_mapped = false;
- }
-
- auto swap(scoped_mapping & lhs, scoped_mapping & rhs) -> void
- {
- using std::swap;
- swap(lhs.m_page, rhs.m_page);
- swap(lhs.m_mapper, rhs.m_mapper);
- swap(lhs.m_mapped, rhs.m_mapped);
- }
-
-} // namespace arch::memory \ No newline at end of file