From 682f28543be1ef7a315284c932075be1976e2930 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Fri, 12 Dec 2025 14:11:07 +0100 Subject: x86_64/pre: remove ported implementation --- .../arch/memory/allocator/area_frame_allocator.hpp | 67 ------- .../pre/include/arch/memory/allocator/concept.hpp | 21 --- .../arch/memory/allocator/tiny_frame_allocator.hpp | 74 -------- arch/x86_64/pre/include/arch/memory/main.hpp | 30 --- .../arch/memory/multiboot/elf_symbols_section.hpp | 170 ----------------- .../pre/include/arch/memory/multiboot/reader.hpp | 59 ------ .../arch/memory/paging/active_page_table.hpp | 206 --------------------- .../arch/memory/paging/inactive_page_table.hpp | 39 ---- .../include/arch/memory/paging/kernel_mapper.hpp | 180 ------------------ .../pre/include/arch/memory/paging/page_entry.hpp | 121 ------------ .../pre/include/arch/memory/paging/page_table.hpp | 157 ---------------- .../include/arch/memory/paging/temporary_page.hpp | 64 ------- .../include/arch/memory/paging/virtual_page.hpp | 91 --------- .../src/memory/allocator/area_frame_allocator.cpp | 88 --------- .../src/memory/allocator/tiny_frame_allocator.cpp | 34 ---- arch/x86_64/pre/src/memory/main.cpp | 77 -------- .../src/memory/multiboot/elf_symbols_section.cpp | 16 -- arch/x86_64/pre/src/memory/multiboot/reader.cpp | 135 -------------- .../pre/src/memory/paging/active_page_table.cpp | 101 ---------- .../pre/src/memory/paging/inactive_page_table.cpp | 20 -- arch/x86_64/pre/src/memory/paging/page_entry.cpp | 78 -------- arch/x86_64/pre/src/memory/paging/page_table.cpp | 140 -------------- .../pre/src/memory/paging/temporary_page.cpp | 29 --- arch/x86_64/pre/src/memory/paging/virtual_page.cpp | 36 ---- 24 files changed, 2033 deletions(-) delete mode 100644 arch/x86_64/pre/include/arch/memory/allocator/area_frame_allocator.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/allocator/concept.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/allocator/tiny_frame_allocator.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/main.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/multiboot/elf_symbols_section.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/multiboot/reader.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/paging/active_page_table.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/paging/page_table.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp delete mode 100644 arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp delete mode 100644 arch/x86_64/pre/src/memory/allocator/area_frame_allocator.cpp delete mode 100644 arch/x86_64/pre/src/memory/allocator/tiny_frame_allocator.cpp delete mode 100644 arch/x86_64/pre/src/memory/main.cpp delete mode 100644 arch/x86_64/pre/src/memory/multiboot/elf_symbols_section.cpp delete mode 100644 arch/x86_64/pre/src/memory/multiboot/reader.cpp delete mode 100644 arch/x86_64/pre/src/memory/paging/active_page_table.cpp delete mode 100644 arch/x86_64/pre/src/memory/paging/inactive_page_table.cpp delete mode 100644 arch/x86_64/pre/src/memory/paging/page_entry.cpp delete mode 100644 arch/x86_64/pre/src/memory/paging/page_table.cpp delete mode 100644 arch/x86_64/pre/src/memory/paging/temporary_page.cpp delete mode 100644 arch/x86_64/pre/src/memory/paging/virtual_page.cpp (limited to 'arch') 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 - -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; - - /** - * @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 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 - -namespace teachos::arch::memory::allocator -{ - /** - * @brief Frame allocator concept required for allocating and deallocating physical frames in memory. - */ - template - concept FrameAllocator = requires(T t, physical_frame const & a) { - { t.allocate_frame() } -> std::same_as>; - { t.deallocate_frame(a) } -> std::same_as; - }; - -} // 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 - -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 - 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; - - /** - * @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, 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 - -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 -#include - -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>; - -} // 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 - -#include -#include - -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 -#include -#include - -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; - - /** - * @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; - - /** - * @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; - - /** - * @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 - 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 - 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 - 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 - 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 - 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 - }; - -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_ACTIVE_PAGE_TABLE_HPP diff --git a/arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp deleted file mode 100644 index 8d96740..0000000 --- a/arch/x86_64/pre/include/arch/memory/paging/inactive_page_table.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP - -#include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/paging/active_page_table.hpp" -#include "arch/memory/paging/temporary_page.hpp" - -namespace teachos::arch::memory::paging -{ - /** - * @brief By the CPU used level 4 page table. - */ - struct inactive_page_table - { - /** - * @brief Constructor. - * - * @param frame Frame that should be mapped as the level 4 page table. - */ - inactive_page_table(allocator::physical_frame frame); - - /** - * @brief Constructor. - * - * @param frame Frame that should be mapped as the level 4 page table. - * @param active_page_table Actual active page table that should be unmapped so we can map a new level 4 - * page table. - * @param temporary_page Temporary page that should be used to map the given frame as the new level 4 page - * table. - */ - inactive_page_table(allocator::physical_frame frame, active_page_table & active_page_table, - temporary_page & temporary_page); - - allocator::physical_frame page_table_level_4_frame; ///< Temporary level 4 page table - }; - -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_INACTIVE_PAGE_TABLE_HPP diff --git a/arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp deleted file mode 100644 index 581f142..0000000 --- a/arch/x86_64/pre/include/arch/memory/paging/kernel_mapper.hpp +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP - -#include "arch/kernel/cpu/control_register.hpp" -#include "arch/memory/paging/active_page_table.hpp" -#include "arch/memory/paging/inactive_page_table.hpp" -#include "arch/memory/paging/temporary_page.hpp" -#include "arch/video/vga/text.hpp" - -#include -#include - -namespace teachos::arch::memory::paging -{ - /** - * @brief Kernel mapper that allows to remap the kernel elf sections in C++. - * - * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. - */ - template - struct kernel_mapper - { - /** - * @brief Constructor. - * - * @param allocator Allocator that should be used to allocate frames for the remapping process. - * @param mem_info Information about elf kernel sections required for remapping process. - */ - kernel_mapper(T & allocator, multiboot::memory_information const & mem_info) - : allocator(allocator) - , mem_info(mem_info) - { - // Nothing to do - } - - /** - * @brief Remap the kernel, meaning we map the entire kernel and all of it's elf sections with the correct flags - * into memory and then replace the created mapping with the current one. - * - * @note We have to use a workaround with an - * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because - * remapping active kernel memory in the kernel wouldn't work. - */ - auto remap_kernel() -> void - { - // Set Page Global Enable bit - auto cr4 = kernel::cpu::read_control_register(kernel::cpu::control_register::CR4); - kernel::cpu::write_control_register(kernel::cpu::control_register::CR4, cr4 | 0x80); - - temporary_page temporary_page{virtual_page{0xCAFE'BABE}, allocator}; - decltype(auto) active_table = active_page_table::create_or_get(); - auto const frame = allocator.allocate_frame(); - exception_handling::assert(frame.has_value(), - "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); - inactive_page_table new_table{frame.value(), active_table, temporary_page}; - remap_elf_kernel_sections(new_table, temporary_page, active_table); - auto const old_table = switch_active_page_table(new_table); - // Turn old level 4 page table, mapped by assembler code into stack guard page. - // Only works if the identity mapped page tables by assembler are right above the stack. - auto const old_level_4_page = - virtual_page::containing_address(old_table.page_table_level_4_frame.start_address()); - active_table.unmap_page(allocator, old_level_4_page); - } - - private: - /** - * @brief Remaps the kernel elf sections. - * - * This is done with switching the current level 4 page table recursive - * mapping to any unmapped address in memory and then actually mapping the level 4 page table on that address. - * Once the remapping process is done we can restore the original recursive mapping with the complete remapped - * kernel. - * - * @note Because we change the entries we also have to ensure we flush the translation lookaside buffer, before we - * map the entries. - * - * @param inactive_table Level 4 page table we temporarily map the kernel into. - * @param temporary_page Temporary page that should be used for the mapping process and then - * unmapped once finished. - * @param active_table Active level 4 page table that has its recursive mapping overwritten temporarily and then - * restored once the process is finished. - */ - auto remap_elf_kernel_sections(inactive_page_table & inactive_table, temporary_page & temporary_page, - active_page_table & active_table) -> void - { - auto const backup = allocator::physical_frame::containing_address( - kernel::cpu::read_control_register(kernel::cpu::control_register::CR3)); - auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - - active_table[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - kernel::cpu::tlb_flush_all(); - map_elf_kernel_sections(active_table); - - page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); - kernel::cpu::tlb_flush_all(); - temporary_page.unmap_page(active_table); - } - - /** - * @brief Switches the current active table pointed to by the CR3 register with another page table that is currently - * inactive. - * - * @param new_table Inactive page table that should now be made active and replace the current active one. - * @return The previous active page table. - */ - auto switch_active_page_table(inactive_page_table new_table) -> inactive_page_table - { - auto const backup = allocator::physical_frame::containing_address( - kernel::cpu::read_control_register(kernel::cpu::control_register::CR3)); - auto const old_table = inactive_page_table{backup}; - - auto const new_address = new_table.page_table_level_4_frame.start_address(); - kernel::cpu::write_control_register(kernel::cpu::control_register::CR3, new_address); - return old_table; - } - - /** - * @brief Maps the required entries according to every elf section and it's contained frames. Additionally each of - * thoose frames gets the correct entry flags according to elf section flags. - * - * @param active_table Active level 4 page table that should be used to map the required elf sections into entries. - * Has had its recursive mapping temporarily replaced and points to unmapped place in memory. - */ - auto map_elf_kernel_sections(active_page_table & active_table) -> void - { - exception_handling::assert(!mem_info.sections.empty(), "[Kernel Mapper] Kernel elf sections empty"); - constexpr std::array USER_SECTION_BASES = { - 0x102000, // .boot_bss (Contains statically allocated variables) - 0x209000, // .stl_text (Contains code for custom std implementations and standard library code) - 0x217000, // .user_text (Contains the actual user code executed) - 0x21E000, // .user_data (Contains static user variables) - - 0x20A000 // .text (Necessary, because symbols for all template standard library features are placed here if - // they were first used in the Kernel Code Section) - }; - - for (auto const & section : mem_info.sections) - { - if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) - { - continue; - } - exception_handling::assert(section.physical_address % allocator::PAGE_FRAME_SIZE == 0U, - "[Kernel Mapper] Section must be page aligned"); - auto const start_frame = allocator::physical_frame::containing_address(section.physical_address); - // End address is exclusive, so that it is not part of the section anymore (one past the last frame of this - // section). But end frame would now point to the actual last frame and not one past the last frame, therefore - // we increment by one to get one past the last frame of this section. - auto const end_frame = - ++(allocator::physical_frame::containing_address(section.physical_address + section.section_size - 1)); - - allocator::frame_container::iterator const begin{start_frame}; - allocator::frame_container::iterator const end{end_frame}; - allocator::frame_container const frames{begin, end}; - entry entry{section.flags}; - - if (std::ranges::find(USER_SECTION_BASES, section.physical_address) != USER_SECTION_BASES.end()) - { - entry.set_user_accessible(); - } - - for (auto const & frame : frames) - { - active_table.identity_map(allocator, frame, entry.get_flags()); - } - } - - auto const vga_buffer_frame = - allocator::physical_frame::containing_address(video::vga::text::DEFAULT_VGA_TEXT_BUFFER_ADDRESS); - active_table.identity_map(allocator, vga_buffer_frame, entry::WRITABLE); - } - - T & allocator; - multiboot::memory_information const & - mem_info; ///< Information about elf kernel sections required for remapping process. - }; - -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_KERNEL_MAPPER_HPP diff --git a/arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp b/arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp deleted file mode 100644 index 8147c5c..0000000 --- a/arch/x86_64/pre/include/arch/memory/paging/page_entry.hpp +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP - -#include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/multiboot/elf_symbols_section.hpp" - -#include -#include - -namespace teachos::arch::memory::paging -{ - /** - * @brief Marks a specific entry in an actual page table. - */ - struct entry - { - /** - * @brief Possible set bits in our underlying std::bitset and the meaning when they are set. - */ - enum bitset : uint64_t - { - PRESENT = 1UL << 0UL, ///< Page is in memory and therefore present. - ///< is assumed to be READONLY and only that flag is shown in the objdump. - WRITABLE = 1UL << 1UL, ///< It is possible to write to the page. - USER_ACCESSIBLE = 1UL << 2UL, ///< Page can be accessed in user mode instead of only in kernel mode code. - WRITE_THROUGH_CACHING = 1UL << 3UL, ///< Write to the page go directly to memory instead of the cache. - DISABLED_CACHING = 1UL << 4UL, ///< Page uses caching. - ACCESSED = 1UL << 5UL, ///< Page is currently in use. - DIRTY = 1UL << 6UL, ///< Page has been writen too. - HUGE_PAGE = 1UL << 7UL, ///< Page is huge (2 MiB page size in P2 page table and 1 GiB in P3 page table, - ///< instead of 4 KiB). Has to be false for P1 and P4 page tables. - GLOBAL = 1UL << 8UL, ///< Page is not flushed from caches on address space switches (PGE bit of CR4 register - ///< has to be set) - EXECUTING_CODE_FORBIDDEN = - 1UL << 63UL, ///< Page is forbidden from executing code (NXE bit in the EFER register has to be set) - }; - - /** - * @brief Defaulted constructor. - */ - entry() = default; - - /** - * @brief Creates a new entry object from a 64bit address. Should follow the scheme where bit index 12 - 51 are the - * actual address and the other bits are flags. - * - * @param flags Flags that will be passed to underlying std::bitset. - */ - explicit entry(uint64_t flags); - - /** - * @brief Creates a new entry converting the given elf section flags into the corresponding correct entry flags. - * - * @note Enables us to set the correct flags on a entry depending on which elf section it is contained in. For - * example entries of .text sections should be executable and read only or entries of .data sections should be - * writable but not executable. - * - * @param elf_flags Elf section flags we want to convert into entry flags. - */ - explicit entry(multiboot::elf_section_flags elf_flags); - - /** - * @brief Whether the current page is unused, meaning the underlying std::bitset is 0. - * - * @return Current page is in memory. - */ - auto is_unused() const -> bool; - - /** - * @brief Marks the page as unused, meaning the underlying std::bitset is set to 0. - */ - auto set_unused() -> void; - - /** - * @brief Marks the page as accessible in User mode, meaning the underlying std::bitset has the 2nd bit aditonally - * set. - */ - auto set_user_accessible() -> void; - - /** - * @brief Calculates the physical frame this entry is pointing too, can be null if the page is not present in - * memory. - * - * @return Calculated physical frame entry is pointing too. - */ - auto calculate_pointed_to_frame() const -> std::optional; - - /** - * @brief Copies the address and flags from the given physical frame into the underlying std::bitset - * - * @param frame Physical frame that contains the address we want to copy into our underlying std::bitset. - * @param additional_flags Entry flags which will be copied into our underlying std::bitset. - */ - auto set_entry(allocator::physical_frame frame, std::bitset<64U> additional_flags) -> void; - - /** - * @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 Extracts only the flags from the underlying entry and ignores all bits that contain the physical address. - * - * @return Extracted entry flags, without the physical address. - */ - auto get_flags() const -> std::bitset<64U>; - - private: - std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be - ///< freely used for additional flags by the operating system. - }; - -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_ENTRY_HPP diff --git a/arch/x86_64/pre/include/arch/memory/paging/page_table.hpp b/arch/x86_64/pre/include/arch/memory/paging/page_table.hpp deleted file mode 100644 index 247086c..0000000 --- a/arch/x86_64/pre/include/arch/memory/paging/page_table.hpp +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP - -#include "arch/exception_handling/assert.hpp" -#include "arch/memory/allocator/concept.hpp" -#include "arch/memory/paging/page_entry.hpp" - -namespace teachos::arch::memory::paging -{ - constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. - - /** - * @brief Forward delcaration of the page_table, because it should only be accessible over the handle. - * - * @note The actual methods or constructor are not defined meaning they are not callable from outside. Instead the - * struct is only fully defined in the implementation (.cpp) file of the page table, and therefore the memthods are - * only accesible in that file. - */ - struct page_table; - - /** - * @brief Handle that ensures accessing the page table is safe because it adds additional checks to the next_table - * method and ensures it can only be called if the table level is not LEVEL1. - */ - struct page_table_handle - { - /** - * @brief Level of the page table. - * - * Level 1 will not be able to call next_table anymore, because it would result in - * attempting to access memory that it should not. - */ - enum level : uint8_t - { - LEVEL1, - LEVEL2, - LEVEL3, - LEVEL4 - }; - - /** - * @brief Constructor. - * - * @param table Underlying page table the handle should point to. - * @param table_level Level the underlying page table is on, used to ensure safety. - */ - page_table_handle(page_table * table, level table_level); - - /** - * @brief Set every entry of the page to unused. - */ - auto zero_entries() -> void; - - /** - * @brief Checks if all entries of this page are unused. - */ - auto is_empty() const -> bool; - - /** - * @brief Get the current table level. - * - * @return Current table level. - */ - auto get_level() const -> level; - - /** - * @brief Returns the next page table level from the given page table index. Meaning we - * use an index into a Level 4 page table to get the according Level 3 page table. - * - * @note If this method is called with a Level 1 page table it will instead assert and halt execution, because there - * is no furthere page table and mangeling up and returning the physical address would cause hard to debug issues. - * - * @param table_index Index of this page table in the page table one level lower. - */ - auto next_table(std::size_t table_index) const -> std::optional; - - /** - * @brief Call next_table and then checks if the table already exists, if it does not it will use the given - * allocator to get the next free frame and set the entry to that instead. - * - * @param allocator Reference to an allocator following the FrameAllocator concept, which is used to allocate - * entries when a new page table is required. - * @param table_index Index of this page table in the page table one level lower. - * @param flags A bitset of flags that configure the page table entry for this mapping. - */ - template - auto next_table_or_create(T & allocator, std::size_t table_index, std::bitset<64U> flags) -> page_table_handle - { - auto next_handle = next_table(table_index); - // If the next table method failed then it means that the page level of the frame we want allocate has not yet - // been created itself. So we have to do that before we are able to allocate the wanted frame. This has to be done - // for every level, meaning we potenitally create a level 4, level 3 and level 2 page entry, each pointing to a - // page table one level below. - if (!next_handle.has_value()) - { - auto const allocated_frame = allocator.allocate_frame(); - exception_handling::assert(allocated_frame.has_value(), "[Page mapper] Unable to allocate frame"); - this->operator[](table_index).set_entry(allocated_frame.value(), entry::PRESENT | entry::WRITABLE); - // There should now be an entry at the previously not existent index, therefore we can simply access it again. - next_handle = next_table(table_index); - exception_handling::assert(next_handle.has_value(), "[Page mapper] Unable to create new entry into page table"); - next_handle.value().zero_entries(); - } - - // Check if the now created or previously created level 4, level 3 or level 2 page entry is used by user - // accessible code. If it is that page entry needs to be user accesible as well. - entry entry{flags.to_ulong()}; - if (entry.contains_flags(entry::USER_ACCESSIBLE)) - { - this->operator[](table_index).set_user_accessible(); - } - return next_handle.value(); - } - - /** - * @brief Index operator overload to access specific mutable entry directy. - * - * @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 Index operator overload to access specific immutable entry directy. - * - * @param index Index of the entry we want to access and read or write. - * @return Entry at the given table index. - */ - auto operator[](std::size_t index) const -> entry const &; - - /** - * @brief Pre decrement operator on the page table level enum, is defined so we can use it as a replacement - * for an int index in a range based for loop. - * - * @note Will halt execution if called with page_table_handle::LEVEL1, because there is no level below. Has to be - * defined as either a friend function or inline header method, because we define an operator of another type. In - * this instance friend function was choosen, because the struct itself also requires the operator, but declaring - * before the struct is not possible, because the enum is in the struct. This is inpossible because the struct - * requires the operator declared before itself to work, and the operator requires the struct declared before itself - * to work. Furthermore this allows the defintion of the method to be done in the cpp, avoiding includes in the - * header file. - * - * @param value Value we want to decrement on - * @return New level value decrement by one, meaning the level is also decrement by one Level4 --> Level3, ... - */ - friend auto operator--(level & value) -> level &; - - private: - page_table * table; ///< Handle to underlying page table, can never be null (invariant ensured by - ///< constructor) - level table_level; ///< Level page table is currently on, depends on how often next_level was - ///< called successfuly. - }; - -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_PAGE_TABLE_HPP diff --git a/arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp b/arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp deleted file mode 100644 index d0d7781..0000000 --- a/arch/x86_64/pre/include/arch/memory/paging/temporary_page.hpp +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP - -#include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/allocator/tiny_frame_allocator.hpp" -#include "arch/memory/paging/active_page_table.hpp" -#include "arch/memory/paging/virtual_page.hpp" - -namespace teachos::arch::memory::paging -{ - /** - * @brief A temporary page used to remap the kernel. - */ - struct temporary_page - { - /** - * @brief Construct a new temporary page object. - * - * @tparam Type constraint of the allocator, being that is follows the given concept and contains an allocate and - * deallocate method. - * @param page Page to turn into temporary page. - * @param allocator Frame allocator used to fill page. - */ - template - temporary_page(virtual_page page, T & allocator) - : page{page} - , allocator{allocator} - { - // Nothing to do - } - - /** - * @brief Unmap the current page. - * - * @param active_table The current active page table. - */ - auto unmap_page(active_page_table & active_table) -> void; - - /** - * @brief Map the temporary page to a frame. - * - * @param frame The frame to which the page is mapped. - * @param active_table The current active page table. - * @return level1 page table handle containing the mapped page. - */ - auto map_table_frame(allocator::physical_frame frame, active_page_table & active_table) -> page_table_handle; - - private: - /** - * @brief Map the temporary page to a frame. - * - * @param frame The frame to which the page is mapped. - * @param active_table The current active page table. - * @return The virtual address of the page. - */ - auto map_to_frame(allocator::physical_frame frame, active_page_table & active_table) -> virtual_address; - - virtual_page page; ///< Underlying virtual page we want to temporarily map. - allocator::tiny_frame_allocator allocator; ///< Allocator that should be used to map the temporary page. - }; - -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_TEMPORARY_PAGE_HPP \ No newline at end of file diff --git a/arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp b/arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp deleted file mode 100644 index 1a20eae..0000000 --- a/arch/x86_64/pre/include/arch/memory/paging/virtual_page.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP -#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP - -#include "arch/memory/allocator/physical_frame.hpp" -#include "arch/memory/paging/page_table.hpp" - -#include -#include -#include - -namespace teachos::arch::memory::paging -{ - using virtual_address = std::size_t; - - /** - * @brief Virtual page entry contained in P1 page tables - */ - struct virtual_page - { - /** - * @brief Defaulted constructor. - */ - constexpr virtual_page() = default; - - /** - * @brief Constructor. - * - * @param page_number Index number of the current virtual page, used to distinguish it from other pages. - */ - explicit constexpr virtual_page(std::size_t page_number) - : page_number(page_number) - { - // Nothing to do - } - - /** - * @brief Returns the virtual page the given address is contained in. - * - * @param address Virtual address we want to get the corresponding virtual page for. - * @return Frame the given address is contained in. - */ - auto static containing_address(virtual_address address) -> virtual_page; - - /** - * @brief Evaluates the start address of the virtual page. - * - * @return Start address of the virtual page. - */ - auto start_address() const -> virtual_address; - - /** - * @brief Calculates the index into the page table with the given level, which leads to this virtual page. - * - * @param level Level of the page table we want to calculate the index for. - * @return Index into the page table with the given level. - */ - auto get_level_index(page_table_handle::level level) const -> size_t; - - /** - * @brief Post increment operator. Returns a copy of the value. - * - * @return Copy of the incremented underlying page number. - */ - auto operator++(int) -> virtual_page; - - /** - * @brief Pre increment operator. Returns a reference to the changed value. - * - * @return Reference to the incremented underlying page number. - */ - auto operator++() -> virtual_page &; - - /** - * @brief Defaulted equals operator. - */ - auto operator==(virtual_page const & other) const -> bool = default; - - /** - * @brief Defaulted three-way comparsion operator. - */ - auto operator<=>(virtual_page const & other) const -> std::partial_ordering = default; - - std::size_t page_number = - {}; ///< Index number of the current virtual page, used to distinguish it from other pages. - }; - - using page_container = stl::container>; - -} // namespace teachos::arch::memory::paging - -#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_VIRTUAL_PAGE_HPP diff --git a/arch/x86_64/pre/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/pre/src/memory/