aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorFabian Imhof <fabian.imhof@ost.ch>2024-10-13 10:58:34 +0000
committerFabian Imhof <fabian.imhof@ost.ch>2024-10-13 10:58:34 +0000
commitb3c8a1819226b7dbaad82623c8294b99c91297ef (patch)
tree30a489862647c2573f6e0d723e0107f0e74869e0 /arch
parent553f3a824511bb8107982b2b2737f5b1dff59855 (diff)
downloadteachos-b3c8a1819226b7dbaad82623c8294b99c91297ef.tar.xz
teachos-b3c8a1819226b7dbaad82623c8294b99c91297ef.zip
continue implementing frame allocator
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/include/arch/memory/frame_allocator.hpp45
-rw-r--r--arch/x86_64/src/kernel/main.cpp99
-rw-r--r--arch/x86_64/src/memory/frame_allocator.cpp13
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;
}
}
}