From 32add45849744dc976c7af6ec24f985bbace47d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 2 Oct 2024 13:02:35 +0000 Subject: Creating base frame allocation code --- arch/x86_64/src/memory/frame_allocator.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 arch/x86_64/src/memory/frame_allocator.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp new file mode 100644 index 0000000..425528a --- /dev/null +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -0,0 +1,9 @@ +#include "arch/memory/frame_allocator.hpp" + +namespace teachos::arch::memory +{ + auto AreaFrameAllocator::allocate_frame() -> std::optional {} + + auto AreaFrameAllocator::deallocate_frame(Frame frame) -> void {} + +} // namespace teachos::arch::memory -- cgit v1.2.3 From 1ab9c3c09d32283b39ca1026a9e29ada5ff7fda5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 6 Oct 2024 07:34:30 +0000 Subject: Renaming scheme --- arch/x86_64/src/memory/frame_allocator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 425528a..b9d26a5 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,8 +2,8 @@ namespace teachos::arch::memory { - auto AreaFrameAllocator::allocate_frame() -> std::optional {} + auto area_frame_allocator::allocate_frame() -> std::optional {} - auto AreaFrameAllocator::deallocate_frame(Frame frame) -> void {} + auto area_frame_allocator::deallocate_frame(frame frame) -> void {} } // namespace teachos::arch::memory -- cgit v1.2.3 From 8773024d1b4e756fe5d3494479247c64c7ad8491 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 8 Oct 2024 09:51:26 +0000 Subject: begin implementing frame allocator --- arch/x86_64/src/memory/frame_allocator.cpp | 70 +++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index b9d26a5..b8f53be 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,8 +2,76 @@ namespace teachos::arch::memory { - auto area_frame_allocator::allocate_frame() -> std::optional {} + auto area_frame_allocator::allocate_frame() -> std::optional + { + /* + * Only try to allocate memory if current_area is not null, because + * the current_area is null if there is no more available memory. + */ + if (current_area) + { + frame frame{next_free_frame.frame_number}; + + struct frame current_area_last_frame = { + 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) + { + // `frame` is used by the kernel or multiboot information structure + next_free_frame = arch::memory::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; + } + + // `frame` was not valid, try it again with the updated `next_free_frame` + return allocate_frame(); + } + + // no free frames left + return std::nullopt; + } auto area_frame_allocator::deallocate_frame(frame frame) -> void {} + namespace + { + auto area_frame_allocator::choose_next_area() -> void + { + current_area = std::nullopt; + + // TODO: Fix this loop as soon as you've created an area iterator + for (const auto & area : areas) + { + std::size_t address = area.base_addr + area.length - 1; + if (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_addr < current_area->base_address) + { + current_area = area; + } + } + } + + if (current_area) + { + // Update the `next_free_frame` according to the new memory area + frame start_frame = frame::containing_address(current_area->base_address); + if (next_free_frame < start_frame) + { + next_free_frame = start_frame; + } + } + } + + } // namespace } // namespace teachos::arch::memory -- cgit v1.2.3 From 7edd03e9a14a3025b4d2b2ff51d838d20b79b2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 8 Oct 2024 11:30:01 +0000 Subject: Added doxygen comments to all fields and structs --- arch/x86_64/src/memory/multiboot.cpp | 41 ++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 arch/x86_64/src/memory/multiboot.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp new file mode 100644 index 0000000..91e7550 --- /dev/null +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -0,0 +1,41 @@ +#include "multiboot.hpp" + +namespace teachos::arch::memory +{ + auto elf_section_flags::writeable() const -> bool { return is_bit_set(0); } + + auto elf_section_flags::occupies_memory() const -> bool { return is_bit_set(1); } + + auto elf_section_flags::is_executable() const -> bool { return is_bit_set(2); } + + auto elf_section_flags::contains_duplicate_data() const -> bool { return is_bit_set(4); } + + auto elf_section_flags::contains_strings() const -> bool { return is_bit_set(5); } + + auto elf_section_flags::section_header_info_is_section_header_table_index() const -> bool { return is_bit_set(6); } + + auto elf_section_flags::preserve_ordering_after_combination() const -> bool { return is_bit_set(7); } + + auto elf_section_flags::requires_special_os_processing() const -> bool { return is_bit_set(8); } + + auto elf_section_flags::is_section_group_member() const -> bool { return is_bit_set(9); } + + auto elf_section_flags::holds_thread_local_data() const -> bool { return is_bit_set(10); } + + auto elf_section_flags::is_compressed() const -> bool { return is_bit_set(11); } + + auto elf_section_flags::has_special_ordering_requirements() const -> bool { return is_bit_set(30); } + + auto elf_section_flags::is_excluded_unless_referenced_or_allocated() const -> bool { return is_bit_set(31); } + + 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_header::is_null() const -> bool + { + return name_table_index == 0U && type == elf_section_type::UNSPECIFIED && + flags == teachos::arch::memory::elf_section_flags{0U} && virtual_address == 0U && file_offset == 0U && + additional_information == 0U && address_alignment == 0U && fixed_table_entry_size == 0U; + } +} // namespace teachos::arch::memory -- cgit v1.2.3 From 553f3a824511bb8107982b2b2737f5b1dff59855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sun, 13 Oct 2024 08:28:30 +0000 Subject: Add missing cpp files to cmake and fix elf alignment issues --- arch/x86_64/src/memory/frame_allocator.cpp | 66 ++++++++++++++++-------------- arch/x86_64/src/memory/multiboot.cpp | 4 +- 2 files changed, 37 insertions(+), 33 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index b8f53be..3793ac6 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,6 +2,37 @@ namespace teachos::arch::memory { + auto area_frame_allocator::choose_next_area() -> void + { + current_area = std::nullopt; + auto begin = areas; + auto end = areas + 5; + + // TODO: Fix this loop as soon as you've created an area iterator + for (auto area = begin; area != end; ++area) + { + std::size_t address = area->base_address + area->area_length - 1; + if (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) + { + current_area = *area; + } + } + } + + if (current_area) + { + // Update the `next_free_frame` according to the new memory area + frame start_frame = frame::containing_address(current_area->base_address); + if (next_free_frame < start_frame) + { + next_free_frame = start_frame; + } + } + } + auto area_frame_allocator::allocate_frame() -> std::optional { /* @@ -40,38 +71,11 @@ namespace teachos::arch::memory return std::nullopt; } - auto area_frame_allocator::deallocate_frame(frame frame) -> void {} - - namespace + auto area_frame_allocator::deallocate_frame(frame frame) -> void { - auto area_frame_allocator::choose_next_area() -> void + // TODO: Fix, simply done because compiler will complain if frame is unused and not compile + if (frame.frame_number == 3) { - current_area = std::nullopt; - - // TODO: Fix this loop as soon as you've created an area iterator - for (const auto & area : areas) - { - std::size_t address = area.base_addr + area.length - 1; - if (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_addr < current_area->base_address) - { - current_area = area; - } - } - } - - if (current_area) - { - // Update the `next_free_frame` according to the new memory area - frame start_frame = frame::containing_address(current_area->base_address); - if (next_free_frame < start_frame) - { - next_free_frame = start_frame; - } - } } - - } // namespace + } } // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp index 91e7550..3f6248d 100644 --- a/arch/x86_64/src/memory/multiboot.cpp +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -1,4 +1,4 @@ -#include "multiboot.hpp" +#include "arch/memory/multiboot.hpp" namespace teachos::arch::memory { @@ -34,7 +34,7 @@ namespace teachos::arch::memory auto elf_section_header::is_null() const -> bool { - return name_table_index == 0U && type == elf_section_type::UNSPECIFIED && + return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == teachos::arch::memory::elf_section_flags{0U} && virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && fixed_table_entry_size == 0U; } -- cgit v1.2.3 From b3c8a1819226b7dbaad82623c8294b99c91297ef Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Sun, 13 Oct 2024 10:58:34 +0000 Subject: continue implementing frame allocator --- arch/x86_64/src/memory/frame_allocator.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 3793ac6..829cd6d 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -5,19 +5,18 @@ namespace teachos::arch::memory auto area_frame_allocator::choose_next_area() -> void { current_area = std::nullopt; - auto begin = areas; - auto end = areas + 5; - // TODO: Fix this loop as soon as you've created an area iterator - for (auto area = begin; area != end; ++area) + for (memory_area_iterator it = begin(); it != end(); ++it) { - std::size_t address = area->base_address + area->area_length - 1; + memory_area & area = *it; + + std::size_t address = area.base_address + area.area_length - 1; if (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) + if (!current_area || area.base_address < current_area->base_address) { - current_area = *area; + current_area = area; } } } -- cgit v1.2.3 From 8beb8b758c33cf1ac5357b31296927e7df8cf971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Oct 2024 08:15:16 +0000 Subject: Fix typos, implementation in header and missing doxygen --- arch/x86_64/src/memory/frame_allocator.cpp | 32 ++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 829cd6d..3ad2d96 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -2,6 +2,34 @@ namespace teachos::arch::memory { + frame::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}; } + + memory_area_iterator::memory_area_iterator(memory_area * p) + : ptr(p) + { + // Nothing to do + } + + memory_area & memory_area_iterator::operator*() const { return *ptr; } + + auto memory_area_iterator::operator++(int) -> memory_area_iterator + { + ++(*this); + return *this; + } + + auto memory_area_iterator::operator++() -> memory_area_iterator & + { + ++ptr; + return *this; + } + auto area_frame_allocator::choose_next_area() -> void { current_area = std::nullopt; @@ -77,4 +105,8 @@ namespace teachos::arch::memory { } } + + auto area_frame_allocator::begin() -> memory_area_iterator { return area_begin; } + + auto area_frame_allocator::end() -> memory_area_iterator { return area_end; } } // namespace teachos::arch::memory -- cgit v1.2.3 From 38e0b13ab9a4997fdf9f311fd125825919d2e6c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Mon, 14 Oct 2024 14:03:27 +0000 Subject: Start developing paging --- arch/x86_64/src/memory/frame_allocator.cpp | 35 +++++++++++--------- arch/x86_64/src/memory/multiboot.cpp | 28 ++++++++-------- arch/x86_64/src/memory/paging.cpp | 53 ++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 30 deletions(-) create mode 100644 arch/x86_64/src/memory/paging.cpp (limited to 'arch/x86_64/src/memory') 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 + auto area_frame_allocator::allocate_frame() -> std::optional { /* * 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 + { + 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 -- cgit v1.2.3 From 205934ca45d591924b4be6e7ae5a8849958e0cf6 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 08:23:39 +0000 Subject: continue implementing paging --- arch/x86_64/src/memory/frame_allocator.cpp | 12 ++++++---- arch/x86_64/src/memory/paging.cpp | 36 +++++++++++------------------- 2 files changed, 21 insertions(+), 27 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 3733cc3..01dcc88 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -1,7 +1,11 @@ #include "arch/memory/frame_allocator.hpp" +#include "arch/exception_handling/assert.hpp" + namespace teachos::arch::memory { + uint64_t PAGE_SIZE; + physical_frame::physical_frame(std::size_t frame_number) : frame_number(frame_number) { @@ -13,6 +17,8 @@ namespace teachos::arch::memory return physical_frame{address / PAGE_FRAME_SIZE}; } + auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_SIZE; } + memory_area_iterator::memory_area_iterator(memory_area * p) : ptr(p) { @@ -103,10 +109,8 @@ namespace teachos::arch::memory auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void { - // TODO: Fix, simply done because compiler will complain if physical_frame is unused and not compile - if (physical_frame.frame_number == 3) - { - } + arch::exception_handling::assert(false && physical_frame.frame_number == 0, + "[deallocate_frame] Not implemented Exception"); } auto area_frame_allocator::begin() -> memory_area_iterator { return area_begin; } diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 555357c..90c4199 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -1,34 +1,16 @@ #include "arch/memory/paging.hpp" +#include "arch/exception_handling/assert.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 { - if (present()) + if (contains_flags(1)) { auto physical_address = calculate_physical_address(); return physical_frame::containing_address(physical_address); @@ -39,7 +21,7 @@ namespace teachos::arch::memory auto entry::calculate_physical_address() const -> std::size_t { constexpr std::size_t start_bit = 12U; - constexpr std::size_t end_bit = 51U; + constexpr std::size_t end_bit = 52U; size_t value = 0U; for (auto i = start_bit; i < end_bit; i++) @@ -49,5 +31,13 @@ namespace teachos::arch::memory return value; } - auto entry::is_bit_set(uint8_t index) const -> bool { return flags[index] == 1U; } + auto entry::set(physical_frame frame) -> void + { + arch::exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, + "Start address is not aligned with Page"); + flags = std::bitset<64U>(frame.start_address()) | flags; + } + + auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + } // namespace teachos::arch::memory -- cgit v1.2.3 From 03d3dec4807d6adcfc5e21bd13992014900b4eac Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 08:40:56 +0000 Subject: implement page table members --- arch/x86_64/src/memory/paging.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 90c4199..58a2b99 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -40,4 +40,15 @@ namespace teachos::arch::memory auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + auto page_table::zero_entries() -> void + { + auto begin = &entries[0]; + auto end = &entries[PAGE_TABLE_ENTRY_COUNT]; + + for (auto entry = begin; entry < end; ++entry) + { + entry->set_unused(); + } + } + } // namespace teachos::arch::memory -- cgit v1.2.3 From 11f9c91e602bd0231e6bc402418dedf445e47402 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Tue, 15 Oct 2024 08:45:29 +0000 Subject: Adding enum flags --- arch/x86_64/src/memory/multiboot.cpp | 36 ++++-------------------------------- arch/x86_64/src/memory/paging.cpp | 7 +++---- 2 files changed, 7 insertions(+), 36 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp index bd3b00b..b0432a9 100644 --- a/arch/x86_64/src/memory/multiboot.cpp +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -2,40 +2,12 @@ namespace teachos::arch::memory { - auto elf_section_flags::writable() const -> bool { return is_bit_set(0U); } - - 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(2U); } - - 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(5U); } - - 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(7U); } - - 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(9U); } - - 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(11U); } - - 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(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] == 1U; } + auto elf_section_flags::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } auto elf_section_header::is_null() const -> bool { - return name_table_index == 0U && type == elf_section_type::INACTIVE && - flags == teachos::arch::memory::elf_section_flags{0U} && virtual_address == 0U && file_offset == 0U && - additional_information == 0U && address_alignment == 0U && fixed_table_entry_size == 0U; + return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == elf_section_flags(0U) && + virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && + fixed_table_entry_size == 0U; } } // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 58a2b99..6fef339 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -31,15 +31,15 @@ namespace teachos::arch::memory return value; } - auto entry::set(physical_frame frame) -> void + auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + + auto entry::set_address(physical_frame frame) -> void { arch::exception_handling::assert((frame.start_address() & ~0x000fffff'fffff000) == 0, "Start address is not aligned with Page"); flags = std::bitset<64U>(frame.start_address()) | flags; } - auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } - auto page_table::zero_entries() -> void { auto begin = &entries[0]; @@ -50,5 +50,4 @@ namespace teachos::arch::memory entry->set_unused(); } } - } // namespace teachos::arch::memory -- cgit v1.2.3 From 0fac2d5f7a868b5d65db6fb42ce256485e651206 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 09:02:52 +0000 Subject: replace standalone value with enum --- arch/x86_64/src/memory/paging.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 6fef339..4603e74 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -10,7 +10,7 @@ namespace teachos::arch::memory auto entry::calculate_pointed_to_frame() const -> std::optional { - if (contains_flags(1)) + if (contains_flags(PRESENT)) { auto physical_address = calculate_physical_address(); return physical_frame::containing_address(physical_address); -- cgit v1.2.3 From 429d99ca40254e9e19da938ff9f2065a543708cd Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 09:05:37 +0000 Subject: rename contains_flags parameter --- arch/x86_64/src/memory/multiboot.cpp | 2 +- arch/x86_64/src/memory/paging.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp index b0432a9..8c6793e 100644 --- a/arch/x86_64/src/memory/multiboot.cpp +++ b/arch/x86_64/src/memory/multiboot.cpp @@ -2,7 +2,7 @@ namespace teachos::arch::memory { - auto elf_section_flags::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } 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 index 4603e74..445c796 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -31,7 +31,7 @@ namespace teachos::arch::memory return value; } - auto entry::contains_flags(std::bitset<64U> b) const -> bool { return (flags & b) == b; } + auto entry::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } auto entry::set_address(physical_frame frame) -> void { -- cgit v1.2.3 From 0c4fd9eaed4a71975879aa83cd2da4b6266a64b5 Mon Sep 17 00:00:00 2001 From: Fabian Imhof Date: Tue, 15 Oct 2024 15:48:43 +0000 Subject: add 4th level page table --- arch/x86_64/src/memory/paging.cpp | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 445c796..61d9d0f 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -50,4 +50,31 @@ namespace teachos::arch::memory entry->set_unused(); } } + + auto page_table::next_table_address(std::size_t index) const -> std::optional + { + auto entry = entries[index]; + + if (entry.contains_flags(entry.PRESENT) && !entry.contains_flags(entry.HUGE_PAGE)) + { + std::size_t table_address = reinterpret_cast(this); + return (table_address << 9) | (index << 12); + } + else + { + return std::nullopt; + } + } + + auto page_table::next_table(size_t index) const -> std::optional + { + auto address = next_table_address(index); + + if (address.has_value()) + { + return reinterpret_cast(*address); + } + + return std::nullopt; + } } // namespace teachos::arch::memory -- cgit v1.2.3 From f56004a77314d4b4d68bfaf496fd7c6013ba7a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 11:52:01 +0000 Subject: Adjust types --- arch/x86_64/src/memory/paging.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 61d9d0f..2f78da8 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -60,19 +60,17 @@ namespace teachos::arch::memory std::size_t table_address = reinterpret_cast(this); return (table_address << 9) | (index << 12); } - else - { - return std::nullopt; - } + // TODO: Implement behaviour for huge pages currently not done + return std::nullopt; } - auto page_table::next_table(size_t index) const -> std::optional + auto page_table::next_table(std::size_t index) const -> std::optional { auto address = next_table_address(index); if (address.has_value()) { - return reinterpret_cast(*address); + return reinterpret_cast(*address); } return std::nullopt; -- cgit v1.2.3 From 934822e48a7c5a3e65ed74261ce5ab4315595f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 13:33:23 +0000 Subject: Fix compilation issues with assigning values to page_map_variable address --- arch/x86_64/src/memory/frame_allocator.cpp | 19 ++++++++++++++++--- arch/x86_64/src/memory/paging.cpp | 13 ++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 01dcc88..70276ae 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -4,8 +4,6 @@ namespace teachos::arch::memory { - uint64_t PAGE_SIZE; - physical_frame::physical_frame(std::size_t frame_number) : frame_number(frame_number) { @@ -17,7 +15,7 @@ namespace teachos::arch::memory return physical_frame{address / PAGE_FRAME_SIZE}; } - auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_SIZE; } + auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_FRAME_SIZE; } memory_area_iterator::memory_area_iterator(memory_area * p) : ptr(p) @@ -39,6 +37,21 @@ namespace teachos::arch::memory return *this; } + area_frame_allocator::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) + : next_free_frame(0) + , current_area(std::nullopt) + , area_begin(memory_areas) + , area_end(memory_areas + area_count) + , 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(); + } + auto area_frame_allocator::choose_next_area() -> void { current_area = std::nullopt; diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index 2f78da8..a07b2c0 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -42,12 +42,9 @@ namespace teachos::arch::memory auto page_table::zero_entries() -> void { - auto begin = &entries[0]; - auto end = &entries[PAGE_TABLE_ENTRY_COUNT]; - - for (auto entry = begin; entry < end; ++entry) + for (size_t i = 0; i < sizeof(entries) / sizeof(entries[0]); ++i) { - entry->set_unused(); + entries[i].set_unused(); } } @@ -75,4 +72,10 @@ namespace teachos::arch::memory return std::nullopt; } + + entry & page_table::operator[](std::size_t index) + { + arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + return entries[index]; + } } // namespace teachos::arch::memory -- cgit v1.2.3 From 35e25757b6cffbcb2ff1eea8daf4c5f1ca421cb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 14:10:32 +0000 Subject: Adjust table accessing code to make it safer (always out of bounds checked) --- arch/x86_64/src/memory/paging.cpp | 47 +++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index a07b2c0..a8f2c40 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -40,25 +40,21 @@ namespace teachos::arch::memory flags = std::bitset<64U>(frame.start_address()) | flags; } - auto page_table::zero_entries() -> void + page_table::page_table() + : entries() + , p4(reinterpret_cast(0xfffffffffffff000)) { - for (size_t i = 0; i < sizeof(entries) / sizeof(entries[0]); ++i) - { - entries[i].set_unused(); - } + // Nothing to do } - auto page_table::next_table_address(std::size_t index) const -> std::optional + auto page_table::zero_entries() -> void { - auto entry = entries[index]; - - if (entry.contains_flags(entry.PRESENT) && !entry.contains_flags(entry.HUGE_PAGE)) + constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); + for (size_t i = 0; i < entry_amount; ++i) { - std::size_t table_address = reinterpret_cast(this); - return (table_address << 9) | (index << 12); + auto entry = this->operator[](i); + entry.set_unused(); } - // TODO: Implement behaviour for huge pages currently not done - return std::nullopt; } auto page_table::next_table(std::size_t index) const -> std::optional @@ -73,9 +69,32 @@ namespace teachos::arch::memory return std::nullopt; } - entry & page_table::operator[](std::size_t index) + auto page_table::operator[](std::size_t index) -> entry & + { + // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which + // could be incredibly hard to debug later. + arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); + return entries[index]; + } + + auto page_table::operator[](std::size_t index) const -> entry const & { + // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which + // could be incredibly hard to debug later. arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); return entries[index]; } + + auto page_table::next_table_address(std::size_t index) const -> std::optional + { + auto entry = this->operator[](index); + + if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) + { + std::size_t const table_address = reinterpret_cast(this); + return (table_address << 9) | (index << 12); + } + // TODO: Implement behaviour for huge pages currently not done + return std::nullopt; + } } // namespace teachos::arch::memory -- cgit v1.2.3 From d539ed1f4f26a42959bcae6ea3050b7f99f5f872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Wed, 16 Oct 2024 14:30:04 +0000 Subject: Attempt to implement page table checks using templates --- arch/x86_64/src/memory/paging.cpp | 58 --------------------------------------- 1 file changed, 58 deletions(-) (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/paging.cpp b/arch/x86_64/src/memory/paging.cpp index a8f2c40..9774132 100644 --- a/arch/x86_64/src/memory/paging.cpp +++ b/arch/x86_64/src/memory/paging.cpp @@ -39,62 +39,4 @@ namespace teachos::arch::memory "Start address is not aligned with Page"); flags = std::bitset<64U>(frame.start_address()) | flags; } - - page_table::page_table() - : entries() - , p4(reinterpret_cast(0xfffffffffffff000)) - { - // Nothing to do - } - - auto page_table::zero_entries() -> void - { - constexpr size_t entry_amount = sizeof(entries) / sizeof(entries[0]); - for (size_t i = 0; i < entry_amount; ++i) - { - auto entry = this->operator[](i); - entry.set_unused(); - } - } - - auto page_table::next_table(std::size_t index) const -> std::optional - { - auto address = next_table_address(index); - - if (address.has_value()) - { - return reinterpret_cast(*address); - } - - return std::nullopt; - } - - auto page_table::operator[](std::size_t index) -> entry & - { - // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which - // could be incredibly hard to debug later. - arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); - return entries[index]; - } - - auto page_table::operator[](std::size_t index) const -> entry const & - { - // C array is not bounds checked, therefore we have to check ourselves, to ensure no out of bounds reads, which - // could be incredibly hard to debug later. - arch::exception_handling::assert(index < PAGE_TABLE_ENTRY_COUNT, "[Page Table] index out of bounds"); - return entries[index]; - } - - auto page_table::next_table_address(std::size_t index) const -> std::optional - { - auto entry = this->operator[](index); - - if (entry.contains_flags(entry::PRESENT) && !entry.contains_flags(entry::HUGE_PAGE)) - { - std::size_t const table_address = reinterpret_cast(this); - return (table_address << 9) | (index << 12); - } - // TODO: Implement behaviour for huge pages currently not done - return std::nullopt; - } } // namespace teachos::arch::memory -- cgit v1.2.3 From a2fdcea0d7615f8933401e45e0c64a2f618bb730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 19 Oct 2024 13:15:45 +0000 Subject: Move compelte multiboot2 code into seperate files and behaviour into seperate static class --- arch/x86_64/src/memory/frame_allocator.cpp | 44 ++------ arch/x86_64/src/memory/multiboot.cpp | 13 --- .../src/memory/multiboot/elf_symbols_section.cpp | 13 +++ arch/x86_64/src/memory/multiboot/memory_map.cpp | 24 +++++ arch/x86_64/src/memory/multiboot/reader.cpp | 117 +++++++++++++++++++++ 5 files changed, 165 insertions(+), 46 deletions(-) delete mode 100644 arch/x86_64/src/memory/multiboot.cpp create mode 100644 arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp create mode 100644 arch/x86_64/src/memory/multiboot/memory_map.cpp create mode 100644 arch/x86_64/src/memory/multiboot/reader.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 70276ae..7776082 100644 --- a/arch/x86_64/src/memory/frame_allocator.cpp +++ b/arch/x86_64/src/memory/frame_allocator.cpp @@ -17,37 +17,15 @@ namespace teachos::arch::memory auto physical_frame::start_address() const -> uint64_t { return frame_number * PAGE_FRAME_SIZE; } - memory_area_iterator::memory_area_iterator(memory_area * p) - : ptr(p) - { - // Nothing to do - } - - memory_area & memory_area_iterator::operator*() const { return *ptr; } - - auto memory_area_iterator::operator++(int) -> memory_area_iterator - { - ++(*this); - return *this; - } - - auto memory_area_iterator::operator++() -> memory_area_iterator & - { - ++ptr; - return *this; - } - - area_frame_allocator::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_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info) : next_free_frame(0) , current_area(std::nullopt) - , area_begin(memory_areas) - , area_end(memory_areas + area_count) - , 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)) + , area_begin(mem_info.memory_areas) + , area_end(mem_info.memory_areas + mem_info.area_count) + , kernel_start(physical_frame::containing_address(mem_info.kernel_start)) + , kernel_end(physical_frame::containing_address(mem_info.kernel_end)) + , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start)) + , multiboot_end(physical_frame::containing_address(mem_info.multiboot_end)) { choose_next_area(); } @@ -56,9 +34,9 @@ namespace teachos::arch::memory { current_area = std::nullopt; - for (memory_area_iterator it = begin(); it != end(); ++it) + for (multiboot::memory_area_iterator it = begin(); it != end(); ++it) { - memory_area & area = *it; + multiboot::memory_area & area = *it; std::size_t address = area.base_address + area.area_length - 1; if (physical_frame::containing_address(address) >= next_free_frame) @@ -126,7 +104,7 @@ namespace teachos::arch::memory "[deallocate_frame] Not implemented Exception"); } - auto area_frame_allocator::begin() -> memory_area_iterator { return area_begin; } + auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; } - auto area_frame_allocator::end() -> memory_area_iterator { return area_end; } + auto area_frame_allocator::end() -> multiboot::memory_area_iterator { return area_end; } } // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/multiboot.cpp b/arch/x86_64/src/memory/multiboot.cpp deleted file mode 100644 index 8c6793e..0000000 --- a/arch/x86_64/src/memory/multiboot.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "arch/memory/multiboot.hpp" - -namespace teachos::arch::memory -{ - auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } - - auto elf_section_header::is_null() const -> bool - { - return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == elf_section_flags(0U) && - virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && - fixed_table_entry_size == 0U; - } -} // namespace teachos::arch::memory diff --git a/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp new file mode 100644 index 0000000..78ab952 --- /dev/null +++ b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp @@ -0,0 +1,13 @@ +#include "arch/memory/multiboot/elf_sybols_section.hpp" + +namespace teachos::arch::memory::multiboot +{ + auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; } + + auto elf_section_header::is_null() const -> bool + { + return name_table_index == 0U && type == elf_section_type::INACTIVE && flags == elf_section_flags(0U) && + virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U && + fixed_table_entry_size == 0U; + } +} // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/src/memory/multiboot/memory_map.cpp b/arch/x86_64/src/memory/multiboot/memory_map.cpp new file mode 100644 index 0000000..6b1d1d4 --- /dev/null +++ b/arch/x86_64/src/memory/multiboot/memory_map.cpp @@ -0,0 +1,24 @@ +#include "arch/memory/multiboot/memory_map.hpp" + +namespace teachos::arch::memory::multiboot +{ + memory_area_iterator::memory_area_iterator(multiboot::memory_area * p) + : ptr(p) + { + // Nothing to do + } + + multiboot::memory_area & memory_area_iterator::operator*() const { return *ptr; } + + auto memory_area_iterator::operator++(int) -> memory_area_iterator + { + ++(*this); + return *this; + } + + auto memory_area_iterator::operator++() -> memory_area_iterator & + { + ++ptr; + return *this; + } +} // namespace teachos::arch::memory::multiboot diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp new file mode 100644 index 0000000..8741b44 --- /dev/null +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -0,0 +1,117 @@ +#include "arch/memory/multiboot/reader.hpp" + +#include "arch/boot/pointers.hpp" +#include "arch/exception_handling/assert.hpp" +#include "arch/memory/multiboot/info.hpp" + +namespace teachos::arch::memory::multiboot +{ + namespace + { + template + requires std::is_pointer::value + auto align_to_8_byte_boundary(T ptr, uint32_t size) -> T + { + return reinterpret_cast(reinterpret_cast(ptr) + ((size + 7) & ~7)); + } + + auto process_memory_map(memory_map_header * mminfo, memory_area *& memory_areas, uint8_t & area_count) -> void + { + auto expected_entry_size = mminfo->entry_size; + constexpr auto actual_entry_size = sizeof(memory_area); + arch::exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memory_area entry size"); + + auto total_size = mminfo->info.size; + auto total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; + auto number_of_entries = total_entries_size / actual_entry_size; + + memory_areas = &mminfo->entries; + area_count = number_of_entries; + } + + auto process_elf_sections(elf_symbols_section_header * symbol, uint64_t & kernel_start, + uint64_t & kernel_end) -> void + { + auto expected_entry_size = symbol->entry_size; + constexpr auto actual_entry_size = sizeof(elf_section_header); + arch::exception_handling::assert(expected_entry_size == actual_entry_size, + "Unexpected elf_section_header entry size"); + + auto expected_total_size = symbol->info.size; + auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections; + constexpr auto actual_total_section_size = sizeof(elf_symbols_section_header) - sizeof(uint32_t); + auto actual_total_size = actual_total_entry_size + actual_total_section_size; + arch::exception_handling::assert(expected_total_size == actual_total_size, + "Unexpected elf_symbols_section_header total size"); + + auto begin = reinterpret_cast(&symbol->end); + auto end = begin + symbol->number_of_sections; + arch::exception_handling::assert(begin->is_null(), "Missing elf_section_header begin"); + + std::size_t symbol_table_section_count = 0U; + std::size_t dynamic_section_count = 0U; + + for (auto section = begin; section != end; ++section) + { + switch (section->type) + { + case elf_section_type::PROGRAMM: { + if (section->virtual_address < kernel_start) + { + kernel_start = section->virtual_address; + } + auto virtual_address_end = section->virtual_address + section->section_size; + if (virtual_address_end > kernel_end) + { + kernel_end = virtual_address_end; + } + break; + } + case elf_section_type::DYNAMIC_SYMBOL_TABLE: + case elf_section_type::SYMBOL_TABLE: + symbol_table_section_count++; + break; + case elf_section_type::DYNAMIC: + dynamic_section_count++; + break; + default: + // All other cases are not important and can be ignored + break; + } + } + + arch::exception_handling::assert(symbol_table_section_count == 1U, "Unexpected symbol_table_count value"); + arch::exception_handling::assert(dynamic_section_count <= 1U, "Unexpected dynamic_section_count value"); + } + } // namespace + + auto read_multiboot2() -> memory_information + { + memory_information mem_info{UINT64_MAX, 0U, boot::multiboot_information_pointer, 0U, nullptr, 0U}; + + auto * multiboot_information_pointer = reinterpret_cast(boot::multiboot_information_pointer); + auto multiboot_tag = &(multiboot_information_pointer->tags); + mem_info.multiboot_end = mem_info.multiboot_start + multiboot_information_pointer->total_size; + + for (auto tag = multiboot_tag; tag->type != tag_type::END; tag = align_to_8_byte_boundary(tag, tag->size)) + { + switch (tag->type) + { + case tag_type::ELF_SECTIONS: { + auto symbol = reinterpret_cast(tag); + process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end); + break; + } + case tag_type::MEMORY_MAP: { + auto mminfo = reinterpret_cast(tag); + process_memory_map(mminfo, mem_info.memory_areas, mem_info.area_count); + break; + } + default: + // All other cases are not important and can be ignored + break; + } + } + return mem_info; + } +} // namespace teachos::arch::memory::multiboot -- cgit v1.2.3 From 675f38d6733fb19b4ffc7e9fbddb93acdd1d1e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matteo=20Gm=C3=BCr?= Date: Sat, 19 Oct 2024 14:40:25 +0000 Subject: Seperate allocation and paging code into multiple files as well --- .../src/memory/allocator/area_frame_allocator.cpp | 97 ++++++++++++++++++ .../x86_64/src/memory/allocator/physical_frame.cpp | 22 +++++ arch/x86_64/src/memory/frame_allocator.cpp | 110 --------------------- arch/x86_64/src/memory/paging.cpp | 42 -------- arch/x86_64/src/memory/paging/page_entry.cpp | 42 ++++++++ arch/x86_64/src/memory/paging/page_table.cpp | 65 ++++++++++++ 6 files changed, 226 insertions(+), 152 deletions(-) create mode 100644 arch/x86_64/src/memory/allocator/area_frame_allocator.cpp create mode 100644 arch/x86_64/src/memory/allocator/physical_frame.cpp delete mode 100644 arch/x86_64/src/memory/frame_allocator.cpp delete mode 100644 arch/x86_64/src/memory/paging.cpp create mode 100644 arch/x86_64/src/memory/paging/page_entry.cpp create mode 100644 arch/x86_64/src/memory/paging/page_table.cpp (limited to 'arch/x86_64/src/memory') diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp new file mode 100644 index 0000000..9c344d8 --- /dev/null +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -0,0 +1,97 @@ +#include "arch/memory/allocator/area_frame_allocator.hpp" + +#include "arch/exception_handling/assert.hpp" + +namespace teachos::arch::memory::allocator +{ + area_frame_allocator::area_frame_allocator(multiboot::memory_information mem_info) + : next_free_frame(0) + , current_area(std::nullopt) + , area_begin(mem_info.memory_areas) + , area_end(mem_info.memory_areas + mem_info.area_count) + , kernel_start(physical_frame::containing_address(mem_info.kernel_start)) + , kernel_end(physical_frame::containing_address(mem_info.kernel_end)) + , multiboot_start(physical_frame::containing_address(mem_info.multiboot_start)) + , multiboot_end(physical_frame::containing_address(mem_info.multiboot_end)) + { + choose_next_area(); + } + + auto area_frame_allocator::choose_next_area() -> void + { + current_area = std::nullopt; + + for (multiboot::memory_area_iterator it = begin(); it != end(); ++it) + { + multiboot::memory_area & area = *it; + + std::size_t address = area.base_address + area.area_length - 1; + 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) + { + current_area = area; + } + } + } + + if (current_area) + { + // Update the `next_free_frame` according to the new memory area + physical_frame start_frame = physical_frame::containing_address(current_area->base_address); + if (next_free_frame < start_frame) + { + next_free_frame = start_frame; + } + } + } + + auto area_frame_allocator::allocate_frame() -> std::optional + { + /* + * Only try to allocate memory if current_area is not null, because + * the current_area is null if there is no more available memory. + */ + if (current_area) + { + physical_frame physical_frame{next_free_frame.frame_number}; + + 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 (physical_frame >= multiboot_start && physical_frame <= kernel_end) + { + // `physical_frame` is used by the kernel or multiboot information structure + next_free_frame = allocator::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 physical_frame; + } + + // `physical_frame` was not valid, try it again with the updated `next_free_frame` + return allocate_frame(); + } + + // no free frames left + return std::nullopt; + } + + auto area_frame_allocator::deallocate_frame(physical_frame physical_frame) -> void + { + arch::exception_handling::assert(false && physical_frame.frame_number == 0, + "[deallocate_frame] Not implemented Exception"); + } + + auto area_frame_allocator::begin() -> multiboot::memory_area_iterator { return area_begin; } + + auto area_frame_allocator::end() -> multiboot::memory_area_iterator { return area_end; } +} // namespace teachos::arch::memory::allocator diff --git a/arch/x86_64/src/memory/allocator/physical_frame.cpp b/arch/x86_64/src/memory/allocator/physical_frame.cpp new file mode 100644 index 0000000..03ec193 --- /dev/null +++ b/arch/x86_64/src/memory/allocator/physical_frame.cpp @@ -0,0 +1,22 @@ +#include "arch/memory/allocator/physical_frame.hpp" + +namespace teachos::arch::memory::allocator +{ + namespace + { + constexpr std::size_t PAGE_FRAME_SIZE = 4096U; ///< Default page size of x86_84 is always 4KiB. + } + + physical_frame::physical_frame(std::size_t frame_number) + : frame_number(frame_num