diff options
| -rw-r--r-- | arch/x86_64/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/memory/frame_allocator.hpp | 117 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/memory/multiboot.hpp | 2 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/memory/paging.hpp | 150 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/video/vga/io.hpp | 8 | ||||
| -rw-r--r-- | arch/x86_64/include/arch/video/vga/text.hpp | 32 | ||||
| -rw-r--r-- | arch/x86_64/src/kernel/main.cpp | 26 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/frame_allocator.cpp | 35 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/multiboot.cpp | 28 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/paging.cpp | 53 |
10 files changed, 328 insertions, 124 deletions
diff --git a/arch/x86_64/CMakeLists.txt b/arch/x86_64/CMakeLists.txt index 882ea9a..25f8634 100644 --- a/arch/x86_64/CMakeLists.txt +++ b/arch/x86_64/CMakeLists.txt @@ -43,6 +43,7 @@ target_sources("_video" PRIVATE target_sources("_memory" PRIVATE "src/memory/multiboot.cpp" "src/memory/frame_allocator.cpp" + "src/memory/paging.cpp" ) #[============================================================================[ diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index 1fd1f08..ab93231 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -8,47 +8,46 @@ namespace teachos::arch::memory { - namespace - { - constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB - } + constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB. /** - * @brief Specific frame containing helper functions to determine if a specific address is in that frame or not + * @brief Specific physical_frame containing helper functions to determine if a specific address is in that + * physical_frame or not. */ - struct frame + struct physical_frame { /** * @brief Constructor * - * @param frame_number Index number that should be assigned to this frame + * @param frame_number Index number that should be assigned to this physical_frame. */ - frame(std::size_t frame_number); + explicit physical_frame(std::size_t frame_number); /** - * @brief Returns the frame the given address is contained in + * @brief Returns the physical_frame the given address is contained in. * - * @param address Address we want to get the corresponding frame for - * @return Frame the given address is contained in + * @param address Address we want to get the corresponding physical_frame for. + * @return Frame the given address is contained in. */ - static auto containing_address(std::size_t address) -> frame; + static auto containing_address(std::size_t address) -> physical_frame; /** - * @brief Defaulted equals operator + * @brief Defaulted equals operator. */ - constexpr auto operator==(const frame & other) const -> bool = default; + constexpr auto operator==(const physical_frame & other) const -> bool = default; /** - * @brief Defaulted three-way comparsion operator + * @brief Defaulted three-way comparsion operator. */ - constexpr auto operator<=>(const frame & other) const -> std::partial_ordering = default; + constexpr auto operator<=>(const physical_frame & other) const -> std::partial_ordering = default; - std::size_t frame_number; ///< Index number of the current frame, used to distinguish it from other frames + std::size_t + frame_number; ///< Index number of the current physical frame, used to distinguish it from other frames. }; template<typename T> concept FrameAllocator = requires(T t) { - { t.allocate_frame() } -> std::same_as<std::optional<frame>>; + { t.allocate_frame() } -> std::same_as<std::optional<physical_frame>>; { t.deallocate_frame() } -> std::same_as<void>; }; @@ -58,121 +57,121 @@ namespace teachos::arch::memory struct memory_area_iterator { /** - * @brief Constructor + * @brief Constructor. * - * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer + * @param p Underlying address the iterator should point too, ensure to not pass an invalid pointer. */ explicit memory_area_iterator(memory_area * p); /** * @brief Dereferences the initally given pointer to its value. * - * @return Reference to the value + * @return Reference to the value. */ memory_area & operator*() const; /** * @brief Post increment operator. Returns a copy of the value * - * @return Copy of the incremented underlying address + * @return Copy of the incremented underlying address. */ memory_area_iterator operator++(int); /** - * @brief Pre increment operator. Returns a reference to the changed value + * @brief Pre increment operator. Returns a reference to the changed value. * - * @return Reference to the incremented underlying address + * @return Reference to the incremented underlying address. */ memory_area_iterator & operator++(); /** * @brief Defaulted comparsion operator. Simply compares the memory address of both iterators. * - * @param other Other iterator to compare to - * @return Whether poith iterators point to the same underlying address in memory + * @param other Other iterator to compare to. + * @return Whether poith iterators point to the same underlying address in memory. */ bool operator==(memory_area_iterator const & other) const = default; private: - memory_area * ptr; ///< Underlying address the iterator is currently pointing too + memory_area * ptr; ///< Underlying address the iterator is currently pointing too. }; /** - * @brief Allocates memory using memory areas read from the multiboot2 information pointer + * @brief Allocates memory using memory areas read from the multiboot2 information pointer. */ struct area_frame_allocator { /** * @brief Constructor * - * @param kernel_start Start address of the kernel code in memory - * @param kernel_end End address of the kernel code in memory - * @param multiboot_start Start address of the multiboot code in memory - * @param multiboot_end End address of the multiboot code in memory - * @param memory_areas Pointer to the first element of all memory areas - * @param area_count Amount of total entries in the memory_areas array + * @param kernel_start Start address of the kernel code in memory. + * @param kernel_end End address of the kernel code in memory. + * @param multiboot_start Start address of the multiboot code in memory. + * @param multiboot_end End address of the multiboot code in memory. + * @param memory_areas Pointer to the first element of all memory areas. + * @param area_count Amount of total entries in the memory_areas array. */ area_frame_allocator(std::size_t kernel_start, std::size_t kernel_end, std::size_t multiboot_start, std::size_t multiboot_end, memory_area * memory_areas, uint8_t area_count) : area_begin(memory_areas) , area_end(memory_areas + area_count) - , kernel_start(frame::containing_address(kernel_start)) - , kernel_end(frame::containing_address(kernel_end)) - , multiboot_start(frame::containing_address(multiboot_start)) - , multiboot_end(frame::containing_address(multiboot_end)) + , kernel_start(physical_frame::containing_address(kernel_start)) + , kernel_end(physical_frame::containing_address(kernel_end)) + , multiboot_start(physical_frame::containing_address(multiboot_start)) + , multiboot_end(physical_frame::containing_address(multiboot_end)) { choose_next_area(); } /** - * @brief Allocate memory by finding and returning a free frame + * @brief Allocate memory by finding and returning a free physical_frame. * - * The frame allocation executes multiple checks before returning - * the frame that is available to allocate. It must at least + * 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 frame + * - update the next_free_frame after finding a free physical_frame */ - auto allocate_frame() -> std::optional<frame>; + auto allocate_frame() -> std::optional<physical_frame>; /** - * @brief Deallocates a previously allocated frame + * @brief Deallocates a previously allocated physical_frame. * - * @param frame Previously allocated frame that should be allocated + * @param physical_frame Previously allocated physical_frame that should be allocated. */ - auto deallocate_frame(frame frame) -> void; + auto deallocate_frame(physical_frame physical_frame) -> void; /** * @brief Returns the iterator pointing to the first element of the memory area. - * Allows using this class in the for each loop, because it follows the InputIterator template scheme + * Allows using this class in the for each loop, because it follows the InputIterator template scheme. * - * @return Iterator pointing to first element of the memory area + * @return Iterator pointing to first element of the memory area. */ auto begin() -> memory_area_iterator; /** * @brief Returns the iterator pointing to one past the last element of the memory area. - * Allows using this class in the for each loop, because it follows the InputIterator template scheme + * Allows using this class in the for each loop, because it follows the InputIterator template scheme. * - * @return Iterator pointing to one past the last element of the memory area + * @return Iterator pointing to one past the last element of the memory area. */ auto end() -> memory_area_iterator; private: /** - * @brief Find the next memory area and write it into current_area + * @brief Find the next memory area and write it into current_area. */ auto choose_next_area() -> void; - frame next_free_frame{0}; ///< The frame after the last allocated one - std::optional<memory_area> current_area{std::nullopt}; ///< The current memory area - memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas - memory_area_iterator area_end; ///< Pointer to one pas the last element of all memory areas - frame const kernel_start; ///< The start address of the kernel code in memory - frame const kernel_end; ///< The end address of the kernel code in memory - frame const multiboot_start; ///< The start address of the multiboot code in memory - frame const multiboot_end; ///< The end address of the multiboot code in memory + physical_frame next_free_frame{0}; ///< The physical_frame after the last allocated one. + std::optional<memory_area> current_area{std::nullopt}; ///< The current memory area. + memory_area_iterator area_begin; ///< Pointer to the first element of all memory areas. + memory_area_iterator area_end; ///< Pointer to one pas the last element of all memory areas. + 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 teachos::arch::memory diff --git a/arch/x86_64/include/arch/memory/multiboot.hpp b/arch/x86_64/include/arch/memory/multiboot.hpp index 35b483e..93d214c 100644 --- a/arch/x86_64/include/arch/memory/multiboot.hpp +++ b/arch/x86_64/include/arch/memory/multiboot.hpp @@ -152,7 +152,7 @@ namespace teachos::arch::memory * * @return Current section is writable. */ - auto writeable() const -> bool; + auto writable() const -> bool; /** * @brief (SHF_ALLOC) Whether the current section occupies memory during execution or not. ALLOC flag is shown in diff --git a/arch/x86_64/include/arch/memory/paging.hpp b/arch/x86_64/include/arch/memory/paging.hpp new file mode 100644 index 0000000..a5408e1 --- /dev/null +++ b/arch/x86_64/include/arch/memory/paging.hpp @@ -0,0 +1,150 @@ +#ifndef TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP +#define TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP + +#include "frame_allocator.hpp" + +namespace teachos::arch::memory +{ + constexpr std::size_t PAGE_TABLE_ENTRY_COUNT = 512U; ///< Default entry count of a page table in x86_84 is 512. + + /** + * @brief Virtual page entry contained in P1 page tables + */ + struct virtual_page + { + std::size_t number; ///< Index number of the current virtual page, used to distinguish it from other pages. + + /** + * @brief Defaulted equals operator. + */ + constexpr auto operator==(const virtual_page & other) const -> bool = default; + + /** + * @brief Defaulted three-way comparsion operator. + */ + constexpr auto operator<=>(const virtual_page & other) const -> std::partial_ordering = default; + }; + + /** + * @brief Marks a specific entry in an actual page table. + */ + struct entry + { + /** + * @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 Whether the current page is in memory and therefore present or not. Read from bit index 0. + * + * @return Current page is in memory. + */ + auto present() const -> bool; + + /** + * @brief Whether it is possible to write to the current page or not. Read from bit index 1. + * + * @return Current page can be written too. + */ + auto writable() const -> bool; + + /** + * @brief Whether the current page can be accessed in user mode, or only in kernel mode code. Read from bit index 2. + * + * @return Current page can be accessed in user mode. + */ + auto user_accessible() const -> bool; + + /** + * @brief Whether any write to the current page go directly to memory instead of the cache or not. Read from bit + * index 3. + * + * @return Writes to the current page go directly to memory. + */ + auto write_through_caching() const -> bool; + + /** + * @brief Whether the current page uses caching or not. Read from bit index 4. + * + * @return Current page does not use caching. + */ + auto disabled_caching() const -> bool; + + /** + * @brief Whether the current page is currently being used or not. Read from bit index 5. + * + * @return Current page is currently being used. + */ + auto is_accessing() const -> bool; + + /** + * @brief Whether the current page has been writen too or not. Read from bit index 6. + * + * @return Current page has been writen too. + */ + auto is_diry() const -> bool; + + /** + * @brief Whether the current page is huge or not (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. Read from bit index 7. + * + * @return Current page is huge + */ + auto is_huge_page() const -> bool; + + /** + * @brief Whether the current page is not flushed from caches on address space switches or not (PGE bit of CR4 + * register has to be set). Read from bit index 8. + * + * @return Current page is not flushed from caches on address space switches. + */ + auto is_global() const -> bool; + + /** + * @brief Whether the current page is forbidden from executing code or not (NXE bit in the EFER register has to be + * set). Read from bit index 63. + * + * @return Current page is forbidden from executing code. + */ + auto executing_code_forbidden() const -> bool; + + /** + * @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<physical_frame>; + + private: + /** + * @brief Extracts the physical address from the underlying bitset read from bit index 12 - 51. Is a 52 bit page + * aligned physical address of the frame of the next page table or the pyhscial address of the frame for P1 page + * tables. + * + * @return Extracted physical address of the next page or of the frame for P1 page tables. + */ + auto calculate_physical_address() const -> std::size_t; + + /** + * @brief Checks the underlying std::bitset if the bit at the specific index is set, meaning a value of 1 + * + * @param index Specific index we want to check at + * @return Bit value 1 is set and will return true + */ + auto is_bit_set(uint8_t index) const -> bool; + + std::bitset<64U> flags; ///< Underlying bitset used to read the flags from. Bits 9 - 11 and 52 - 62 can be freely + ///< used for additional flagsby the operating system. + }; +} // namespace teachos::arch::memory + +#endif // TEACHOS_ARCH_X86_64_MEMORY_PAGING_HPP diff --git a/arch/x86_64/include/arch/video/vga/io.hpp b/arch/x86_64/include/arch/video/vga/io.hpp index da9375d..3d2e90c 100644 --- a/arch/x86_64/include/arch/video/vga/io.hpp +++ b/arch/x86_64/include/arch/video/vga/io.hpp @@ -10,24 +10,24 @@ namespace teachos::arch::video::vga namespace crtc { /** - * @brief The address port of the CRT Controller + * @brief The address port of the CRT Controller. */ using address_port = arch::io::port<0x3d4, 1>; /** - * @brief The data port of the CRT Controller + * @brief The data port of the CRT Controller. */ using data_port = arch::io::port<0x3d5, 1>; namespace registers { /** - * @brief The address of the Cursor Start register of the CRTC + * @brief The address of the Cursor Start register of the CRTC. */ [[maybe_unused]] auto constexpr cursor_start = std::byte{0x0a}; /** - * @brief The address of the Cursor End register of the CRTC + * @brief The address of the Cursor End register of the CRTC. */ [[maybe_unused]] auto constexpr curser_end = std::byte{0x0b}; } // namespace registers diff --git a/arch/x86_64/include/arch/video/vga/text.hpp b/arch/x86_64/include/arch/video/vga/text.hpp index 79ec7be..cfafce0 100644 --- a/arch/x86_64/include/arch/video/vga/text.hpp +++ b/arch/x86_64/include/arch/video/vga/text.hpp @@ -12,14 +12,14 @@ namespace teachos::arch::video::vga::text */ enum struct color : std::uint8_t { - black, /**< Equivalent to HTML color \#000000 */ - blue, /**< Equivalent to HTML color \#0000AA */ - green, /**< Equivalent to HTML color \#00AA00 */ - cyan, /**< Equivalent to HTML color \#00AAAA */ - red, /**< Equivalent to HTML color \#AA0000 */ - purple, /**< Equivalent to HTML color \#AA00AA */ - brown, /**< Equivalent to HTML color \#AA5500 */ - gray, /**< Equivalent to HTML color \#AAAAAA */ + black, ///< Equivalent to HTML color \#000000 + blue, ///< Equivalent to HTML color \#0000AA + green, ///< Equivalent to HTML color \#00AA00 + cyan, ///< Equivalent to HTML color \#00AAAA + red, ///< Equivalent to HTML color \#AA0000 + purple, ///< Equivalent to HTML color \#AA00AA + brown, ///< Equivalent to HTML color \#AA5500 + gray, ///< Equivalent to HTML color \#AAAAAA }; /** @@ -27,8 +27,8 @@ namespace teachos::arch::video::vga::text */ enum struct foreground_flag : bool { - none, /**< Apply no flag e.g., keep color as is. */ - intense, /**< Make the color more intense (usually brighter). */ + none, ///< Apply no flag e.g., keep color as is. + intense, ///< Make the color more intense (usually brighter). }; /** @@ -36,8 +36,8 @@ namespace teachos::arch::video::vga::text */ enum struct background_flag : bool { - none, /**< Apply no flag e.g., keep color as is. */ - blink_or_bright, /**< Make the cell blink or more intense, dependent on the VGA configuration */ + none, ///< Apply no flag e.g., keep color as is. + blink_or_bright, ///< Make the cell blink or more intense, dependent on the VGA configuration }; /** @@ -51,10 +51,10 @@ namespace teachos::arch::video::vga::text */ struct attribute { - color foreground_color : 3; /**< The foreground color of the cell, e.g. the color of the code point.*/ - enum foreground_flag foreground_flag : 1; /**< The foreground color modification flag of the cell.*/ - color bacground_color : 3; /**< The background color of the cell.*/ - enum background_flag background_flag : 1; /**< The background color modification flag of the cell.*/ + color foreground_color : 3; ///< The foreground color of the cell, e.g. the color of the code point + enum foreground_flag foreground_flag : 1; ///< The foreground color modification flag of the cell. + color bacground_color : 3; ///< The background color of the cell. + enum background_flag background_flag : 1; ///< The background color modification flag of the cell. }; static_assert(sizeof(attribute) == 1, "The VGA text mode attribute must fit inside a single byte."); diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp index bdf530c..7e4a336 100644 --- a/arch/x86_64/src/kernel/main.cpp +++ b/arch/x86_64/src/kernel/main.cpp @@ -5,6 +5,8 @@ #include "arch/memory/multiboot.hpp" #include "arch/video/vga/text.hpp" +#include <algorithm> + namespace teachos::arch::kernel { auto assert(bool condition) -> void @@ -63,7 +65,7 @@ namespace teachos::arch::kernel for (auto section = begin; section != end; ++section) { - bool const writeable = section->flags.writeable(); + bool const writable = section->flags.writable(); bool const occupies_memory = section->flags.occupies_memory(); bool const is_executable = section->flags.is_executable(); bool const contains_duplicate_data = section->flags.contains_duplicate_data(); @@ -79,7 +81,7 @@ namespace teachos::arch::kernel bool const is_excluded_unless_referenced_or_allocated = section->flags.is_excluded_unless_referenced_or_allocated(); - if (writeable && occupies_memory && is_executable && contains_duplicate_data && contains_strings && + if (writable && occupies_memory && is_executable && contains_duplicate_data && contains_strings && section_header_info_is_section_header_table_index && preserve_ordering_after_combination && requires_special_os_processing && is_section_group_member && holds_thread_local_data && is_compressed && has_special_ordering_requirements && is_excluded_unless_referenced_or_allocated) @@ -182,20 +184,16 @@ namespace teachos::arch::kernel // Address of Frame: 0x203F00 auto allocator = arch::memory::area_frame_allocator(kernel_start, kernel_end, multiboot_start, multiboot_end, memory_areas, area_count); - auto allocated = allocator.allocate_frame(); // WATCH OUT: using optional::value() crashes the build... I think its because of missing exception handling - if (allocated.has_value()) - { - video::vga::text::write("Allocated Frame address: ", video::vga::text::common_attributes::green_on_black); - video::vga::text::write_number(reinterpret_cast<uint64_t>(&allocated->frame_number), - video::vga::text::common_attributes::green_on_black); - video::vga::text::write("Allocated Frame number: ", video::vga::text::common_attributes::green_on_black); - video::vga::text::write_number(allocated->frame_number, video::vga::text::common_attributes::green_on_black); - } - else + auto last_allocated = allocator.allocate_frame(); + auto allocated = last_allocated; + do { - video::vga::text::write("NO VALUE", video::vga::text::common_attributes::green_on_black); - } + last_allocated = allocated; + allocated = allocator.allocate_frame(); + } while (allocated.has_value()); + video::vga::text::write("Allocated Frames", video::vga::text::common_attributes::green_on_black); + video::vga::text::write_number(allocated->frame_number, video::vga::text::common_attributes::green_on_black); } } // namespace teachos::arch::kernel diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 3ad2d96..3733cc3 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,13 +2,16 @@ namespace teachos::arch::memory { - frame::frame(std::size_t frame_number) + physical_frame::physical_frame(std::size_t frame_number) : frame_number(frame_number) { // Nothing to do } - auto frame::containing_address(std::size_t address) -> frame { return frame{address / PAGE_FRAME_SIZE}; } + auto physical_frame::containing_address(std::size_t address) -> physical_frame + { + return physical_frame{address / PAGE_FRAME_SIZE}; + } memory_area_iterator::memory_area_iterator(memory_area * p) : ptr(p) @@ -39,7 +42,7 @@ namespace teachos::arch::memory memory_area & area = *it; std::size_t address = area.base_address + area.area_length - 1; - if (frame::containing_address(address) >= next_free_frame) + if (physical_frame::containing_address(address) >= next_free_frame) { // The `next_free_frame` address is smaller than the last address of the current area if (!current_area || area.base_address < current_area->base_address) @@ -52,7 +55,7 @@ namespace teachos::arch::memory if (current_area) { // Update the `next_free_frame` according to the new memory area - frame start_frame = frame::containing_address(current_area->base_address); + physical_frame start_frame = physical_frame::containing_address(current_area->base_address); if (next_free_frame < start_frame) { next_free_frame = start_frame; @@ -60,7 +63,7 @@ namespace teachos::arch::memory } } - auto area_frame_allocator::allocate_frame() -> std::optional<frame> + auto area_frame_allocator::allocate_frame() -> std::optional<physical_frame> { /* * Only try to allocate memory if current_area is not null, because @@ -68,29 +71,29 @@ namespace teachos::arch::memory */ if (current_area) { - frame frame{next_free_frame.frame_number}; + physical_frame physical_frame{next_free_frame.frame_number}; - struct frame current_area_last_frame = { - frame::containing_address(current_area->base_address + current_area->area_length - 1)}; + struct physical_frame current_area_last_frame = { + physical_frame::containing_address(current_area->base_address + current_area->area_length - 1)}; if (next_free_frame > current_area_last_frame) { // All frames of current area are used, switch to next area choose_next_area(); } - else if (frame >= multiboot_start && frame <= kernel_end) + else if (physical_frame >= multiboot_start && physical_frame <= kernel_end) { - // `frame` is used by the kernel or multiboot information structure - next_free_frame = arch::memory::frame{kernel_end.frame_number + 1}; + // `physical_frame` is used by the kernel or multiboot information structure + next_free_frame = arch::memory::physical_frame{kernel_end.frame_number + 1}; } else { // Frame is unused, increment `next_free_frame` and return it next_free_frame.frame_number += 1; - return frame; + return physical_frame; } - // `frame` was not valid, try it again with the updated `next_free_frame` + // `physical_frame` was not valid, try it again with the updated `next_free_frame` return allocate_frame(); } @@ -98,10 +101,10 @@ namespace teachos::arch::memory return std::nullopt; } - auto area_frame_allocator::deallocate_frame(frame frame) -> void + auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { - // TODO: Fix, simply done because compiler will complain if frame is unused and not compile - if (frame.frame_number == 3) + // TODO: Fix, simply done because compiler will complain if physical_frame is unused and not compile + if (physical_frame.frame_number == 3) { } } diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp index 3f6248d..bd3b00b 100644 --- a/arch/x86_64/src/memory/multiboot.cpp +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -2,35 +2,35 @@ namespace teachos::arch::memory { - auto elf_section_flags::writeable() const -> bool { return is_bit_set(0); } + auto elf_section_flags::writable() const -> bool { return is_bit_set(0U); } - auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1); } + auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1U); } - auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2); } + auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2U); } - auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4); } + auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4U); } - auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5); } + auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5U); } - auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6); } + auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6U); } - auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7); } + auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7U); } - auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8); } + auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8U); } - auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9); } + auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9U); } - auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10); } + auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10U); } - auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11); } + auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11U); } - auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30); } + auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30U); } - auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31); } + auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31U); } auto elf_section_flags::operator==(elf_section_flags const & other) const -> bool { return flags == other.flags; } - auto elf_section_flags::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1; } + auto elf_section_flags::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; } auto elf_section_header::is_null() const -> bool { diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp new file mode 100644 index 0000000..555357c --- /dev/null +++ b/arch/x86_64/src/memory/paging.cpp @@ -0,0 +1,53 @@ +#include "arch/memory/paging.hpp" + +namespace teachos::arch::memory +{ + auto entry::is_unused() const -> bool { return flags == 0U; } + + auto entry::set_unused() -> void { flags = 0U; } + + auto entry::present() const -> bool { return is_bit_set(0U); } + + auto entry::writable() const -> bool { return is_bit_set(1U); } + + auto entry::user_accessible() const -> bool { return is_bit_set(2U); } + + auto entry::write_through_caching() const -> bool { return is_bit_set(3U); } + + auto entry::disabled_caching() const -> bool { return is_bit_set(4U); } + + auto entry::is_accessing() const -> bool { return is_bit_set(5U); } + + auto entry::is_diry() const -> bool { return is_bit_set(6U); } + + auto entry::is_huge_page() const -> bool { return is_bit_set(7U); } + + auto entry::is_global() const -> bool { return is_bit_set(8U); } + + auto entry::executing_code_forbidden() const -> bool { return is_bit_set(63U); } + + auto entry::calculate_pointed_to_frame() const -> std::optional<physical_frame> + { + if (present()) + { + auto physical_address = calculate_physical_address(); + return physical_frame::containing_address(physical_address); + } + return std::nullopt; + } + + auto entry::calculate_physical_address() const -> std::size_t + { + constexpr std::size_t start_bit = 12U; + constexpr std::size_t end_bit = 51U; + size_t value = 0U; + + for (auto i = start_bit; i < end_bit; i++) + { + value |= (flags[i] ? (1 << (i - start_bit)) : 0); + } + return value; + } + + auto entry::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; } +} // namespace teachos::arch::memory |
