aboutsummaryrefslogtreecommitdiff
path: root/arch/x86_64/src
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86_64/src')
-rw-r--r--arch/x86_64/src/kernel/main.cpp151
-rw-r--r--arch/x86_64/src/memory/frame_allocator.cpp44
-rw-r--r--arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp (renamed from arch/x86_64/src/memory/multiboot.cpp)6
-rw-r--r--arch/x86_64/src/memory/multiboot/memory_map.cpp24
-rw-r--r--arch/x86_64/src/memory/multiboot/reader.cpp117
5 files changed, 158 insertions, 184 deletions
diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp
index babe251..c0d4aed 100644
--- a/arch/x86_64/src/kernel/main.cpp
+++ b/arch/x86_64/src/kernel/main.cpp
@@ -1,120 +1,14 @@
#include "arch/kernel/main.hpp"
-#include "arch/boot/pointers.hpp"
#include "arch/exception_handling/assert.hpp"
#include "arch/memory/frame_allocator.hpp"
-#include "arch/memory/multiboot.hpp"
+#include "arch/memory/multiboot/reader.hpp"
#include "arch/video/vga/text.hpp"
#include <algorithm>
namespace teachos::arch::kernel
{
- auto process_memory_map(arch::memory::memory_map * mminfo, arch::memory::memory_area *& memory_areas,
- uint8_t & area_count) -> void
- {
- auto expected_entry_size = mminfo->entry_size;
- constexpr auto actual_entry_size = sizeof(arch::memory::memory_area);
- arch::exception_handling::assert(expected_entry_size == actual_entry_size, "Unexpected memoryarea entry size");
-
- auto total_size = mminfo->tag.size;
- auto total_entries_size = total_size - sizeof(arch::memory::memory_map) + 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(arch::memory::elf_symbols_section * symbol, uint64_t & kernel_start,
- uint64_t & kernel_end) -> void
- {
- auto expected_entry_size = symbol->entry_size;
- constexpr auto actual_entry_size = sizeof(arch::memory::elf_section_header);
- arch::exception_handling::assert(expected_entry_size == actual_entry_size,
- "Unexpected elf_section_header entry size");
-
- auto expected_total_size = symbol->tag.size;
- auto actual_total_entry_size = actual_entry_size * symbol->number_of_sections;
- constexpr auto actual_total_section_size = sizeof(arch::memory::elf_symbols_section) - 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 total size");
-
- auto begin = reinterpret_cast<arch::memory::elf_section_header *>(&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)
- {
- bool const writable = section->flags.contains_flags(arch::memory::elf_section_flags::WRITABLE);
- bool const occupies_memory = section->flags.contains_flags(arch::memory::elf_section_flags::OCCUPIES_MEMORY);
- bool const is_executable = section->flags.contains_flags(arch::memory::elf_section_flags::EXECUTABLE_CODE);
- bool const contains_duplicate_data =
- section->flags.contains_flags(arch::memory::elf_section_flags::DUPLICATE_DATA);
- bool const contains_strings = section->flags.contains_flags(arch::memory::elf_section_flags::CONTAINS_STRING);
- bool const section_header_info_is_section_header_table_index = section->flags.contains_flags(
- arch::memory::elf_section_flags::SECTION_HEADER_INFO_IS_SECTION_HEADER_TABLE_INDEX);
- bool const preserve_ordering_after_combination =
- section->flags.contains_flags(arch::memory::elf_section_flags::PRESERVE_ORDERING_AFTER_COMBINATION);
- bool const requires_special_os_processing =
- section->flags.contains_flags(arch::memory::elf_section_flags::REQUIRES_SPECIAL_OS_PROCESSING);
- bool const is_section_group_member =
- section->flags.contains_flags(arch::memory::elf_section_flags::SECTION_GROUP_MEMBER);
- bool const holds_thread_local_data =
- section->flags.contains_flags(arch::memory::elf_section_flags::HOLDS_THREAD_LOCAL_DATA);
- bool const is_compressed = section->flags.contains_flags(arch::memory::elf_section_flags::COMPRESSED);
- bool const has_special_ordering_requirements =
- section->flags.contains_flags(arch::memory::elf_section_flags::SPECIAL_ORDERING_REQUIREMENTS);
- bool const is_excluded_unless_referenced_or_allocated =
- section->flags.contains_flags(arch::memory::elf_section_flags::EXCLUDED_UNLESS_REFERENCED_OR_ALLOCATED);
-
- if (writable && occupies_memory && is_executable && contains_duplicate_data && contains_strings &&
- section_header_info_is_section_header_table_index && preserve_ordering_after_combination &&
- requires_special_os_processing && is_section_group_member && holds_thread_local_data && is_compressed &&
- has_special_ordering_requirements && is_excluded_unless_referenced_or_allocated)
- {
- }
-
- switch (section->type)
- {
- case arch::memory::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 arch::memory::elf_section_type::DYNAMIC_SYMBOL_TABLE:
- case arch::memory::elf_section_type::SYMBOL_TABLE:
- symbol_table_section_count++;
- break;
- case arch::memory::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");
- }
-
- template<typename T>
- requires std::is_pointer<T>::value
- auto align_to_8_byte_boundary(T ptr, uint32_t size) -> T
- {
- return reinterpret_cast<T>(reinterpret_cast<uint8_t *>(ptr) + ((size + 7) & ~7));
- }
-
auto main() -> void
{
using namespace video::vga;
@@ -123,47 +17,8 @@ namespace teachos::arch::kernel
text::cursor(false);
text::write("TeachOS is starting up...", text::common_attributes::green_on_black);
- auto * multiboot_information_pointer =
- reinterpret_cast<arch::memory::multi_boot_info *>(arch::boot::multiboot_information_pointer);
- auto multiboot_tag = &(multiboot_information_pointer->tags);
-
- uint64_t kernel_start = UINT64_MAX;
- uint64_t kernel_end = 0;
- uint64_t multiboot_start = arch::boot::multiboot_information_pointer;
- uint64_t multiboot_end = multiboot_start + multiboot_information_pointer->total_size;
- arch::memory::memory_area * memory_areas = nullptr;
- uint8_t area_count = 0;
-
- /*
- * Loop over the multiboot2 tags to access the information needed.
- * Tags are defined in the header file and are padded so that each
- * Tag starts at an 8-bytes aligned adress.
- *
- * The increment part aligns the size to an 8-byte address.
- */
- for (auto tag = multiboot_tag; tag->type != arch::memory::multi_boot_tag_type::END;
- tag = align_to_8_byte_boundary(tag, tag->size))
- {
- switch (tag->type)
- {
- case arch::memory::multi_boot_tag_type::ELF_SECTIONS: {
- auto symbol = reinterpret_cast<teachos::arch::memory::elf_symbols_section *>(tag);
- process_elf_sections(symbol, kernel_start, kernel_end);
- break;
- }
- case arch::memory::multi_boot_tag_type::MEMORY_MAP: {
- auto mminfo = reinterpret_cast<teachos::arch::memory::memory_map *>(tag);
- process_memory_map(mminfo, memory_areas, area_count);
- break;
- }
- default:
- // All other cases are not important and can be ignored
- break;
- }
- }
-
- auto allocator = arch::memory::area_frame_allocator(kernel_start, kernel_end, multiboot_start, multiboot_end,
- memory_areas, area_count);
+ auto memory_information = memory::multiboot::read_multiboot2();
+ auto allocator = memory::area_frame_allocator(memory_information);
auto last_allocated = allocator.allocate_frame();
auto allocated = last_allocated;
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/elf_symbols_section.cpp
index 8c6793e..78ab952 100644
--- a/arch/x86_64/src/memory/multiboot.cpp
+++ b/arch/x86_64/src/memory/multiboot/elf_symbols_section.cpp
@@ -1,6 +1,6 @@
-#include "arch/memory/multiboot.hpp"
+#include "arch/memory/multiboot/elf_sybols_section.hpp"
-namespace teachos::arch::memory
+namespace teachos::arch::memory::multiboot
{
auto elf_section_flags::contains_flags(std::bitset<64U> other) const -> bool { return (flags & other) == other; }
@@ -10,4 +10,4 @@ namespace teachos::arch::memory
virtual_address == 0U && file_offset == 0U && additional_information == 0U && address_alignment == 0U &&
fixed_table_entry_size == 0U;
}
-} // namespace teachos::arch::memory
+} // 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<typename T>
+ requires std::is_pointer<T>::value
+ auto align_to_8_byte_boundary(T ptr, uint32_t size) -> T
+ {
+ return reinterpret_cast<T>(reinterpret_cast<uint8_t *>(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<elf_section_header *>(&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<info_header *>(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<elf_symbols_section_header *>(tag);
+ process_elf_sections(symbol, mem_info.kernel_start, mem_info.kernel_end);
+ break;
+ }
+ case tag_type::MEMORY_MAP: {
+ auto mminfo = reinterpret_cast<memory_map_header *>(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