aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@ost.ch>2025-12-12 14:11:07 +0100
committerFelix Morgner <felix.morgner@ost.ch>2025-12-12 14:11:07 +0100
commit682f28543be1ef7a315284c932075be1976e2930 (patch)
tree159198a415732989da7b0905ecd967db6e04e11b
parent50c9c9a1d963e66f7658ab31e9ecd65bf227cfff (diff)
downloadteachos-682f28543be1ef7a315284c932075be1976e2930.tar.xz
teachos-682f28543be1ef7a315284c932075be1976e2930.zip
x86_64/pre: remove ported implementation
-rw-r--r--arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp67
-rw-r--r--arch/x86_64/pre/include/arch/memory/allocator/concept.hpp21
-rw-r--r--arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp74
-rw-r--r--arch/x86_64/pre/include/arch/memory/main.hpp30
-rw-r--r--arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp170
-rw-r--r--arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp59
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp206
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp39
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp180
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp121
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/page_table.hpp157
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp64
-rw-r--r--arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp91
-rw-r--r--arch/x86_64/pre/src/memory/allocator/area_frame_allocator.cpp88
-rw-r--r--arch/x86_64/pre/src/memory/allocator/tiny_frame_allocator.cpp34
-rw-r--r--arch/x86_64/pre/src/memory/main.cpp77
-rw-r--r--arch/x86_64/pre/src/memory/multiboot/elf_symbols_section.cpp16
-rw-r--r--arch/x86_64/pre/src/memory/multiboot/reader.cpp135
-rw-r--r--arch/x86_64/pre/src/memory/paging/active_page_table.cpp101
-rw-r--r--arch/x86_64/pre/src/memory/paging/inactive_page_table.cpp20
-rw-r--r--arch/x86_64/pre/src/memory/paging/page_entry.cpp78
-rw-r--r--arch/x86_64/pre/src/memory/paging/page_table.cpp140
-rw-r--r--arch/x86_64/pre/src/memory/paging/temporary_page.cpp29
-rw-r--r--arch/x86_64/pre/src/memory/paging/virtual_page.cpp36
24 files changed, 0 insertions, 2033 deletions
diff --git a/arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp b/arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp
deleted file mode 100644
index a86c9b7..0000000
--- a/arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#ifndef TEACHOS_X86_64_MEMORY_AREA_ALLOCATOR_HPP
-#define TEACHOS_X86_64_MEMORY_AREA_ALLOCATOR_HPP
-
-// #include "arch/memory/allocator/physical_frame.hpp"
-// #include "arch/memory/multiboot/reader.hpp"
-
-#include <optional>
-
-namespace x86_64::memory
-{
- /**
- * @brief Allocates memory linearly using memory areas read from the multiboot2 information pointer and leaks any
- * deallocated frames.
- */
- struct area_frame_allocator
- {
- /**
- * @brief Constructor.
- *
- * @param mem_info Structure containg all relevant information to map and allocate memory.
- */
- area_frame_allocator(multiboot::memory_information const & mem_info);
-
- /**
- * @brief Allocate memory by finding and returning a free physical frame.
- *
- * @note The physical_frame allocation executes multiple checks before returning
- * the physical_frame that is available to allocate. It must at least
- * do the following:
- * - check if the next_free_frame is within the current_area
- * - check if the next_free_frame is actually free
- * - update the next_free_frame after finding a free physical_frame
- *
- * @return next free physical frame or nullopt if none was found.
- */
- auto allocate_frame() -> std::optional<physical_frame>;
-
- /**
- * @brief Deallocates a previously allocated physical frame.
- *
- * @note Simply does nothing, because the simply area frame
- * allocator implementation does not keep track of free or used frames and can therefore not deallocate, because it
- * does not know which frames have been alocated in the first place.
- *
- * @param physical_frame Previously allocated physical_frame that should be deallocated.
- */
- auto deallocate_frame(physical_frame const & physical_frame) -> void;
-
- private:
- /**
- * @brief Find the next memory area and write it into current_area.
- */
- auto choose_next_area() -> void;
-
- physical_frame next_free_frame; ///< The physical_frame after the last allocated one.
- std::optional<multiboot::memory_area> current_area; ///< The current memory area.
- multiboot::memory_area_container const
- memory_areas; ///< All memory areas in custom container allows to use std::ranges.
- physical_frame const kernel_start; ///< The start address of the kernel code in memory.
- physical_frame const kernel_end; ///< The end address of the kernel code in memory.
- physical_frame const multiboot_start; ///< The start address of the multiboot code in memory.
- physical_frame const multiboot_end; ///< The end address of the multiboot code in memory.
- };
-
-} // namespace x86_64::memory
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_AREA_FRAME_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/allocator/concept.hpp b/arch/x86_64/pre/include/arch/memory/allocator/concept.hpp
deleted file mode 100644
index 2d3f4ae..0000000
--- a/arch/x86_64/pre/include/arch/memory/allocator/concept.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP
-
-#include "arch/memory/allocator/physical_frame.hpp"
-
-#include <optional>
-
-namespace teachos::arch::memory::allocator
-{
- /**
- * @brief Frame allocator concept required for allocating and deallocating physical frames in memory.
- */
- template<typename T>
- concept FrameAllocator = requires(T t, physical_frame const & a) {
- { t.allocate_frame() } -> std::same_as<std::optional<physical_frame>>;
- { t.deallocate_frame(a) } -> std::same_as<void>;
- };
-
-} // namespace teachos::arch::memory::allocator
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_CONCEPT_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp b/arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp
deleted file mode 100644
index 1e4746d..0000000
--- a/arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP
-
-#include "arch/memory/allocator/concept.hpp"
-#include "arch/memory/allocator/physical_frame.hpp"
-
-#include <array>
-
-namespace teachos::arch::memory::allocator
-{
- namespace
- {
- constexpr uint8_t TINY_ALLOCATOR_FRAMES_COUNT = 3U;
- }
-
- /**
- * @brief Allocates memory using memory areas read from the multiboot2 information pointer. Does not allocate its own
- * frames, but uses the necessary three frames provided by another allocator to map one virtual level 1 page entry and
- * the necessary upper layers.
- */
- struct tiny_frame_allocator
- {
- /**
- * @brief Constructor.
- *
- * @tparam T Contract the allocator that should be used to actually allocate and deallocate, the underlying three
- * frames has to follow.
- *
- * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
- * entries when the underlying frames are created.
- */
- template<allocator::FrameAllocator T>
- tiny_frame_allocator(T & allocator)
- : frames{}
- {
- // Has to be done this way, because constructing the constructor with the data from allocator.allocate_frames(),
- // does not work because it would set the value correctly but because we pass it as an std::optional it would not
- // set the engaged flag. Meaning the has_value() method would still return false.
- for (auto & frame : frames)
- {
- auto allocated = allocator.allocate_frame();
- if (allocated.has_value())
- {
- frame.emplace(allocated.value());
- }
- }
- }
-
- /**
- * @brief Allocate memory by finding and returning one of the three free physical frames.
- *
- * @return First free physical frames of the three frames held by this allocator or nullopt if we used up all three
- * frames already.
- */
- auto allocate_frame() -> std::optional<physical_frame>;
-
- /**
- * @brief Deallocates one of the three previously allocated physical frames.
- *
- * @note If more than the three frames are deallocated the method will halt execution, because it can only hold 3
- * frames.
- *
- * @param physical_frame Previously allocated physical_frame that should be deallocated.
- */
- auto deallocate_frame(physical_frame const & physical_frame) -> void;
-
- private:
- std::array<std::optional<physical_frame>, TINY_ALLOCATOR_FRAMES_COUNT> frames =
- {}; ///< Container that holds the frames allocated by another allocator.
- };
-
-} // namespace teachos::arch::memory::allocator
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_ALLOCATOR_TINY_FRAME_ALLOCATOR_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/main.hpp b/arch/x86_64/pre/include/arch/memory/main.hpp
deleted file mode 100644
index d51815f..0000000
--- a/arch/x86_64/pre/include/arch/memory/main.hpp
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP
-
-#include "arch/memory/paging/page_entry.hpp"
-
-#include <cstdint>
-
-namespace teachos::arch::memory
-{
-
- /**
- * @brief Maps a heap section to a page.
- *
- * @param heap_start Start-address of the heap.
- * @param heap_size Size of the heap.
- * @param additional_flags Additional flags to apply to the page entry.
- */
- auto remap_heap(std::size_t heap_start, std::size_t heap_size, paging::entry::bitset additional_flags) -> void;
-
- /**
- * @brief Initializes memory management.
- *
- * @note Enables the necessary register flags and remaps the kernel,
- * elf_sections, vga_text and the heap.
- */
- auto initialize_memory_management() -> void;
-
-} // namespace teachos::arch::memory
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_MAIN_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp b/arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp
deleted file mode 100644
index 348c159..0000000
--- a/arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp
+++ /dev/null
@@ -1,170 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
-
-// #include "arch/memory/multiboot/info.hpp"
-// #include "arch/stl/container.hpp"
-// #include "arch/stl/contiguous_pointer_iterator.hpp"
-
-#include <bitset>
-#include <cstdint>
-
-namespace teachos::arch::memory::multiboot
-{
- /**
- * @brief Defines all elf section types an elf section header can have.
- *
- * @note See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information.
- */
- enum struct elf_section_type : uint32_t
- {
- INACTIVE, ///< (SHT_NULL) Unused, meaning all values are zeroed out.
- PROGRAMM, ///< (SHT_PROGBITS) Program data (DATA, CODE).
- SYMBOL_TABLE, ///< (SHT_SYMBTAB) Contains actual entries pointed to in symbol hash table.
- STRING_TABLE, ///< (SHT_STRTAB) Contains symbols, section and debugging null-terminated strings.
- RELOCATION_ENTRY_WITH_ADDENDS, ///< (SHT_RELA) Only used on 64 bit systems.
- SYMBOL_HASH_TABLE, ///< (SHT_HASH) Hash table used by dynamic linker to locate symbols.
- DYNAMIC, ///< (SHT_DYNAMIC) Contains dynamic linking information.
- NOTE, ///< (SHT_NOTE) Stores information that marks files in some way.
- EMPTY, ///< (SHT_NOBITS) Program data section, that occupies no space in the file (.bss).
- RELOCATION_ENTRY_WITHOUT_ADDENDS, ///< (SHT_REL) Only used on 32 bit systems.
- UNSPECIFIED, ///< (SHT_SHLIB) Reserved but has unspecified semantics.
- DYNAMIC_SYMBOL_TABLE, ///< (SHT_DYNSYM) Holds minimal set of symbols adequate for dynamic linking.
- INITALIZATION_FUNCTION_ARRAY = 14, ///< (SHT_INIT_ARRAY) Array of pointers to intialization functions () -> void.
- TERMINATION_FUNCTION_ARRAY, ///< (SHT_FINI_ARRAY) Array of pointers to termination functions () -> void.
- PRE_INITALIZATION_FUNCTION_ARRAY ///< (SHT_PRE_INIT_ARRAY) Array of pointers to functions invoked before other
- ///< initalization functions () -> void.
- };
-
- /**
- * @brief Defines helper function for all states that the elf section flags of an elf section header can
- * have.
- *
- * @note See https://docs.oracle.com/cd/E19683-01/816-1386/chapter6-94076/index.html for more information.
- */
- struct elf_section_flags
- {
- /**
- * @brief Possible set bits in our underlying std::bitset and the meaning when they are set.
- */
- enum bitset : uint32_t
- {
- WRITABLE = 1U << 0U, ///< (SHF_WRITE) Section is writable at runtime. If it isn't then the section
- ///< is assumed to be READONLY and only that flag is shown in the objdump.
- OCCUPIES_MEMORY = 1U << 1U, ///< (SHF_ALLOC) Section occupies memory during execution.
- ///< ALLOC flag is shown in the objdump.
- EXECUTABLE_CODE = 1U << 2U, ///< (SHF_EXECINSTR) Section is executable. CODE flag is shown in the object dump.
- DUPLICATE_DATA = 1U << 4U, ///< (SHF_MERGE) Section might be merged with another section.
- CONTAINS_STRING = 1U << 5U, ///< (SHF_STRINGS) Section contains null-terminated strings.
- SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX =
- 1U << 6U, ///< (SHF_INFO_LINK) Section contains the section header table index in the (sh_info)
- ///< additional_information variable.
- PRESERVE_ORDERING_AFTER_COMBINATION =
- 1U << 7U, ///< (SHF_LINK_ORDER) Section preserves order after combining with another section.
- REQUIRES_SPECIAL_OS_PROCESSING =
- 1U << 8U, ///< (SHF_OS_NONCONFORMING) Section requires non-standard OS specific handling of its code or
- ///< data, which does not confirm to standard ELF specifications.
- SECTION_GROUP_MEMBER = 1U << 9U, ///< (SHF_GROUP) Section is a member of a section group.
- HOLDS_THREAD_LOCAL_DATA = 1U << 10U, ///< (SHF_TLS) Section holds thread-local data.
- COMPRESSED = 1U << 11U, ///< (SHF_COMPRESSED) Section contains compressed data.
- SPECIAL_ORDERING_REQUIREMENTS =
- 1U << 30U, ///< (SHF_ORDERED) Section has special ordering requirements, meaning it
- ///< should be ordered in relation to other sections of the same type.
- EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED = 1U << 31U, ///< (SHF_EXCLUDE)Section is excluded unless referenced or
- ///< allocated, used for LTO (Link-Time Optimizations).
- };
-
- /**
- * @brief Constructor.
- *
- * @param flags Actual value read from the elf section header, which should be converted into a std::bitset, to
- * allow reading the state of single bits more easily.
- */
- explicit elf_section_flags(uint64_t flags)
- : flags(flags)
- {
- // Nothing to do
- }
-
- /**
- * @brief Checks if the given std::bitset is a subset or equivalent to the underlying std::bitset.
- *
- * @note Meaning that all bits that are set in the given std::bitset also have to be set in the underlyng
- * std::bitset. Any additional bits that are set are not relevant.
- *
- * @param other Flags that we want to compare against and check if the underlying std::bitset has the same bits set.
- * @return Whether the given flags are a subset or equivalent with the underlying std::bitset.
- */
- auto contains_flags(std::bitset<64U> other) const -> bool;
-
- /**
- * @brief Allows to compare the underlying std::bitset of two instances.
- *
- * @param other Other instance that we want to compare with.
- * @return Whether the underlying std::bitset of both types is the same.
- */
- auto operator==(elf_section_flags const & other) const -> bool = default;
-
- private:
- std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 21 - 28 are reserved for operating
- ///< system specific semantics and bits 29 - 32 are reserved for processor specific
- ///< semantics. Bits 33 - 64 are unused for compatability with ELF32.
- };
-
- /**
- * @brief Defines the data included in a section header, where each section has exactly one section header.
- *
- * @note See https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html for more information.
- */
- struct elf_section_header
- {
- uint32_t name_table_index; ///< Index into the section header string table, specifies the name of the section.
- elf_section_type type; ///< Categorizes the sections content and semantics.
- elf_section_flags flags; ///< 1-bit flgas that describe section attributes.
- uint64_t physical_address; ///< If section appears in memory image of a process, gives address at which the
- ///< sections first byte should reside, otherwise 0.
- uint64_t file_offset; ///< Offset from the beginning of the file to the first byte in the section. SHT_NOBITS
- ///< contains the conceptual placement instead (because it occupies no space in the file).
- uint64_t section_size; ///< Complete section size in bytes, SHT_NOBITS may have non-zero value but will always
- ///< occupy no space in the file.
- uint32_t other_section; ///< Section header table index link, behaviour varies on type
- ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link.
- uint32_t additional_information; ///< Extra information, behaviour varies on type
- ///< https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html#sh_link.
- uint64_t address_alignment; ///< Possible address alignment constraints. Value of virutal_address must be 0 % value
- ///< of address_alignment. Value 0 or 1 mean no alignment constraints.
- uint64_t fixed_table_entry_size; ///< If sections holds table with fixed-sized entries, this gives the size in
- ///< bytes of each entry.
-
- /**
- * @brief Detect whether a section header is inactive or not, should always be the case for the first entry in the
- * sections table.
- *
- * @return Whether the current section header is actually null or not, requires all fields besides section_size and
- * other_section to contain 0.
- */
- auto is_null() const -> bool;
- };
-
- // /**
- // * @brief Defines an entry in the multi_boot_tag array of the multi_boot_info struct, of type
- // * multi_boot_tag_type::ELF_SECTIONS.
- // *
- // * @note The first section in the sections array will always be INACTIVE, there can only ever be one DYNAMIC
- // section
- // * and only either one DYNAMIC_SYMBOL_TABLE or SYMBOL_TABLE.
- // */
- // struct elf_symbols_section_header
- // {
- // tag info; ///< Basic multi_boot_tag information.
- // uint32_t number_of_sections; ///< Number of sections in the sections array.
- // uint32_t entry_size; ///< Size of each entry in the sections array.
- // uint32_t section_index; ///< Index to the string table used for symbol names.
- // std::byte end; ///< Marks the end of the tag, used to mark the beginning of any additional data.
- // ///< contained in the section, to ensure byte alignment is actually 4 byte.
- // };
-
- // using elf_section_header_container = stl::container<stl::contiguous_pointer_iterator<elf_section_header>>;
-
-} // namespace teachos::arch::memory::multiboot
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_ELF_SYBOLS_SECTION_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp
deleted file mode 100644
index 275e5e2..0000000
--- a/arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
-
-// #include "arch/memory/multiboot/elf_symbols_section.hpp"
-// #include "arch/memory/multiboot/memory_map.hpp"
-
-#include "arch/memory/multiboot/elf_symbols_section.hpp"
-
-#include <multiboot2/information.hpp>
-
-#include <cstdint>
-#include <span>
-
-namespace teachos::arch::memory::multiboot
-{
- /**
- * @brief Contains all relevant information to map and allocate memory that is read from the multiboot2 information
- * structure.
- */
- struct memory_information
- {
- std::size_t kernel_start; ///< Start address of the kernel code in memory.
- std::size_t kernel_end; ///< End address of the kernel code in memory.
- multiboot2::elf_symbols; ///< Contains non-owning pointers to all kernel sections.
- std::size_t multiboot_start; ///< Start address of the multiboot code in memory.
- std::size_t multiboot_end; ///< End address of the multiboot code in memory.
- // std::sp
- // memory_area_container areas; ///< Contains non-owning pointers to all memory areas.
- };
-
- /**
- * @brief Reads the relevant multiboot2 information data from memory.
- *
- * @note This is done using the multiboot_information_pointer, which marks the start of the multiboot2 data. The
- * indivdual headers we have to read are 8 byte aligned, whereas the data contained in those headers does not have to
- * be. All sections that are read additionaly receive some sanity to ensure the read address is actually pointing to
- * the expected structure, if they are not this method will assert.
- *
- * The memory_information variables are calcualted like this:
- * - kernel_start: Calculated by getting the lowest address specified in the elf symbols headers.
- * - kernel_end: Calculated by getting the highest address specified in the elf symbols headers and adding the length
- * of that section.
- * - multiboot_start: Calcualted by simply getting the value of the multiboot information pointer, because it already
- * contains the address pointint to the start of the multiboot2 data.
- * - multiboot_end: Calcualted by getting the value of the multiboot information pointer and adding the total size of
- * the complete multiboot2 data
- * - memory_areas: Calculated by simply accessing the address of the entries variable in the memory map header
- * structure.
- * - area_count: Calculated by subtracing the memory map header size from the total tag size, which results in the
- * remaining size (size of the entries array), this size is then divided by the size of one entry in that array, which
- * should be 24 bytes.
- *
- * @return Relevant data read from multiboot2.
- */
- auto read_multiboot2() -> memory_information;
-
-} // namespace teachos::arch::memory::multiboot
-
-#endif // TEACHOS_ARCH_X86_64_MEMORY_MULTIBOOT_READER_HPP
diff --git a/arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp
deleted file mode 100644
index abefd61..0000000
--- a/arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp
+++ /dev/null
@@ -1,206 +0,0 @@
-#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP
-#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP
-
-#include "arch/exception_handling/assert.hpp"
-#include "arch/kernel/cpu/tlb.hpp"
-#include "arch/memory/allocator/concept.hpp"
-#include "arch/memory/paging/virtual_page.hpp"
-
-#include <array>
-#include <bitset>
-#include <optional>
-
-namespace teachos::arch::memory::paging
-{
- /**
- * @brief Currently actively by the CPU used level 4 page table, is used to ensure there is only ever one valid
- * instance and it cannot be copied or constructed again.
- */
- struct active_page_table
- {
- /**
- * @brief Creates a single instance of an active level 4 page table table and returns the created instance or
- * alternatively returns the previously created instance instead. The instance is owned by this method and is
- * static, meaning it lives on for the complete lifetime of the program.
- *
- * @return Active single unique instance of the level 4 page table.
- */
- auto static create_or_get() -> active_page_table &;
-
- /**
- * @brief Index operator overload to access specific mutable entry directy of the level 4 page table.
- *
- * @param index Index of the entry we want to access and only read.
- * @return Entry at the given table index.
- */
- auto operator[](std::size_t index) -> entry &;
-
- /**
- * @brief Translates virtual address into corresponding physical address. Calls translate_page under the hood.
- *
- * @param address Virtual address we want to translate into physical one.
- * @return Physical address corresponding to the provided virtual address.
- */
- auto translate_address(virtual_address address) -> std::optional<allocator::physical_address>;
-
- /**
- * @brief Translates page into physical frame, will first attempt to parse normally using default page size and if
- * it failed attempt to parse using huge pages.
- *
- * @param page Page to translate into physical frame.
- * @return Physical frame corresponding to the provided virtual page.
- */
- auto translate_page(virtual_page page) -> std::optional<allocator::physical_frame>;
-
- /**
- * @brief Translates huge page into actual physical frame.
- *
- * @param page Page to translate into physical frame.
- * @return Physical frame corresponding to the provided virtual page.
- */
- auto translate_huge_page(virtual_page page) -> std::optional<allocator::physical_frame>;
-
- /**
- * @brief Maps a virtual page to a physical frame in the page table with the specified flags.
- *
- * @note Allocates and maps an entry in every page level if it does not exists yet down to level 1. If the level 1
- * page table already exists it halts execution instead.
- *
- * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and
- * deallocate method.
- * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
- * entries when a new page table is required.
- * @param page Virtual page that is being mapped.
- * @param frame Physical frame that the virtual page will be mapped to.
- * @param flags A bitset of flags that configure the page table entry for this mapping.
- */
- template<allocator::FrameAllocator T>
- auto map_page_to_frame(T & allocator, virtual_page page, allocator::physical_frame frame, std::bitset<64U> flags)
- -> void
- {
- auto current_handle = active_handle;
-
- for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level)
- {
- current_handle = current_handle.next_table_or_create(allocator, page.get_level_index(level), flags);
- }
-
- auto & level1_entry = current_handle[page.get_level_index(page_table_handle::LEVEL1)];
- arch::exception_handling::assert(!level1_entry.contains_flags(entry::HUGE_PAGE),
- "[Page Mapper] Unable to map huge pages");
- arch::exception_handling::assert(level1_entry.is_unused(), "[Page Mapper] Page table entry is already used");
- level1_entry.set_entry(frame, flags.to_ulong() | entry::PRESENT);
- }
-
- /**
- * @brief Allocates the next free frame and then uses that frame to call map_page_to_frame.
- *
- * @see map_page_to_frame
- */
- template<allocator::FrameAllocator T>
- auto map_page_to_next_free_frame(T & allocator, virtual_page page, std::bitset<64U> flags) -> void
- {
- auto const frame = allocator.allocate_frame();
- exception_handling::assert(frame.has_value(), "[Page mapper] Out of memory exception");
- map_page_to_frame(allocator, page, frame.value(), flags);
- }
-
- /**
- * @brief Gets the corresponding page the given frame has to be contained in and uses that to call
- * map_page_to_frame.
- *
- * @see map_page_to_frame
- */
- template<allocator::FrameAllocator T>
- auto identity_map(T & allocator, allocator::physical_frame frame, std::bitset<64U> flags) -> void
- {
- auto const page = virtual_page::containing_address(frame.start_address());
- map_page_to_frame(allocator, page, frame, flags);
- }
-
- /**
- * @brief Unmaps the virtual page from the previously mapped to physical frame and resets the flags.
- *
- * @note For the unmap function to deallocates and unmaps correctly, the entry in every page level if this page was
- * the last one up to level 4 should be unmapped and ensured to clear the Translation Lookaside Buffer, so that the
- * unmapped value is removed from cache as well. This is currently not done and instead we only dallocate and unmap
- * the level 1 page table entry, this is the case because it conflicts with our recursive mapping for the temporary
- * page, which requires the other page table entries to walk to the actual level 4 page table. If we remove all page
- * table entries beforehand, we therefore can not remap the kernel anymore.
- *
- * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and
- * deallocate method.
- * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
- * entries when a new page table is required.
- * @param page Virtual page that is being unmapped.
- */
- template<allocator::FrameAllocator T>
- auto unmap_page(T & allocator, virtual_page page) -> void
- {
- exception_handling::assert(translate_page(page).has_value(),
- "[Page Mapper] Attempted to unmap page, which has not been mapped previously");
-
- auto current_handle = active_handle;
-
- for (auto level = page_table_handle::LEVEL4; level != page_table_handle::LEVEL1; --level)
- {
- auto const level_index = page.get_level_index(level);
- auto const next_handle = current_handle.next_table(level_index);
- // The next table method failed even tough the page has to be mapped already, because translate_page did not
- // fail. This can only mean that we attempted to unmap a huge page, which is not supported in the first place.
- exception_handling::assert(next_handle.has_value(), "[Page Mapper] Unable to unmap huge pages");
- current_handle = next_handle.value();
- }
-
- unmap_page_table_entry(allocator, page, current_handle);
- kernel::cpu::tlb_flush(page.start_address());
- }
-
- private:
- /**
- * @brief Private constructor should only be used by create or get method, which ensures to create only ever one
- * instance.
- *
- * @param active_handle Handle to the underlying currently active level 4 page table.
- */
- active_page_table(page_table_handle active_handle);
-
- /**
- * @brief Deleted copy constructor.
- */
- active_page_table(active_page_table const &) = delete;
-
- /**
- * @brief Deleted copy assignment operator.
- */
- active_page_table & operator=(active_page_table const &) = delete;
-
- /**
- * @brief Unmaps specific page at the current internal handle level.
- *
- * @tparam T Type constraint of the allocator, being that is follows the given concept and contains an allocate and
- * deallocate method.
- * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate
- * entries *when a new page table is required.
- * @param page Virtual page that is being unmapped.
- * @param handle Page Table handle we want to access the entry that should be cleared on.
- */
- template<allocator::FrameAllocator T>
- auto static unmap_page_table_entry(T & allocator, virtual_page page, page_table_handle & handle) -> void
- {
- auto level_index = page.get_level_index(handle.get_level());
- auto & entry = handle[level_index];
- auto const frame = entry.calculate_pointed_to_frame();
- exception_handling::assert(frame.has_value(),
- "[Page Mapper] Attempted to unmap page, which has not been mapped previously");
- entry.set_unused();
- allocator.deallocate_frame(frame.value());
- }
-
- public:
- page_table_handle active_handle; ///< Underlying active level 4 page table
- };
-