Use a friendlier way of iterating over the memory map

This commit is contained in:
apio 2022-12-04 15:45:13 +01:00
parent 5aa2d1fa18
commit 5f6c48bd12
Signed by: apio
GPG Key ID: B8A7D06E42258954
4 changed files with 132 additions and 44 deletions

View File

@ -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

View File

@ -3,6 +3,7 @@
#include "arch/CPU.h"
#include "arch/MMU.h"
#include "boot/bootboot.h"
#include "memory/MemoryMap.h"
#include <luna/Alignment.h>
#include <luna/Bitmap.h>
#include <luna/String.h>
@ -29,22 +30,10 @@ 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
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.
}
@ -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);

View File

@ -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<MemoryMapEntry> MemoryMapIterator::at(usize index)
{
if (index >= m_mmap_entries) return err(ERANGE);
return memory_map_entry_from_mmapent(m_base_ent + index);
}
Result<MemoryMapEntry> 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();
}

View File

@ -0,0 +1,37 @@
#pragma once
#include "boot/bootboot.h"
#include <luna/Result.h>
#include <luna/Types.h>
struct MemoryMapEntry
{
u64 ptr;
u64 size;
bool free;
};
class MemoryMapIterator
{
public:
MemoryMapIterator();
void rewind();
Result<MemoryMapEntry> next();
MemoryMapEntry largest_free();
MemoryMapEntry highest();
Result<MemoryMapEntry> at(usize index);
usize entries()
{
return m_mmap_entries;
}
private:
usize m_mmap_entries;
MMapEnt* m_base_ent;
usize m_cur_ent;
};