Add a RangeAllocator which serves as a physical memory allocator
This commit is contained in:
parent
716974a916
commit
8bff2ee0f5
38
kernel/include/memory/RangeAllocator.h
Normal file
38
kernel/include/memory/RangeAllocator.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class RangeAllocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void init(void* start_address, uint64_t count);
|
||||||
|
void init_from_mmap();
|
||||||
|
|
||||||
|
void* request_page();
|
||||||
|
void free_page(void* address);
|
||||||
|
void free_pages(void* address, uint64_t count);
|
||||||
|
|
||||||
|
void lock_page(void* address);
|
||||||
|
void lock_pages(void* address, uint64_t count);
|
||||||
|
|
||||||
|
uint64_t get_free();
|
||||||
|
uint64_t get_used();
|
||||||
|
uint64_t get_reserved();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reserve_page(void* address);
|
||||||
|
void reserve_pages(void* address, uint64_t count);
|
||||||
|
|
||||||
|
bool bitmap_read(uint64_t index);
|
||||||
|
void bitmap_set(uint64_t index, bool value);
|
||||||
|
|
||||||
|
uint64_t free_mem = 0;
|
||||||
|
uint64_t used_mem = 0;
|
||||||
|
uint64_t reserved_mem = 0;
|
||||||
|
|
||||||
|
char* bitmap_addr;
|
||||||
|
uint64_t bitmap_size;
|
||||||
|
|
||||||
|
uint64_t start_index = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern RangeAllocator physical_allocator;
|
@ -4,6 +4,7 @@
|
|||||||
#include "cpu/CPU.h"
|
#include "cpu/CPU.h"
|
||||||
#include "interrupts/Interrupts.h"
|
#include "interrupts/Interrupts.h"
|
||||||
#include "io/Serial.h"
|
#include "io/Serial.h"
|
||||||
|
#include "memory/RangeAllocator.h"
|
||||||
#include "panic/hang.h"
|
#include "panic/hang.h"
|
||||||
#include "render/Draw.h"
|
#include "render/Draw.h"
|
||||||
#include "render/TextRenderer.h"
|
#include "render/TextRenderer.h"
|
||||||
@ -29,4 +30,6 @@ void Init::early_init()
|
|||||||
|
|
||||||
ASSERT(Draw::try_initialize());
|
ASSERT(Draw::try_initialize());
|
||||||
// ASSERT(TextRenderer::try_initialize());
|
// ASSERT(TextRenderer::try_initialize());
|
||||||
|
|
||||||
|
physical_allocator.init_from_mmap();
|
||||||
}
|
}
|
@ -14,6 +14,7 @@
|
|||||||
#include "log/Log.h"
|
#include "log/Log.h"
|
||||||
#include "memory/KernelHeap.h"
|
#include "memory/KernelHeap.h"
|
||||||
#include "memory/Memory.h"
|
#include "memory/Memory.h"
|
||||||
|
#include "memory/RangeAllocator.h"
|
||||||
#include "panic/hang.h"
|
#include "panic/hang.h"
|
||||||
#include "power/shutdown.h"
|
#include "power/shutdown.h"
|
||||||
#include "render/BBRenderer.h"
|
#include "render/BBRenderer.h"
|
||||||
@ -73,7 +74,26 @@ extern "C" void _start()
|
|||||||
|
|
||||||
kinfoln("Interrupts enabled");
|
kinfoln("Interrupts enabled");
|
||||||
|
|
||||||
printf("%d KB of system memory, %d KB available\n", Memory::get_system() / 1024, Memory::get_usable() / 1024);
|
printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024,
|
||||||
|
physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024,
|
||||||
|
physical_allocator.get_reserved() / 1024);
|
||||||
|
|
||||||
|
void* address = physical_allocator.request_page();
|
||||||
|
printf("Allocated page at address 0x%zx\n", address);
|
||||||
|
|
||||||
|
void* address2 = physical_allocator.request_page();
|
||||||
|
printf("Allocated page at address 0x%zx\n", address2);
|
||||||
|
|
||||||
|
printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024,
|
||||||
|
physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024,
|
||||||
|
physical_allocator.get_reserved() / 1024);
|
||||||
|
|
||||||
|
physical_allocator.free_page(address);
|
||||||
|
printf("Freed page\n");
|
||||||
|
|
||||||
|
printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024,
|
||||||
|
physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024,
|
||||||
|
physical_allocator.get_reserved() / 1024);
|
||||||
|
|
||||||
Debug::DebugStatus::the()->StartBootStage(Color{0x33, 0x33, 0x00, 0xFF});
|
Debug::DebugStatus::the()->StartBootStage(Color{0x33, 0x33, 0x00, 0xFF});
|
||||||
ACPI::SDTHeader* rootSDT = ACPI::GetRSDTOrXSDT();
|
ACPI::SDTHeader* rootSDT = ACPI::GetRSDTOrXSDT();
|
||||||
|
131
kernel/src/memory/RangeAllocator.cpp
Normal file
131
kernel/src/memory/RangeAllocator.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include "memory/RangeAllocator.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "bootboot.h"
|
||||||
|
#include "memory/Memory.h"
|
||||||
|
#include "std/string.h"
|
||||||
|
|
||||||
|
extern BOOTBOOT bootboot;
|
||||||
|
|
||||||
|
RangeAllocator physical_allocator;
|
||||||
|
|
||||||
|
void RangeAllocator::init_from_mmap()
|
||||||
|
{
|
||||||
|
uint64_t total_mem = Memory::get_system();
|
||||||
|
|
||||||
|
void* biggest_chunk = nullptr;
|
||||||
|
uint64_t biggest_chunk_size = 0;
|
||||||
|
|
||||||
|
MMapEnt* ptr = &bootboot.mmap;
|
||||||
|
uint64_t mmap_entries = (bootboot.size - 128) / 16;
|
||||||
|
for (uint64_t i = 0; i < mmap_entries; i++)
|
||||||
|
{
|
||||||
|
if (MMapEnt_Size(ptr) > biggest_chunk_size)
|
||||||
|
{
|
||||||
|
biggest_chunk = (void*)MMapEnt_Ptr(ptr);
|
||||||
|
biggest_chunk_size = MMapEnt_Size(ptr);
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_addr = (char*)biggest_chunk;
|
||||||
|
ASSERT((total_mem / 4096 / 8) < biggest_chunk_size);
|
||||||
|
bitmap_size = total_mem / 4096 / 8 + 1;
|
||||||
|
memset(bitmap_addr, 0, bitmap_size);
|
||||||
|
|
||||||
|
free_mem = total_mem;
|
||||||
|
|
||||||
|
lock_pages(bitmap_addr, bitmap_size / 4096 + 1);
|
||||||
|
|
||||||
|
ptr = &bootboot.mmap;
|
||||||
|
for (uint64_t i = 0; i < mmap_entries; i++)
|
||||||
|
{
|
||||||
|
if (!MMapEnt_IsFree(ptr)) { reserve_pages((void*)MMapEnt_Ptr(ptr), MMapEnt_Size(ptr) / 4096); }
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RangeAllocator::bitmap_read(uint64_t index)
|
||||||
|
{
|
||||||
|
return (bitmap_addr[index / 8] & (0b10000000 >> (index % 8))) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RangeAllocator::bitmap_set(uint64_t index, bool value)
|
||||||
|
{
|
||||||
|
uint64_t byteIndex = index / 8;
|
||||||
|
uint8_t bitIndexer = 0b10000000 >> (index % 8);
|
||||||
|
bitmap_addr[byteIndex] &= ~bitIndexer;
|
||||||
|
if (value) { bitmap_addr[byteIndex] |= bitIndexer; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void* RangeAllocator::request_page()
|
||||||
|
{
|
||||||
|
for (uint64_t index = start_index; index < (bitmap_size * 8); index++)
|
||||||
|
{
|
||||||
|
if (bitmap_read(index)) continue;
|
||||||
|
bitmap_set(index, true);
|
||||||
|
start_index = index + 1;
|
||||||
|
free_mem -= 4096;
|
||||||
|
used_mem += 4096;
|
||||||
|
return (void*)(index * 4096);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RangeAllocator::free_page(void* address)
|
||||||
|
{
|
||||||
|
uint64_t index = (uint64_t)address / 4096;
|
||||||
|
if (!bitmap_read(index)) return;
|
||||||
|
bitmap_set(index, false);
|
||||||
|
used_mem -= 4096;
|
||||||
|
free_mem += 4096;
|
||||||
|
if (start_index > index) start_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RangeAllocator::free_pages(void* address, uint64_t count)
|
||||||
|
{
|
||||||
|
for (uint64_t index = 0; index < count; index++) { free_page((void*)((uint64_t)address + index)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void RangeAllocator::lock_page(void* address)
|
||||||
|
{
|
||||||
|
uint64_t index = (uint64_t)address / 4096;
|
||||||
|
if (bitmap_read(index)) return;
|
||||||
|
bitmap_set(index, true);
|
||||||
|
used_mem += 4096;
|
||||||
|
free_mem -= 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RangeAllocator::reserve_page(void* address)
|
||||||
|
{
|
||||||
|
uint64_t index = (uint64_t)address / 4096;
|
||||||
|
if (bitmap_read(index)) return;
|
||||||
|
bitmap_set(index, true);
|
||||||
|
reserved_mem += 4096;
|
||||||
|
free_mem -= 4096;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RangeAllocator::lock_pages(void* address, uint64_t count)
|
||||||
|
{
|
||||||
|
for (uint64_t index = 0; index < count; index++) { lock_page((void*)((uint64_t)address + index)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void RangeAllocator::reserve_pages(void* address, uint64_t count)
|
||||||
|
{
|
||||||
|
for (uint64_t index = 0; index < count; index++) { reserve_page((void*)((uint64_t)address + index)); }
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t RangeAllocator::get_free()
|
||||||
|
{
|
||||||
|
return free_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t RangeAllocator::get_used()
|
||||||
|
{
|
||||||
|
return used_mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t RangeAllocator::get_reserved()
|
||||||
|
{
|
||||||
|
return reserved_mem;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user