diff options
| author | Felix Morgner <felix.morgner@ost.ch> | 2025-12-12 14:11:07 +0100 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@ost.ch> | 2025-12-12 14:11:07 +0100 |
| commit | 682f28543be1ef7a315284c932075be1976e2930 (patch) | |
| tree | 159198a415732989da7b0905ecd967db6e04e11b | |
| parent | 50c9c9a1d963e66f7658ab31e9ecd65bf227cfff (diff) | |
| download | teachos-682f28543be1ef7a315284c932075be1976e2930.tar.xz teachos-682f28543be1ef7a315284c932075be1976e2930.zip | |
x86_64/pre: remove ported implementation
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 - }; - |
