diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86_64/include/arch/memory/frame_allocator.hpp | 45 | ||||
| -rw-r--r-- | arch/x86_64/src/kernel/main.cpp | 99 | ||||
| -rw-r--r-- | arch/x86_64/src/memory/frame_allocator.cpp | 13 |
3 files changed, 116 insertions, 41 deletions
diff --git a/arch/x86_64/include/arch/memory/frame_allocator.hpp b/arch/x86_64/include/arch/memory/frame_allocator.hpp index a52cc46..fa22ce5 100644 --- a/arch/x86_64/include/arch/memory/frame_allocator.hpp +++ b/arch/x86_64/include/arch/memory/frame_allocator.hpp @@ -57,8 +57,40 @@ namespace teachos::arch::memory }; /** + * @brief Iterator for memory areas + */ + class memory_area_iterator + { + memory_area * ptr; + + public: + std::size_t begin; + std::size_t end; + + explicit memory_area_iterator(memory_area * p) + : ptr(p) + { + } + + memory_area & operator*() const { return *ptr; } + memory_area_iterator & operator++() + { + ++ptr; + return *this; + } + + memory_area_iterator operator++(int) + { + memory_area_iterator temp = *this; + ++(*this); + return temp; + } + + bool operator==(const memory_area_iterator & other) const { return ptr == other.ptr; } + }; + + /** * @brief Allocates memory using memory areas read from the multiboot2 information pointer - * */ struct area_frame_allocator { @@ -70,6 +102,10 @@ namespace teachos::arch::memory frame multiboot_start; //!< The start address of the multiboot code in memory frame multiboot_end; //!< The end address of the multiboot code in memory + private: + uint8_t N; + + public: /** * @brief Constructor * @@ -80,12 +116,13 @@ namespace teachos::arch::memory * @param memory_areas Pointer to the first element of all memory areas */ 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) + std::size_t multiboot_end, memory_area * memory_areas, uint8_t area_count) : areas(memory_areas) , kernel_start(frame{kernel_start}) , kernel_end(frame{kernel_end}) , multiboot_start(frame{multiboot_start}) , multiboot_end(frame{multiboot_end}) + , N(area_count) { choose_next_area(); } @@ -109,6 +146,10 @@ namespace teachos::arch::memory */ auto deallocate_frame(frame frame) -> void; + memory_area_iterator begin() { return memory_area_iterator(areas); } + + memory_area_iterator end() { return memory_area_iterator(areas + N); } + private: /** * @brief Find the next memory area and write it into current_area diff --git a/arch/x86_64/src/kernel/main.cpp b/arch/x86_64/src/kernel/main.cpp index 01c955b..3fa44d3 100644 --- a/arch/x86_64/src/kernel/main.cpp +++ b/arch/x86_64/src/kernel/main.cpp @@ -1,6 +1,7 @@ #include "arch/kernel/main.hpp" #include "arch/boot/pointers.hpp" +#include "arch/memory/frame_allocator.hpp" #include "arch/memory/multiboot.hpp" #include "arch/video/vga/text.hpp" @@ -20,33 +21,21 @@ namespace teachos::arch::kernel } } - auto print_mem_info(arch::memory::memory_info * mem_info) -> void + auto process_memory_map(arch::memory::memory_map * mminfo, arch::memory::memory_area ** memory_areas, + uint8_t * area_count) -> void { - video::vga::text::write("Memory info low: ", video::vga::text::common_attributes::green_on_black); - video::vga::text::write_number(mem_info->mem_lower, video::vga::text::common_attributes::green_on_black); - } - - auto print_memory_map(arch::memory::memory_map * mminfo) -> void - { - // TODO: Probably same issue as elf sections because the values are kind of weird as well auto expected_entry_size = mminfo->entry_size; constexpr auto actual_entry_size = sizeof(arch::memory::memory_area); assert(expected_entry_size == actual_entry_size); - auto remaining_size = mminfo->tag.size - (4 * sizeof(uint32_t)); - auto entry_amount = remaining_size / mminfo->entry_size; - - auto begin = &mminfo->entries; - auto end = begin + entry_amount; - for (auto entry = begin; entry != end; ++entry) - { - video::vga::text::write("Looping Memory area", video::vga::text::common_attributes::green_on_black); - } + *memory_areas = &mminfo->entries; + *area_count = sizeof(mminfo->entries) / mminfo->entry_size; } - auto print_elf_sections(arch::memory::elf_symbols_section * symbol) -> void + auto process_elf_sections(arch::memory::elf_symbols_section * symbol, uint64_t * kernel_start, + uint64_t * kernel_end) -> void { - // TODO: Check if sectiosn now actually match the elf file + // Validate ELF sections auto expected_entry_size = symbol->entry_size; constexpr auto actual_entry_size = sizeof(arch::memory::elf_section_header); assert(expected_entry_size == actual_entry_size); @@ -66,16 +55,31 @@ namespace teachos::arch::kernel for (auto section = begin; section != end; ++section) { - if (section->type == arch::memory::elf_section_type::DYNAMIC_SYMBOL_TABLE || - section->type == arch::memory::elf_section_type::SYMBOL_TABLE) + switch (section->type) { - symbol_table_section_count++; - } - else if (section->type == arch::memory::elf_section_type::DYNAMIC) - { - dynamic_section_count++; + case arch::memory::elf_section_type::PROGRAMM: + if (section->virtual_address < *kernel_start) + { + *kernel_start = section->virtual_address; + } + + if (section->virtual_address + section->section_size > *kernel_end) + { + *kernel_end = section->virtual_address + section->section_size; + } + 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: + symbol_table_section_count++; + dynamic_section_count++; + break; + default: + // All other cases are not important and can be ignored + break; } - video::vga::text::write("Looping Code section", video::vga::text::common_attributes::green_on_black); } assert(symbol_table_section_count == 1U); @@ -94,6 +98,13 @@ namespace teachos::arch::kernel (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 @@ -106,19 +117,43 @@ namespace teachos::arch::kernel { switch (tag->type) { - case arch::memory::multi_boot_tag_type::BASIC_MEMORY_INFO: - print_mem_info((arch::memory::memory_info *)tag); - break; case arch::memory::multi_boot_tag_type::ELF_SECTIONS: - print_elf_sections((arch::memory::elf_symbols_section *)tag); + process_elf_sections((arch::memory::elf_symbols_section *)tag, &kernel_start, &kernel_end); break; case arch::memory::multi_boot_tag_type::MEMORY_MAP: - print_memory_map((arch::memory::memory_map *)tag); + process_memory_map((arch::memory::memory_map *)tag, &memory_areas, &area_count); break; default: // All other cases are not important and can be ignored break; } } + + // Kernel start 0x100000 + // Kernel end 0x23E943 + // Kernel Size 0x13E943 -> 1'304'899 + // Multiboot start 0x241AA0 + // Multiboot end 0x242280 + // Multiboot Size 0x7E0 -> 2'016 + // Memory area start 0x241b10 + // + // Address of Frame: 0x203F00 + auto allocator = arch::memory::area_frame_allocator(kernel_start, kernel_end, multiboot_start, multiboot_end, + memory_areas, area_count); + std::optional<arch::memory::frame> allocated = allocator.allocate_frame(); + + // WATCH OUT: using optional::value() crashes the build... I think its because of missing exception handling + if (allocated.has_value()) + { + video::vga::text::write("Allocated Frame address: ", video::vga::text::common_attributes::green_on_black); + video::vga::text::write_number(reinterpret_cast<uint64_t>(&allocated->frame_number), + video::vga::text::common_attributes::green_on_black); + video::vga::text::write("Allocated Frame number: ", video::vga::text::common_attributes::green_on_black); + video::vga::text::write_number(allocated->frame_number, video::vga::text::common_attributes::green_on_black); + } + else + { + video::vga::text::write("NO VALUE", video::vga::text::common_attributes::green_on_black); + } } } // namespace teachos::arch::kernel diff --git a/arch/x86_64/src/memory/frame_allocator.cpp b/arch/x86_64/src/memory/frame_allocator.cpp index 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; } } } |
