diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2026-03-16 19:03:53 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2026-03-16 19:03:53 +0100 |
| commit | 69a92ce3077f01ce43daef5681db298594a4badc (patch) | |
| tree | de3a97018853d453c550bba7a1507211ae28fd31 /arch/x86_64/include | |
| parent | cc5f6ef95acb7a0024c43eba314eb1f3563b41b8 (diff) | |
| download | teachos-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.hpp | 3 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/memory/page_table.hpp | 127 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/memory/paging_root.hpp | 27 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/memory/recursive_page_mapper.hpp | 22 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/memory/scoped_mapping.hpp | 68 |
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 |
