Kernel: Start working on heap

This commit is contained in:
Bananymous 2023-04-14 15:16:38 +03:00
parent 6a3b3213cf
commit 633929629c
4 changed files with 169 additions and 0 deletions

View File

@ -26,6 +26,7 @@ set(KERNEL_SOURCES
kernel/Input/PS2Keymap.cpp
kernel/InterruptController.cpp
kernel/kernel.cpp
kernel/Memory/Heap.cpp
kernel/Memory/kmalloc.cpp
kernel/PCI.cpp
kernel/PIC.cpp

View File

@ -0,0 +1,61 @@
#pragma once
#include <BAN/NoCopyMove.h>
#include <BAN/Vector.h>
#include <stdint.h>
#define PAGE_SIZE 4096
namespace Kernel::Memory
{
using paddr_t = uintptr_t;
class PhysicalRange
{
public:
static constexpr paddr_t invalid = ~paddr_t(0);
public:
PhysicalRange(paddr_t, size_t);
paddr_t reserve_page();
void release_page(paddr_t);
paddr_t start() const { return m_start + m_list_pages * PAGE_SIZE; }
paddr_t end() const { return m_start + m_total_pages * PAGE_SIZE; }
uint64_t pages() const { return m_reservable_pages; }
private:
paddr_t page_address(uint64_t) const;
private:
paddr_t m_start { 0 };
size_t m_size { 0 };
uint64_t m_total_pages { 0 };
uint64_t m_reservable_pages { 0 };
uint64_t m_list_pages { 0 };
uint64_t* m_free_list { nullptr };
uint64_t* m_used_list { nullptr };
};
class Heap
{
BAN_NON_COPYABLE(Heap);
BAN_NON_MOVABLE(Heap);
public:
static void initialize();
static Heap& get();
private:
Heap() = default;
void initialize_impl();
private:
BAN::Vector<PhysicalRange> m_physical_ranges;
};
}

View File

@ -0,0 +1,103 @@
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/MMU.h>
#include <kernel/multiboot.h>
extern uint8_t g_kernel_end[];
namespace Kernel::Memory
{
PhysicalRange::PhysicalRange(paddr_t start, size_t size)
{
ASSERT(start + size > (paddr_t)g_kernel_end);
// Align start to page boundary and after the kernel memory
m_start = BAN::Math::max(start, (paddr_t)g_kernel_end);
if (auto rem = m_start % PAGE_SIZE)
m_start += PAGE_SIZE - rem;
// Align size to page boundary
m_size = size - (m_start - start);
if (auto rem = m_size % PAGE_SIZE)
m_size -= rem;
// FIXME: if total pages is just over multiple of (4096/sizeof(uint64_t)) we might make
// couple of pages unallocatable
m_total_pages = m_size / PAGE_SIZE;
m_list_pages = BAN::Math::div_round_up<uint64_t>(m_total_pages * sizeof(uint64_t), PAGE_SIZE);
m_reservable_pages = m_total_pages - m_list_pages;
MMU::get().allocate_range(m_start, m_list_pages * PAGE_SIZE, MMU::Flags::Present);
// Initialize free list with every page pointing to the next one
uint64_t* list_ptr = (uint64_t*)m_start;
for (uint64_t i = 0; i < m_reservable_pages - 1; i++)
{
*list_ptr++ = i + 1;
//dprintln("{}/{}", i, m_reservable_pages);
}
*list_ptr = invalid;
m_free_list = (uint64_t*)m_start;
m_used_list = nullptr;
}
paddr_t PhysicalRange::reserve_page()
{
ASSERT_NOT_REACHED();
}
void PhysicalRange::release_page(paddr_t)
{
ASSERT_NOT_REACHED();
}
paddr_t PhysicalRange::page_address(uint64_t page_index) const
{
ASSERT(page_index < m_reservable_pages);
return m_start + (page_index + m_list_pages) * PAGE_SIZE;
}
static Heap* s_instance = nullptr;
void Heap::initialize()
{
ASSERT(s_instance == nullptr);
s_instance = new Heap;
ASSERT(s_instance);
s_instance->initialize_impl();
}
Heap& Heap::get()
{
ASSERT(s_instance);
return *s_instance;
}
void Heap::initialize_impl()
{
if (!(g_multiboot_info->flags & (1 << 6)))
Kernel::panic("Bootloader did not provide a memory map");
for (size_t i = 0; i < g_multiboot_info->mmap_length;)
{
multiboot_memory_map_t* mmmt = (multiboot_memory_map_t*)(g_multiboot_info->mmap_addr + i);
if (mmmt->type == 1)
{
// We can't use the memory ovelapping with kernel
if (mmmt->base_addr + mmmt->length > (paddr_t)g_kernel_end)
MUST(m_physical_ranges.push_back({ mmmt->base_addr, mmmt->length }));
}
i += mmmt->size + sizeof(uint32_t);
}
for (auto& range : m_physical_ranges)
dprintln("RAM {8H}->{8H}, {} pages ({}.{} MB)", range.start(), range.end(), range.pages(), range.pages() * PAGE_SIZE / (1 << 20), range.pages() * PAGE_SIZE % (1 << 20) * 100 / (1 << 20));
}
}

View File

@ -8,6 +8,7 @@
#include <kernel/Input/PS2Controller.h>
#include <kernel/InterruptController.h>
#include <kernel/kprint.h>
#include <kernel/Memory/Heap.h>
#include <kernel/Memory/kmalloc.h>
#include <kernel/Memory/MMU.h>
#include <kernel/multiboot.h>
@ -136,6 +137,9 @@ extern "C" void kernel_main()
MMU::intialize();
dprintln("MMU initialized");
Memory::Heap::initialize();
dprintln("Heap initialzed");
parse_command_line();
dprintln("command line parsed, root='{}'", cmdline.root);