GDT, page frame allocator

This commit is contained in:
Daniel Hammer
2025-02-27 19:48:03 +04:00
commit 6f1c6f1316
31 changed files with 2016 additions and 0 deletions
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <cstdint>
namespace Memory {
extern std::uint64_t HHDMBase;
inline uint64_t HHDM(uint64_t address) {
return HHDMBase + address;
}
inline uint64_t HHDM(void* address) {
return HHDMBase + (uint64_t)address;
}
inline uint64_t SubHHDM(uint64_t address) {
return address - HHDMBase;
}
inline uint64_t SubHHDM(void* address) {
return SubHHDM((uint64_t)address);
}
inline uint64_t IsHDDMVirtAddr(uint64_t address) {
if (address > HHDMBase) {
return true;
}
return false;
}
};
+49
View File
@@ -0,0 +1,49 @@
#include "Memmap.hpp"
#include <KernelTerminal/terminal.hpp>
#include <Common/Panic.hpp>
#include "PageAllocator.hpp"
using namespace Kt;
namespace Memory {
LargestSection Scan(limine_memmap_response* mmap) {
LargestSection currentLargestSection{};
for (size_t i = 0; i < mmap->entry_count; i++) {
auto entry = mmap->entries[i];
if (entry->base == 0) {
continue;
}
if (entry->type == LIMINE_MEMMAP_USABLE) {
kout << "[Mem] Found conventional memory section (size = " << base::dec << entry->length << " bytes, address = 0x" << base::hex << (uint64_t)entry->base << ")" << newline;
if (entry->length > currentLargestSection.size) {
currentLargestSection = {
.address = (uint64_t)entry->base,
.size = entry->length
};
}
}
}
[[unlikely]] if (currentLargestSection.address == 0) {
Panic("Couldn't find a usable memory section.", System::Registers{});
}
return currentLargestSection;
// PageAllocator pa(currentLargestSection);
// uint64_t alloc1 = (uint64_t)pa.Allocate();
// uint64_t alloc2 = (uint64_t)pa.Allocate();
// pa.Free((void *)alloc2);
// uint64_t alloc3 = (uint64_t)pa.Allocate();
// kout << "0x" << base::hex << alloc1 << "\n";
// kout << "0x" << base::hex << alloc2 << "\n";
// kout << "0x" << base::hex << alloc3 << "\n";
}
};
+15
View File
@@ -0,0 +1,15 @@
#pragma once
#include <limine.h>
#include <cstddef>
using namespace std;
namespace Memory {
// Shared
struct LargestSection {
uint64_t address;
size_t size;
};
LargestSection Scan(limine_memmap_response* mmap);
};
+131
View File
@@ -0,0 +1,131 @@
#include "PageAllocator.hpp"
#include "Memmap.hpp"
#include "HHDM.hpp"
#include <KernelTerminal/terminal.hpp>
namespace Memory
{
#if defined(__x86_64__) || defined(__aarch64__)
#define PAGE_SIZE 4096
#else
#error Sorry, Unimplemented!
#endif
PageAllocator::PageAllocator(LargestSection section)
{
g_section = section;
size_t pages = g_section.size / PAGE_SIZE;
Block *current_ref{&head};
Block *start_block_ptr {(Block *)HHDM(section.address)};
Block& start_block = *start_block_ptr;
start_block = Block {
.size = section.size,
.next = nullptr
};
*start_block_ptr = start_block;
current_ref->next = start_block_ptr;
kout << "[Mem] PageAllocator created for memory section starting at 0x" << Kt::base::hex << section.address << Kt::newline;
}
void* PageAllocator::RequestPage(bool phys) {
bool found_block = false;
Block* current_block_ptr{head.next};
Block* current_prev_ptr{(Block *)&head};
while (!found_block) {
if (current_block_ptr == nullptr) {
kerr << "A PageAllocator was forced to return a Null pointer. (1)" << Kt::newline;
return nullptr;
}
if (current_prev_ptr == nullptr) {
kerr << "A PageAllocator was forced to return a Null pointer. (2)" << Kt::newline;
return nullptr;
}
if (current_block_ptr->size >= 0x1000) { // 0x1000 == 4096
current_block_ptr->size -= 0x1000;
if (!current_block_ptr->size) {
current_prev_ptr->next = current_block_ptr->next;
return (void *)current_block_ptr;
}
Block block_copy = *current_block_ptr;
current_prev_ptr->next = (Block *)(uint64_t)current_block_ptr + 0x1000;
*current_prev_ptr->next = block_copy;
if (phys) {
return (void *)SubHHDM(current_block_ptr);
}
return (void *)current_block_ptr;
} else {
if (current_block_ptr->next != nullptr) {
current_prev_ptr = current_block_ptr;
current_block_ptr = current_block_ptr->next;
} else {
kerr << "A PageAllocator was forced to return a Null pointer. (3)" << Kt::newline;
return nullptr;
}
}
if (current_block_ptr != nullptr) {
if (current_block_ptr->next == nullptr) {
kerr << "A PageAllocator was forced to return a Null pointer. (4)" << Kt::newline;
return nullptr;
}
current_block_ptr = current_block_ptr->next;
} else
{
kerr << "A PageAllocator was forced to return a Null pointer. (5)" << Kt::newline;
return nullptr;
}
}
return nullptr;
}
void PageAllocator::Free(void *pagePtr) {
if (!IsHDDMVirtAddr((uint64_t)pagePtr)) {
pagePtr = (void *)HHDM(pagePtr);
}
Block* fmrNext = head.next;
Block* blockPtr = (Block *)pagePtr;
head.next = blockPtr;
head.next->size = 0x1000;
head.next->next = fmrNext;
}
void PageAllocator::Stress() {
// ~410 MiB
for (size_t i = 0; i < 100000; i++) {
kout << "[Mem] Stress allocation " << Kt::base::dec << i << ": " << "0x" << Kt::base::hex << (uint64_t)Memory::KernelPFA->RequestPage(false) << Kt::newline;
}
}
// Traverses the PageAllocator's linked list for debugging
void PageAllocator::Walk() {
Block* current = {head.next};
size_t i{0};
while (current != nullptr) {
kout << "Block " << Kt::base::dec << i << " {" << current->size << " bytes & address 0x" << Kt::base::hex << (uint64_t)current << "}" << Kt::newline;
current = current->next;
i++;
}
}
};
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "Memmap.hpp"
namespace Memory {
class PageAllocator {
LargestSection g_section;
struct Block {
size_t size;
Block* next;
};
Block head;
public:
PageAllocator(LargestSection section);
void* RequestPage(bool phys = false);
void Free(void *pagePtr);
void Stress();
void Walk();
};
extern PageAllocator* KernelPFA;
};