aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src/memory
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-12-12 14:07:28 +0100
committerFelix Morgner <felix.morgner@ost.ch>2025-12-12 14:07:28 +0100
commit50c9c9a1d963e66f7658ab31e9ecd65bf227cfff (patch)
tree7b16e1cbf5aafaa1f5a5d814cac96bb283009e0c /arch/x86_64/src/memory
parent8fc5f9e3cc28b07b1f120eb1ffedc042fa6662b8 (diff)
downloadteachos-50c9c9a1d963e66f7658ab31e9ecd65bf227cfff.tar.xz
teachos-50c9c9a1d963e66f7658ab31e9ecd65bf227cfff.zip
x86_64/memory: clean up dependencies
Diffstat (limited to 'arch/x86_64/src/memory')
-rw-r--r--arch/x86_64/src/memory/kernel_mapper.cpp25
-rw-r--r--arch/x86_64/src/memory/paging_root.cpp149
-rw-r--r--arch/x86_64/src/memory/recursive_page_mapper.cpp85
-rw-r--r--arch/x86_64/src/memory/scoped_mapping.cpp11
4 files changed, 103 insertions, 167 deletions
diff --git a/arch/x86_64/src/memory/kernel_mapper.cpp b/arch/x86_64/src/memory/kernel_mapper.cpp
index f46b5b5..a28cf00 100644
--- a/arch/x86_64/src/memory/kernel_mapper.cpp
+++ b/arch/x86_64/src/memory/kernel_mapper.cpp
@@ -5,8 +5,6 @@
#include "kapi/system.hpp"
#include "x86_64/boot/ld.hpp"
-#include "x86_64/memory/page_table.hpp"
-#include "x86_64/memory/paging_root.hpp"
#include <elf/format.hpp>
#include <elf/section_header.hpp>
@@ -17,7 +15,7 @@
namespace teachos::memory::x86_64
{
- inline namespace
+ namespace
{
using namespace std::string_view_literals;
@@ -37,7 +35,7 @@ namespace teachos::memory::x86_64
, m_kernel_load_base{std::bit_cast<std::uintptr_t>(&boot::x86_64::TEACHOS_VMA)}
{}
- auto kernel_mapper::remap_kernel() -> void
+ auto kernel_mapper::remap_kernel(page_mapper & mapper) -> void
{
auto elf_information = m_mbi->maybe_elf_symbols<elf::format::elf64>();
if (!elf_information)
@@ -60,10 +58,11 @@ namespace teachos::memory::x86_64
}
std::ranges::for_each(allocated_sections,
- [&](auto const & section) -> auto { map_section(section, sections.name(section)); });
+ [&](auto const & section) -> auto { map_section(section, sections.name(section), mapper); });
}
- auto kernel_mapper::map_section(section_header_type const & section, std::string_view name) -> void
+ auto kernel_mapper::map_section(section_header_type const & section, std::string_view name, page_mapper & mapper)
+ -> void
{
cio::print("[x86_64:MEM] mapping ");
cio::println(name);
@@ -76,30 +75,30 @@ namespace teachos::memory::x86_64
auto first_page = page::containing(linear_start_address);
auto first_frame = frame::containing(physical_start_address);
- auto page_flags = page_table::entry::flags::empty;
+ auto page_flags = page_mapper::flags::empty;
if (section.writable())
{
- page_flags |= page_table::entry::flags::writable;
+ page_flags |= page_mapper::flags::writable;
}
- if (!section.executable())
+ if (section.executable())
{
- page_flags |= page_table::entry::flags::no_execute;
+ page_flags |= page_mapper::flags::executable;
}
auto is_prefix_of_name = [=](auto prefix) -> bool {
return name.starts_with(prefix);
};
- if (std::ranges::any_of(user_accessible_prefixes, is_prefix_of_name))
+ if (!std::ranges::any_of(user_accessible_prefixes, is_prefix_of_name))
{
- page_flags |= page_table::entry::flags::user_accessible;
+ page_flags |= page_mapper::flags::supervisor_only;
}
for (auto i = 0uz; i < number_of_pages; ++i)
{
- paging_root::get().map(page{first_page.number() + i}, frame{first_frame.number() + i}, page_flags);
+ mapper.map(first_page + i, first_frame + i, page_flags);
}
}
diff --git a/arch/x86_64/src/memory/paging_root.cpp b/arch/x86_64/src/memory/paging_root.cpp
index 078686b..4f88657 100644
--- a/arch/x86_64/src/memory/paging_root.cpp
+++ b/arch/x86_64/src/memory/paging_root.cpp
@@ -1,161 +1,18 @@
#include "x86_64/memory/paging_root.hpp"
-#include "kapi/memory.hpp"
-#include "kapi/system.hpp"
-
-#include "x86_64/memory/page_table.hpp"
-#include "x86_64/memory/page_utilities.hpp"
-#include "x86_64/memory/scoped_mapping.hpp"
-
-#include <cstddef>
#include <cstdint>
-#include <memory>
-#include <optional>
namespace teachos::memory::x86_64
{
namespace
{
- constexpr auto PML_RECURSIVE_BASE = std::uintptr_t{0177777'776'776'776'776'0000uz};
-
- //! 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 < 5uz)
- auto do_map(recursive_page_table<Level> * pml, page page, page_table::entry::flags flags)
- {
- auto index = pml_index<Level>(page);
- flags = flags & ~page_table::entry::flags::no_execute;
- flags = flags | page_table::entry::flags::writable;
- if (!(*pml)[index].present())
- {
- auto new_table_frame = active_frame_allocator().allocate();
- auto mapping = scoped_mapping{page};
- (*pml)[index].frame(new_table_frame.value(), page_table::entry::flags::present | flags);
- auto new_table = std::optional{std::construct_at(*pml->next(index))};
- return new_table;
- }
- (*pml)[index] |= flags;
- return pml->next(index);
- }
-
- //! Perform the actual PML1 update.
- auto do_map(page_table * pml, page page, frame frame, page_table::entry::flags flags) -> std::optional<std::byte *>
- {
- auto index = pml_index<1>(page);
- if ((*pml)[index].present())
- {
- system::panic("[x86_64:MEM] Tried to map a page that is already mapped");
- }
- (*pml)[index].frame(frame, page_table::entry::flags::present | flags);
- return std::optional{static_cast<std::byte *>(page.start_address())};
- }
+ constexpr auto recursive_base = std::uintptr_t{0177777'776'776'776'776'0000uz};
} // namespace
- auto paging_root::get() -> paging_root &
- {
- auto pml4_address = std::bit_cast<paging_root *>(PML_RECURSIVE_BASE);
- return *pml4_address;
- }
-
- auto paging_root::translate(linear_address address) const -> std::optional<physical_address>
- {
- auto offset = address.raw() % page::size;
- return translate(page::containing(address)).transform([offset](auto frame) -> auto {
- return physical_address{frame.start_address().raw() + offset};
- });
- }
-
- auto paging_root::translate(page page) const -> std::optional<frame>
- {
- auto pml3 = next(pml_index<4>(page));
-
- if (!pml3)
- {
- return std::nullopt;
- }
-
- auto handle_huge_page = [&] -> std::optional<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 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 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);
- }
-
- auto paging_root::map(page page, frame frame, page_table::entry::flags flags) -> std::optional<std::byte *>
+ auto paging_root::get() -> paging_root *
{
- return std::optional{this}
- .and_then([&](auto pml) -> auto { return do_map(pml, page, flags); })
- .and_then([&](auto pml) -> auto { return do_map(pml, page, flags); })
- .and_then([&](auto pml) -> auto { return do_map(pml, page, flags); })
- .and_then([&](auto pml) -> auto { return do_map(pml, page, frame, flags); });
- }
-
- auto paging_root::unmap(page page) -> void
- {
- if (!this->translate(page))
- {
- system::panic("[x86_64:MEM] Tried to unmap a page that was not mapped.");
- }
-
- auto pml4 = this;
- 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();
-
- (*pml1)[pml_index<1>(page)].clear();
-
- if (pml1->empty())
- {
- auto pml1_frame = (*pml2)[pml_index<2>(page)].frame().value();
- active_frame_allocator().release(pml1_frame);
- (*pml2)[pml_index<2>(page)].clear();
- }
-
- if (pml2->empty())
- {
- auto pml2_frame = (*pml3)[pml_index<3>(page)].frame().value();
- active_frame_allocator().release(pml2_frame);
- (*pml3)[pml_index<3>(page)].clear();
- }
-
- if (pml3->empty())
- {
- auto pml3_frame = (*pml4)[pml_index<4>(page)].frame().value();
- active_frame_allocator().release(pml3_frame);
- (*pml4)[pml_index<4>(page)].clear();
- }
+ return std::bit_cast<paging_root *>(recursive_base);
}
} // namespace teachos::memory::x86_64 \ 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
index 47148f0..fe4fd50 100644
--- a/arch/x86_64/src/memory/recursive_page_mapper.cpp
+++ b/arch/x86_64/src/memory/recursive_page_mapper.cpp
@@ -7,13 +7,63 @@
namespace teachos::memory::x86_64
{
+ 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 < 5uz)
+ auto do_map(recursive_page_table<Level> * pml, page page, frame_allocator & allocator, 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, page page, frame frame, page_mapper::flags flags) -> std::optional<std::byte *>
+ {
+ auto index = pml_index<1>(page);
+ if ((*pml)[index].present())
+ {
+ 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(frame_allocator & allocator)
: m_allocator{&allocator}
{}
auto recursive_page_mapper::map(page page, frame frame, flags flags) -> std::byte *
{
- return paging_root::get().map(page, frame, to_table_flags(flags)).value_or(nullptr);
+ auto pml4 = static_cast<recursive_page_table<4> *>((paging_root::get()));
+
+ return std::optional{pml4}
+ .and_then([&](auto pml) -> auto { return do_map(pml, page, *m_allocator, flags); })
+ .and_then([&](auto pml) -> auto { return do_map(pml, page, *m_allocator, flags); })
+ .and_then([&](auto pml) -> auto { return do_map(pml, page, *m_allocator, flags); })
+ .and_then([&](auto pml) -> auto { return do_map(pml, page, frame, flags); })
+ .value_or(nullptr);
}
auto recursive_page_mapper::unmap(page page) -> void
@@ -26,12 +76,39 @@ namespace teachos::memory::x86_64
auto recursive_page_mapper::try_unmap(page page) noexcept -> bool
{
- auto & root = paging_root::get();
- if (!root.translate(page))
+ if (!paging_root::get()->translate(page))
{
return false;
}
- root.unmap(page);
+
+ 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();
+
+ (*pml1)[pml_index<1>(page)].clear();
+
+ if (pml1->empty())
+ {
+ auto pml1_frame = (*pml2)[pml_index<2>(page)].frame().value();
+ m_allocator->release(pml1_frame);
+ (*pml2)[pml_index<2>(page)].clear();
+ }
+
+ if (pml2->empty())
+ {
+ auto pml2_frame = (*pml3)[pml_index<3>(page)].frame().value();
+ m_allocator->release(pml2_frame);
+ (*pml3)[pml_index<3>(page)].clear();
+ }
+
+ if (pml3->empty())
+ {
+ auto pml3_frame = (*pml4)[pml_index<4>(page)].frame().value();
+ m_allocator->release(pml3_frame);
+ (*pml4)[pml_index<4>(page)].clear();
+ }
+
return true;
}
diff --git a/arch/x86_64/src/memory/scoped_mapping.cpp b/arch/x86_64/src/memory/scoped_mapping.cpp
index e243dc9..fa68387 100644
--- a/arch/x86_64/src/memory/scoped_mapping.cpp
+++ b/arch/x86_64/src/memory/scoped_mapping.cpp
@@ -14,14 +14,16 @@ namespace teachos::memory::x86_64
scoped_mapping::scoped_mapping(scoped_mapping && other) noexcept
: m_page{std::exchange(other.m_page, page{})}
+ , m_mapper{std::exchange(other.m_mapper, nullptr)}
, m_mapped{std::exchange(other.m_mapped, false)}
{}
- scoped_mapping::scoped_mapping(page page)
+ scoped_mapping::scoped_mapping(page page, page_mapper & mapper)
: m_page{page}
+ , m_mapper{&mapper}
, m_mapped{false}
{
- if (paging_root::get().translate(page))
+ if (paging_root::get()->translate(page))
{
system::panic("[MEM] Tried to map a page that is already mapped!");
}
@@ -44,14 +46,14 @@ namespace teachos::memory::x86_64
auto scoped_mapping::map(frame frame, page_table::entry::flags flags) -> std::byte *
{
- auto result = active_page_mapper().map(m_page, frame, to_mapper_flags(flags));
+ auto result = m_mapper->map(m_page, frame, to_mapper_flags(flags));
m_mapped = true;
return result;
}
auto scoped_mapping::unmap() -> void
{
- active_page_mapper().unmap(m_page);
+ m_mapper->unmap(m_page);
m_mapped = false;
}
@@ -59,6 +61,7 @@ namespace teachos::memory::x86_64
{
using std::swap;
swap(lhs.m_page, rhs.m_page);
+ swap(lhs.m_mapper, rhs.m_mapper);
swap(lhs.m_mapped, rhs.m_mapped);
}