forked from Bananymous/banan-os
Kernel: kmalloc has now somewhat dynamic storage
Allocations bigger than PAGE_SIZE and those not forced to be identity mapped are now done on a GeneralAllocator. This allows us to use kmalloc for big allocations; bigger than the fixed 1 MiB storage. This is still a hack and the whole kmalloc will have to be rewritten at some point, but for now this does the job :D
This commit is contained in:
parent
388f530edd
commit
5e123031aa
|
@ -137,6 +137,21 @@ namespace IDT
|
||||||
|
|
||||||
extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs)
|
extern "C" void cpp_isr_handler(uint64_t isr, uint64_t error, const Registers* regs)
|
||||||
{
|
{
|
||||||
|
if (isr == ISR::PageFault)
|
||||||
|
{
|
||||||
|
using namespace Kernel;
|
||||||
|
|
||||||
|
vaddr_t vaddr = regs->cr2 & PAGE_ADDR_MASK;
|
||||||
|
|
||||||
|
if (!PageTable::kernel().is_page_free(vaddr))
|
||||||
|
{
|
||||||
|
auto paddr = kmalloc_paddr_of(vaddr);
|
||||||
|
ASSERT(paddr.has_value());
|
||||||
|
PageTable::current().map_page_at(paddr.value(), vaddr, PageTable::Flags::ReadWrite | PageTable::Flags::Present);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pid_t tid = Kernel::Scheduler::current_tid();
|
pid_t tid = Kernel::Scheduler::current_tid();
|
||||||
pid_t pid = tid ? Kernel::Process::current().pid() : 0;
|
pid_t pid = tid ? Kernel::Process::current().pid() : 0;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace Kernel
|
||||||
|
|
||||||
static uint64_t* allocate_page_aligned_page()
|
static uint64_t* allocate_page_aligned_page()
|
||||||
{
|
{
|
||||||
void* page = kmalloc(PAGE_SIZE, PAGE_SIZE);
|
void* page = kmalloc(PAGE_SIZE, PAGE_SIZE, true);
|
||||||
ASSERT(page);
|
ASSERT(page);
|
||||||
memset(page, 0, PAGE_SIZE);
|
memset(page, 0, PAGE_SIZE);
|
||||||
return (uint64_t*)page;
|
return (uint64_t*)page;
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <BAN/Optional.h>
|
||||||
|
#include <kernel/Memory/Types.h>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
void kmalloc_initialize();
|
void kmalloc_initialize();
|
||||||
void kmalloc_dump_info();
|
void kmalloc_dump_info();
|
||||||
|
|
||||||
void* kmalloc(size_t);
|
void* kmalloc(size_t size);
|
||||||
void* kmalloc(size_t, size_t);
|
void* kmalloc(size_t size, size_t align, bool force_identity_map = false);
|
||||||
void kfree(void*);
|
void kfree(void*);
|
||||||
|
|
||||||
|
BAN::Optional<Kernel::paddr_t> kmalloc_paddr_of(Kernel::vaddr_t);
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
#include <BAN/Errors.h>
|
#include <BAN/Errors.h>
|
||||||
#include <kernel/CriticalScope.h>
|
#include <kernel/CriticalScope.h>
|
||||||
#include <kernel/kprint.h>
|
#include <kernel/kprint.h>
|
||||||
|
#include <kernel/Memory/GeneralAllocator.h>
|
||||||
#include <kernel/Memory/kmalloc.h>
|
#include <kernel/Memory/kmalloc.h>
|
||||||
|
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
|
|
||||||
#define MB (1 << 20)
|
#define MB (1 << 20)
|
||||||
|
|
||||||
|
extern uint8_t g_kernel_end[];
|
||||||
|
|
||||||
static constexpr size_t s_kmalloc_min_align = alignof(max_align_t);
|
static constexpr size_t s_kmalloc_min_align = alignof(max_align_t);
|
||||||
|
|
||||||
static uint8_t s_kmalloc_storage[2 * MB];
|
static uint8_t s_kmalloc_storage[2 * MB];
|
||||||
|
|
||||||
|
static BAN::UniqPtr<Kernel::GeneralAllocator> s_general_allocator;
|
||||||
|
|
||||||
struct kmalloc_node
|
struct kmalloc_node
|
||||||
{
|
{
|
||||||
void set_align(ptrdiff_t align) { m_align = align; }
|
void set_align(ptrdiff_t align) { m_align = align; }
|
||||||
|
@ -277,7 +282,7 @@ static void* kmalloc_impl(size_t size, size_t align)
|
||||||
|
|
||||||
void* kmalloc(size_t size)
|
void* kmalloc(size_t size)
|
||||||
{
|
{
|
||||||
return kmalloc(size, s_kmalloc_min_align);
|
return kmalloc(size, s_kmalloc_min_align, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr bool is_power_of_two(size_t value)
|
static constexpr bool is_power_of_two(size_t value)
|
||||||
|
@ -287,16 +292,30 @@ static constexpr bool is_power_of_two(size_t value)
|
||||||
return (value & (value - 1)) == 0;
|
return (value & (value - 1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* kmalloc(size_t size, size_t align)
|
void* kmalloc(size_t size, size_t align, bool force_indentity_map)
|
||||||
{
|
{
|
||||||
const kmalloc_info& info = s_kmalloc_info;
|
const kmalloc_info& info = s_kmalloc_info;
|
||||||
|
|
||||||
ASSERT(is_power_of_two(align));
|
ASSERT(is_power_of_two(align));
|
||||||
if (align < s_kmalloc_min_align)
|
if (align < s_kmalloc_min_align)
|
||||||
align = s_kmalloc_min_align;
|
align = s_kmalloc_min_align;
|
||||||
|
ASSERT(align <= PAGE_SIZE);
|
||||||
|
|
||||||
Kernel::CriticalScope critical;
|
Kernel::CriticalScope critical;
|
||||||
|
|
||||||
|
// FIXME: this is a hack to make more dynamic kmalloc memory
|
||||||
|
if (size > PAGE_SIZE && !force_indentity_map)
|
||||||
|
{
|
||||||
|
using namespace Kernel;
|
||||||
|
|
||||||
|
if (!s_general_allocator)
|
||||||
|
s_general_allocator = MUST(GeneralAllocator::create(PageTable::kernel(), (vaddr_t)g_kernel_end));
|
||||||
|
|
||||||
|
auto vaddr = s_general_allocator->allocate(size);
|
||||||
|
if (vaddr)
|
||||||
|
return (void*)vaddr;
|
||||||
|
}
|
||||||
|
|
||||||
if (size == 0 || size >= info.size)
|
if (size == 0 || size >= info.size)
|
||||||
goto no_memory;
|
goto no_memory;
|
||||||
|
|
||||||
|
@ -331,6 +350,9 @@ void kfree(void* address)
|
||||||
|
|
||||||
Kernel::CriticalScope critical;
|
Kernel::CriticalScope critical;
|
||||||
|
|
||||||
|
if (s_general_allocator && s_general_allocator->deallocate((Kernel::vaddr_t)address))
|
||||||
|
return;
|
||||||
|
|
||||||
if (s_kmalloc_fixed_info.base <= address_uint && address_uint < s_kmalloc_fixed_info.end)
|
if (s_kmalloc_fixed_info.base <= address_uint && address_uint < s_kmalloc_fixed_info.end)
|
||||||
{
|
{
|
||||||
auto& info = s_kmalloc_fixed_info;
|
auto& info = s_kmalloc_fixed_info;
|
||||||
|
@ -386,4 +408,21 @@ void kfree(void* address)
|
||||||
Kernel::panic("Trying to free a pointer {8H} outsize of kmalloc memory", address);
|
Kernel::panic("Trying to free a pointer {8H} outsize of kmalloc memory", address);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BAN::Optional<Kernel::paddr_t> kmalloc_paddr_of(Kernel::vaddr_t vaddr)
|
||||||
|
{
|
||||||
|
using namespace Kernel;
|
||||||
|
|
||||||
|
if (s_general_allocator)
|
||||||
|
{
|
||||||
|
auto paddr = s_general_allocator->paddr_of(vaddr);
|
||||||
|
if (paddr.has_value())
|
||||||
|
return paddr.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vaddr_t)s_kmalloc_storage <= vaddr && vaddr < (vaddr_t)s_kmalloc_storage + sizeof(s_kmalloc_storage))
|
||||||
|
return V2P(vaddr);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
|
@ -133,6 +133,9 @@ extern "C" void kernel_main()
|
||||||
PageTable::initialize();
|
PageTable::initialize();
|
||||||
dprintln("PageTable initialized");
|
dprintln("PageTable initialized");
|
||||||
|
|
||||||
|
Heap::initialize();
|
||||||
|
dprintln("Heap initialzed");
|
||||||
|
|
||||||
TerminalDriver* terminal_driver = VesaTerminalDriver::create();
|
TerminalDriver* terminal_driver = VesaTerminalDriver::create();
|
||||||
ASSERT(terminal_driver);
|
ASSERT(terminal_driver);
|
||||||
dprintln("VESA initialized");
|
dprintln("VESA initialized");
|
||||||
|
@ -141,9 +144,6 @@ extern "C" void kernel_main()
|
||||||
ASSERT(tty1);
|
ASSERT(tty1);
|
||||||
dprintln("TTY initialized");
|
dprintln("TTY initialized");
|
||||||
|
|
||||||
Heap::initialize();
|
|
||||||
dprintln("Heap initialzed");
|
|
||||||
|
|
||||||
parse_command_line();
|
parse_command_line();
|
||||||
dprintln("command line parsed, root='{}'", cmdline.root);
|
dprintln("command line parsed, root='{}'", cmdline.root);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue