GDT, page frame allocator
This commit is contained in:
@@ -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;
|
||||
}
|
||||
};
|
||||
@@ -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";
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
};
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -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;
|
||||
};
|
||||
Reference in New Issue
Block a user