forked from Bananymous/banan-os
Kernel: Start working on heap
This commit is contained in:
parent
6a3b3213cf
commit
633929629c
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue