aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/include
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/x86_64/include
parentcc5f6ef95acb7a0024c43eba314eb1f3563b41b8 (diff)
downloadteachos-69a92ce3077f01ce43daef5681db298594a4badc.tar.xz
teachos-69a92ce3077f01ce43daef5681db298594a4badc.zip
x86_64/memory: remove recursive mapping
Diffstat (limited to 'arch/x86_64/include')
-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
5 files changed, 5 insertions, 242 deletions
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