aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorMatteo Gmür <matteo.gmuer1@ost.ch>2024-11-02 12:38:22 +0000
committerMatteo Gmür <matteo.gmuer1@ost.ch>2024-11-02 12:38:22 +0000
commit5ade8e0d5f190f2e439f81232b38b90c49c0cd1e (patch)
tree588066a732447371f815a37db9950cd65452f688 /arch
parent5ffe7d69545bf098efdd70f105a5df83304b211a (diff)
downloadteachos-5ade8e0d5f190f2e439f81232b38b90c49c0cd1e.tar.xz
teachos-5ade8e0d5f190f2e439f81232b38b90c49c0cd1e.zip
Add comments and improve multiboot information struct usability.
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/include/arch/memory/multiboot/reader.hpp17
-rw-r--r--arch/x86_64/include/arch/memory/paging/active_page_table.hpp4
-rw-r--r--arch/x86_64/include/arch/memory/paging/inactive_page_table.hpp14
-rw-r--r--arch/x86_64/include/arch/memory/paging/kernel_mapper.hpp63
-rw-r--r--arch/x86_64/src/memory/allocator/area_frame_allocator.cpp2
-rw-r--r--arch/x86_64/src/memory/multiboot/reader.cpp42
-rw-r--r--arch/x86_64/src/memory/paging/inactive_page_table.cpp1
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