diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index feedd900..687a9c56 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCES src/video/TextConsole.cpp src/memory/MemoryManager.cpp src/memory/Heap.cpp + src/memory/MemoryMap.cpp src/boot/Init.cpp src/arch/Serial.cpp src/arch/Timer.cpp diff --git a/kernel/src/memory/MemoryManager.cpp b/kernel/src/memory/MemoryManager.cpp index d788befe..fcae5467 100644 --- a/kernel/src/memory/MemoryManager.cpp +++ b/kernel/src/memory/MemoryManager.cpp @@ -3,6 +3,7 @@ #include "arch/CPU.h" #include "arch/MMU.h" #include "boot/bootboot.h" +#include "memory/MemoryMap.h" #include #include #include @@ -29,23 +30,11 @@ static Bitmap g_frame_bitmap; static usize get_physical_address_space_size() { - MMapEnt* ptr = &bootboot.mmap; - u64 biggest_ptr = 0; - u64 biggest_ptr_size = 0; - u64 mmap_entries = (bootboot.size - 128) / 16; - for (u64 i = 0; i < mmap_entries; i++) - { - if (MMapEnt_Ptr(ptr) > biggest_ptr) - { - biggest_ptr = MMapEnt_Ptr(ptr); - biggest_ptr_size = MMapEnt_Size(ptr); - } + MemoryMapIterator iter; + MemoryMapEntry entry = iter.highest(); - ptr++; - } - - return biggest_ptr + biggest_ptr_size; // This would be the address at the end of the last entry, thus the whole - // address space that was passed to us. + return entry.ptr + entry.size; // This is the address at the end of the last (highest) entry, thus the whole + // address space that was passed to us. } namespace MemoryManager @@ -67,28 +56,15 @@ namespace MemoryManager { u64 total_mem = 0; - void* biggest_usable_memory_block = nullptr; - u64 biggest_usable_memory_block_size = 0; + MemoryMapIterator iter; - // walk the memory map - MMapEnt* ptr = &bootboot.mmap; - u64 mmap_entries = (bootboot.size - 128) / 16; - for (u64 i = 0; i < mmap_entries; i++) - { - u64 size = MMapEnt_Size(ptr); - total_mem += size; - if (!MMapEnt_IsFree(ptr)) - { - ptr++; - continue; - } - if (size > biggest_usable_memory_block_size) - { - biggest_usable_memory_block = (void*)MMapEnt_Ptr(ptr); - biggest_usable_memory_block_size = MMapEnt_Size(ptr); - } - ptr++; - } + MemoryMapEntry entry; + while (iter.next().try_set_value(entry)) { total_mem += entry.size; } + + auto largest_free = iter.largest_free(); + + void* biggest_usable_memory_block = (void*)largest_free.ptr; + u64 biggest_usable_memory_block_size = largest_free.size; // The entire physical address space. May contain inexistent memory holes, thus differs from total_mem which // only counts existent memory. Our bitmap needs to have space for all of the physical address space, since @@ -110,18 +86,17 @@ namespace MemoryManager g_frame_bitmap.clear(true); // Set all pages to used/reserved by default, then clear out the free ones - ptr = &bootboot.mmap; - for (u64 i = 0; i < mmap_entries; i++) + iter.rewind(); + while (iter.next().try_set_value(entry)) { - u64 index = MMapEnt_Ptr(ptr) / ARCH_PAGE_SIZE; - u64 pages = MMapEnt_Size(ptr) / ARCH_PAGE_SIZE; - if (!MMapEnt_IsFree(ptr)) { reserved_mem += MMapEnt_Size(ptr); } + u64 index = entry.ptr / ARCH_PAGE_SIZE; + u64 pages = entry.size / ARCH_PAGE_SIZE; + if (!entry.free) { reserved_mem += entry.size; } else { - free_mem += MMapEnt_Size(ptr); + free_mem += entry.size; g_frame_bitmap.clear_region(index, pages, false); } - ptr++; } lock_frames((u64)frame_bitmap_addr, frame_bitmap_size / ARCH_PAGE_SIZE + 1); diff --git a/kernel/src/memory/MemoryMap.cpp b/kernel/src/memory/MemoryMap.cpp new file mode 100644 index 00000000..7c1fcb80 --- /dev/null +++ b/kernel/src/memory/MemoryMap.cpp @@ -0,0 +1,75 @@ +#include "memory/MemoryMap.h" + +extern BOOTBOOT bootboot; + +static MemoryMapEntry memory_map_entry_from_mmapent(MMapEnt* ent) +{ + MemoryMapEntry result; + result.ptr = MMapEnt_Ptr(ent); + result.size = MMapEnt_Size(ent); + result.free = MMapEnt_IsFree(ent); + return result; +} + +MemoryMapIterator::MemoryMapIterator() +{ + m_mmap_entries = (bootboot.size - 128) / 16; + m_base_ent = &bootboot.mmap; + rewind(); +} + +void MemoryMapIterator::rewind() +{ + m_cur_ent = 0; +} + +Result MemoryMapIterator::at(usize index) +{ + if (index >= m_mmap_entries) return err(ERANGE); + return memory_map_entry_from_mmapent(m_base_ent + index); +} + +Result MemoryMapIterator::next() +{ + return at(m_cur_ent++); +} + +MemoryMapEntry MemoryMapIterator::largest_free() +{ + usize largest_size = 0; + usize largest_index = 0; + + rewind(); + + MemoryMapEntry entry; + while (next().try_set_value(entry)) + { + if (entry.free && entry.size > largest_size) + { + largest_size = entry.size; + largest_index = m_cur_ent - 1; + } + } + + return at(largest_index).release_value(); +} + +MemoryMapEntry MemoryMapIterator::highest() +{ + usize highest_ptr = 0; + usize highest_index = 0; + + rewind(); + + MemoryMapEntry entry; + while (next().try_set_value(entry)) + { + if (entry.ptr > highest_ptr) + { + highest_ptr = entry.ptr; + highest_index = m_cur_ent - 1; + } + } + + return at(highest_index).release_value(); +} \ No newline at end of file diff --git a/kernel/src/memory/MemoryMap.h b/kernel/src/memory/MemoryMap.h new file mode 100644 index 00000000..096bd2a7 --- /dev/null +++ b/kernel/src/memory/MemoryMap.h @@ -0,0 +1,37 @@ +#pragma once +#include "boot/bootboot.h" +#include +#include + +struct MemoryMapEntry +{ + u64 ptr; + u64 size; + bool free; +}; + +class MemoryMapIterator +{ + public: + MemoryMapIterator(); + + void rewind(); + + Result next(); + + MemoryMapEntry largest_free(); + + MemoryMapEntry highest(); + + Result at(usize index); + + usize entries() + { + return m_mmap_entries; + } + + private: + usize m_mmap_entries; + MMapEnt* m_base_ent; + usize m_cur_ent; +}; \ No newline at end of file