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:
Bananymous
2023-06-18 23:27:00 +03:00
parent 09c824b90e
commit 9a7b2587af
5 changed files with 69 additions and 10 deletions

View File

@@ -1,16 +1,21 @@
#include <BAN/Errors.h>
#include <kernel/CriticalScope.h>
#include <kernel/kprint.h>
#include <kernel/Memory/GeneralAllocator.h>
#include <kernel/Memory/kmalloc.h>
#include <kernel/Thread.h>
#define MB (1 << 20)
extern uint8_t g_kernel_end[];
static constexpr size_t s_kmalloc_min_align = alignof(max_align_t);
static uint8_t s_kmalloc_storage[2 * MB];
static BAN::UniqPtr<Kernel::GeneralAllocator> s_general_allocator;
struct kmalloc_node
{
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)
{
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)
@@ -287,16 +292,30 @@ static constexpr bool is_power_of_two(size_t value)
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;
ASSERT(is_power_of_two(align));
if (align < s_kmalloc_min_align)
align = s_kmalloc_min_align;
ASSERT(align <= PAGE_SIZE);
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)
goto no_memory;
@@ -331,6 +350,9 @@ void kfree(void* address)
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)
{
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);
}
}
}
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 {};
}