diff options
| author | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-11-02 12:38:22 +0000 |
|---|---|---|
| committer | Matteo Gmür <matteo.gmuer1@ost.ch> | 2024-11-02 12:38:22 +0000 |
| commit | 5ade8e0d5f190f2e439f81232b38b90c49c0cd1e (patch) | |
| tree | 588066a732447371f815a37db9950cd65452f688 | |
| parent | 5ffe7d69545bf098efdd70f105a5df83304b211a (diff) | |
| download | teachos-5ade8e0d5f190f2e439f81232b38b90c49c0cd1e.tar.xz teachos-5ade8e0d5f190f2e439f81232b38b90c49c0cd1e.zip | |
Add comments and improve multiboot information struct usability.
7 files changed, 94 insertions, 49 deletions
diff --git a/arch/x86_64/include/arch/memory/multiboot/reader.hpp b/arch/x86_64/include/arch/memory/multiboot/reader.hpp index a5c4872..9707757 100644 --- a/arch/x86_64/include/arch/memory/multiboot/reader.hpp +++ b/arch/x86_64/include/arch/memory/multiboot/reader.hpp @@ -14,17 +14,12 @@ namespace teachos::arch::memory::multiboot */ 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. - elf_section_header_container::iterator - begin_kernel; ///< Iterator containing non-owning pointer to the first element of all kernel sections. - elf_section_header_container::iterator - end_kernel; ///< Iterator pointing to one past the last element of 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. - memory_area_container::iterator - begin_area; ///< Iterator containing non-owning pointer to the first element of all memory areas. - memory_area_container::iterator end_area; ///< Iterator pointing to one past the last element of all memory areas. + 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. + elf_section_header_container sections; ///< 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. + memory_area_container areas; ///< Contains non-owning pointers to all memory areas. }; /** diff --git a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp index c183aff..71f70b5 100644 --- a/arch/x86_64/include/arch/memory/paging/active_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/active_page_table.hpp @@ -12,8 +12,8 @@ namespace teachos::arch::memory::paging { /** - * @brief Currently active level 4 page table, is used to ensure there is only ever one valid instance and it cannot - * be copied or constructed again. + * @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 { diff --git a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp index df3ba00..54a53f4 100644 --- a/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp +++ b/arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp @@ -7,12 +7,24 @@ namespace teachos::arch::memory::paging { + /** + * @brief By the CPU used level 4 page table. + */ struct inactive_page_table { + /** + * @brief Constructor. + * + * @param frame Frame that should be mapped as the level 4 page table. + * @param active_page_table Actual active page table that should be unmapped so we can map a new level 4 + * page table. + * @param temporary_page Temporary page that should be used to map the given frame as the new level 4 page + * table. + */ inactive_page_table(allocator::physical_frame frame, active_page_table & active_page_table, temporary_page temporary_page); - allocator::physical_frame page_table_level_4_frame; + allocator::physical_frame page_table_level_4_frame; ///< Temporary level 4 page table }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp index 0e2411a..5ee4ea8 100644 --- a/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp +++ b/arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp @@ -14,9 +14,20 @@ namespace teachos::arch::memory::paging typedef shared::container<allocator::physical_frame_iterator> frame_container; + /** + * @brief Kernel mapper that allows to remap the kernel elf sections in C++. + * + * @tparam T Contract the allocator that should be used to allocate frames for the remapping process has to fulfill. + */ template<allocator::FrameAllocator T> struct kernel_mapper { + /** + * @brief Constructor. + * + * @param allocator Allocator that should be used to allocate frames for the remapping process. + * @param mem_info Information about elf kernel sections required for remapping process. + */ kernel_mapper(T & allocator, multiboot::memory_information const & mem_info) : allocator(allocator) , mem_info(mem_info) @@ -24,6 +35,14 @@ namespace teachos::arch::memory::paging // Nothing to do } + /** + * @brief Remap the kernel, meaning we map the entire kernel and all of it's elf sections with the correct flags + * into memory and then replace the created mapping with the current one. + * + * @note We have to use a workaround with an + * inactive page table, that is not used by the CPU to ensure we are not changign memory that we are using. Because + * remapping active kernel memory in the kernel wouldn't work. + */ auto remap_kernel() -> void { temporary_page temp_page{virtual_page{UNUSED_VIRTUAL_ADDRESS}, allocator}; @@ -32,30 +51,51 @@ namespace teachos::arch::memory::paging exception_handling::assert(frame.has_value(), "[Kernel Mapper] Frame could not be allocated and therefore kernel not mapped"); auto const inactive_table = inactive_page_table{frame.value(), active_table, temp_page}; - map_elf_sections(inactive_table, temp_page, active_table); + remap_elf_kernel_sections(inactive_table, temp_page, active_table); } private: - auto map_elf_sections(inactive_page_table inactive_page_table, temporary_page temporary_page, - active_page_table & active_table) -> void + /** + * @brief Remaps the kernel elf sections. This is done with switching the current level 4 page table recursive + * mapping to any unmapped address in memory and then actually mapping the level 4 page table on that address. + * Once the remapping process is done we can restore the original recursive mapping with the complete remapped + * kernel. + * + * @note Because we change the entries we also have to ensure we flush the translation lookaside buffer, before we + * map the entries. + * + * @param inactive_table Level 4 page table we temporarily map the kernel into. + * @param temporary_page Temporary page that should be used for the mapping process and then + * unmapped once finished. + * @param active_table Active level 4 page table that has its recursive mapping overwritten temporarily and then + * restored once the process is finished. + */ + auto remap_elf_kernel_sections(inactive_page_table inactive_table, temporary_page & temporary_page, + active_page_table & active_table) -> void { auto const backup = allocator::physical_frame::containing_address(PAGE_TABLE_LEVEL_4_ADDRESS); auto page_table_level4 = temporary_page.map_table_frame(backup, active_table); - active_table.active_handle[511].set_entry(inactive_page_table.page_table_level_4_frame, + active_table.active_handle[511].set_entry(inactive_table.page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); - map_kernel_sections(active_table); + map_elf_kernel_sections(active_table); page_table_level4[511].set_entry(backup, entry::PRESENT | entry::WRITABLE); tlb_flush_all(); temporary_page.unmap(active_table); } - auto map_kernel_sections(active_page_table & active_table) -> void + /** + * @brief Maps the required entries according to every elf section and it's contained frames. Additionally each of + * thoose frames gets the correct entry flags according to elf section flags. + * + * @param active_table Active level 4 page table that should be used to map the required elf sections into entries. + * Has had its recursive mapping temporarily replaced and points to unmapped place in memory. + */ + auto map_elf_kernel_sections(active_page_table & active_table) -> void { - multiboot::elf_section_header_container sections{mem_info.begin_kernel, mem_info.end_kernel}; - for (auto const & section : sections) + for (auto const & section : mem_info.sections) { if (!section.flags.contains_flags(multiboot::elf_section_flags::OCCUPIES_MEMORY)) { @@ -71,7 +111,7 @@ namespace teachos::arch::memory::paging allocator::physical_frame_iterator const end{end_frame}; frame_container frames{begin, end}; - for (auto frame : frames) + for (auto const & frame : frames) { // TODO: Use actual elf section flags, convert from one to the other flag type. active_table.identity_map(allocator, frame, entry::WRITABLE); @@ -79,8 +119,9 @@ namespace teachos::arch::memory::paging } } - T & allocator; - multiboot::memory_information const & mem_info; + T & allocator; ///< Allocator that should be used to allocate frames for the mapping process. + multiboot::memory_information const & + mem_info; ///< Information about elf kernel sections required for remapping process. }; } // namespace teachos::arch::memory::paging diff --git a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp index 5d56a2a..da4a919 100644 --- a/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp +++ b/arch/x86_64/src/memory/allocator/area_frame_allocator.cpp @@ -11,7 +11,7 @@ namespace teachos::arch::memory::allocator area_frame_allocator::area_frame_allocator(multiboot::memory_information const & mem_info) : next_free_frame(0U) , current_area(std::nullopt) - , memory_areas(mem_info.begin_area, mem_info.end_area) + , memory_areas(mem_info.areas) , 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)) diff --git a/arch/x86_64/src/memory/multiboot/reader.cpp b/arch/x86_64/src/memory/multiboot/reader.cpp index e35baf3..7bdf48f 100644 --- a/arch/x86_64/src/memory/multiboot/reader.cpp +++ b/arch/x86_64/src/memory/multiboot/reader.cpp @@ -18,8 +18,7 @@ namespace teachos::arch::memory::multiboot return reinterpret_cast<T>(reinterpret_cast<uint8_t *>(ptr) + ((size + 7) & ~7)); } - auto process_memory_map(memory_map_header * mminfo, memory_area_container::iterator & begin_area, - memory_area_container::iterator & end_area) -> void + auto process_memory_map(memory_map_header * mminfo) -> memory_area_container { auto const expected_entry_size = mminfo->entry_size; auto constexpr actual_entry_size = sizeof(memory_area); @@ -30,13 +29,13 @@ namespace teachos::arch::memory::multiboot auto const total_entries_size = total_size - sizeof(memory_map_header) + actual_entry_size; auto const number_of_entries = total_entries_size / actual_entry_size; - begin_area = memory_area_container::iterator{&mminfo->entries}; - end_area = begin_area + number_of_entries; + auto const begin = memory_area_container::iterator{&mminfo->entries}; + auto const end = begin + number_of_entries; + return memory_area_container{begin, end}; } - auto process_elf_sections(elf_symbols_section_header * symbol, std::size_t & kernel_start, std::size_t & kernel_end, - elf_section_header_container::iterator & begin_kernel, - elf_section_header_container::iterator & end_kernel) -> void + auto process_elf_sections(elf_symbols_section_header * symbol, std::size_t & kernel_start, + std::size_t & kernel_end) -> elf_section_header_container { auto const expected_entry_size = symbol->entry_size; auto constexpr actual_entry_size = sizeof(elf_section_header); @@ -50,30 +49,30 @@ namespace teachos::arch::memory::multiboot exception_handling::assert(expected_total_size == actual_total_size, "[Multiboot Reader] Unexpected elf symbols section header total size"); - begin_kernel = elf_section_header_container::iterator{reinterpret_cast<elf_section_header *>(&symbol->end)}; - end_kernel = begin_kernel + symbol->number_of_sections; - exception_handling::assert(begin_kernel->is_null(), + auto const begin = elf_section_header_container::iterator{reinterpret_cast<elf_section_header *>(&symbol->end)}; + auto const end = begin + symbol->number_of_sections; + exception_handling::assert(begin->is_null(), "[Multiboot Reader] Elf symbols section not starting with SHT_NULL section"); - elf_section_header_container container{begin_kernel, end_kernel}; + elf_section_header_container sections{begin, end}; auto const elf_section_with_lowest_virtual_address = - std::ranges::min_element(container, [](elf_section_header const & a, elf_section_header const & b) { + std::ranges::min_element(sections, [](elf_section_header const & a, elf_section_header const & b) { return a.virtual_address < b.virtual_address; }); auto const elf_section_with_highest_virtual_address = - std::ranges::max_element(container, [](elf_section_header const & a, elf_section_header const & b) { + std::ranges::max_element(sections, [](elf_section_header const & a, elf_section_header const & b) { auto a_virtual_address_end = a.virtual_address + a.section_size; auto b_virtual_address_end = b.virtual_address + b.section_size; return a_virtual_address_end < b_virtual_address_end; }); - auto const symbol_table_section_count = std::ranges::count_if(container, [](elf_section_header const & section) { + auto const symbol_table_section_count = std::ranges::count_if(sections, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC_SYMBOL_TABLE || section.type == elf_section_type::SYMBOL_TABLE; }); auto const dynamic_section_count = std::ranges::count_if( - container, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC; }); + sections, [](elf_section_header const & section) { return section.type == elf_section_type::DYNAMIC; }); exception_handling::assert( symbol_table_section_count == 1U, @@ -87,6 +86,8 @@ namespace teachos::arch::memory::multiboot auto const highest_elf_section = *elf_section_with_highest_virtual_address; kernel_end = highest_elf_section.virtual_address + highest_elf_section.section_size; + + return sections; } } // namespace @@ -94,12 +95,10 @@ namespace teachos::arch::memory::multiboot { memory_information mem_info{UINT64_MAX, 0U, - elf_section_header_container::iterator{}, - elf_section_header_container::iterator{}, + elf_section_header_container{}, boot::multiboot_information_pointer, 0U, - memory_area_container::iterator{}, - memory_area_container::iterator{}}; + memory_area_container{}}; auto const multiboot_information_pointer = reinterpret_cast<info_header *>(boot::multiboot_information_pointer); auto const multiboot_tag = &multiboot_information_pointer->tags; @@ -111,13 +110,12 @@ namespace teachos::arch::memory::multiboot { case tag_type::ELF_SECTIONS: { auto const symbol = reinterpret_cast<elf_symbols_section_header *>(tag); - process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end, mem_info.begin_kernel, - mem_info.end_kernel); + mem_info.sections = process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end); break; } case tag_type::MEMORY_MAP: { auto const mminfo = reinterpret_cast<memory_map_header *>(tag); - process_memory_map(mminfo, mem_info.begin_area, mem_info.end_area); + mem_info.areas = process_memory_map(mminfo); break; } default: diff --git a/arch/x86_64/src/memory/paging/inactive_page_table.cpp b/arch/x86_64/src/memory/paging/inactive_page_table.cpp index de0421d..0b141e2 100644 --- a/arch/x86_64/src/memory/paging/inactive_page_table.cpp +++ b/arch/x86_64/src/memory/paging/inactive_page_table.cpp @@ -9,7 +9,6 @@ namespace teachos::arch::memory::paging auto table = temporary_page.map_table_frame(page_table_level_4_frame, active_page_table); table.zero_entries(); table[511].set_entry(page_table_level_4_frame, entry::PRESENT | entry::WRITABLE); - temporary_page.unmap(active_page_table); } } // namespace teachos::arch::memory::paging |
