feat/kernel: Added First-Fit algorithm for kernel heap
This commit is contained in:
parent
65fbb97d8a
commit
6374144f4a
6 changed files with 134 additions and 2 deletions
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
|
@ -9,6 +9,10 @@
|
||||||
"typeinfo": "c",
|
"typeinfo": "c",
|
||||||
"log.h": "c",
|
"log.h": "c",
|
||||||
"pmm.h": "c",
|
"pmm.h": "c",
|
||||||
"paging.h": "c"
|
"paging.h": "c",
|
||||||
|
"emk.h": "c",
|
||||||
|
"heap.h": "c",
|
||||||
|
"vmm.h": "c",
|
||||||
|
"align.h": "c"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,12 +4,14 @@
|
||||||
|
|
||||||
#include <boot/limine.h>
|
#include <boot/limine.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <mm/vmm.h>
|
||||||
|
|
||||||
extern uint64_t hhdm_offset;
|
extern uint64_t hhdm_offset;
|
||||||
extern struct limine_memmap_response *memmap;
|
extern struct limine_memmap_response *memmap;
|
||||||
extern uint64_t kvirt;
|
extern uint64_t kvirt;
|
||||||
extern uint64_t kphys;
|
extern uint64_t kphys;
|
||||||
extern uint64_t kstack_top;
|
extern uint64_t kstack_top;
|
||||||
|
extern vctx_t *kvm_ctx;
|
||||||
|
|
||||||
#define HIGHER_HALF(ptr) ((void *)((uint64_t)(ptr) < hhdm_offset ? (uint64_t)(ptr) + hhdm_offset : (uint64_t)(ptr)))
|
#define HIGHER_HALF(ptr) ((void *)((uint64_t)(ptr) < hhdm_offset ? (uint64_t)(ptr) + hhdm_offset : (uint64_t)(ptr)))
|
||||||
#define PHYSICAL(ptr) ((void *)((uint64_t)(ptr) >= hhdm_offset ? (uint64_t)(ptr) - hhdm_offset : (uint64_t)(ptr)))
|
#define PHYSICAL(ptr) ((void *)((uint64_t)(ptr) >= hhdm_offset ? (uint64_t)(ptr) - hhdm_offset : (uint64_t)(ptr)))
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <arch/paging.h>
|
#include <arch/paging.h>
|
||||||
#include <mm/vmm.h>
|
#include <mm/vmm.h>
|
||||||
|
#include <mm/heap.h>
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3);
|
__attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3);
|
||||||
__attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = {
|
__attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = {
|
||||||
|
@ -31,6 +32,7 @@ struct limine_memmap_response *memmap = NULL;
|
||||||
uint64_t kvirt = 0;
|
uint64_t kvirt = 0;
|
||||||
uint64_t kphys = 0;
|
uint64_t kphys = 0;
|
||||||
uint64_t kstack_top = 0;
|
uint64_t kstack_top = 0;
|
||||||
|
vctx_t *kvm_ctx = NULL;
|
||||||
|
|
||||||
void emk_entry(void)
|
void emk_entry(void)
|
||||||
{
|
{
|
||||||
|
@ -91,7 +93,7 @@ void emk_entry(void)
|
||||||
log_early("Initialized paging");
|
log_early("Initialized paging");
|
||||||
|
|
||||||
/* Kernel Virtual Memory Context, not to be confused with KVM */
|
/* Kernel Virtual Memory Context, not to be confused with KVM */
|
||||||
vctx_t *kvm_ctx = vinit(kernel_pagemap, 0x1000);
|
kvm_ctx = vinit(kernel_pagemap, 0x1000);
|
||||||
if (!kvm_ctx)
|
if (!kvm_ctx)
|
||||||
{
|
{
|
||||||
kpanic(NULL, "Failed to create kernel VMM context");
|
kpanic(NULL, "Failed to create kernel VMM context");
|
||||||
|
@ -108,5 +110,18 @@ void emk_entry(void)
|
||||||
vfree(kvm_ctx, b);
|
vfree(kvm_ctx, b);
|
||||||
log_early("Initialized virtual page manager");
|
log_early("Initialized virtual page manager");
|
||||||
|
|
||||||
|
/* Setup kernel heap */
|
||||||
|
heap_init();
|
||||||
|
char *c = kmalloc(1);
|
||||||
|
if (!c)
|
||||||
|
{
|
||||||
|
kpanic(NULL, "Failed to allocate single byte on heap");
|
||||||
|
}
|
||||||
|
|
||||||
|
*c = 32;
|
||||||
|
log_early("Allocated 1 byte @ %llx", (uint64_t)c);
|
||||||
|
kfree(c);
|
||||||
|
log_early("Initialized kernel heap");
|
||||||
|
|
||||||
hlt();
|
hlt();
|
||||||
}
|
}
|
11
kernel/src/mm/heap.h
Normal file
11
kernel/src/mm/heap.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
|
#ifndef HEAP_H
|
||||||
|
#define HEAP_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
void heap_init();
|
||||||
|
void *kmalloc(size_t size);
|
||||||
|
void kfree(void *ptr);
|
||||||
|
|
||||||
|
#endif // HEAP_H
|
82
kernel/src/mm/heap/ff.c
Normal file
82
kernel/src/mm/heap/ff.c
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
|
#include <mm/heap/ff.h>
|
||||||
|
#include <mm/heap.h>
|
||||||
|
#include <mm/vmm.h>
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
#include <boot/emk.h>
|
||||||
|
#include <util/align.h>
|
||||||
|
#include <sys/kpanic.h>
|
||||||
|
|
||||||
|
void *pool;
|
||||||
|
block_t *freelist = NULL;
|
||||||
|
|
||||||
|
void heap_init()
|
||||||
|
{
|
||||||
|
pool = valloc(kvm_ctx, FF_POOL_SIZE, VALLOC_RW);
|
||||||
|
if (!pool)
|
||||||
|
kpanic(NULL, "Failed to alloc memory for the heap pool");
|
||||||
|
freelist = (block_t *)pool;
|
||||||
|
freelist->size = (FF_POOL_SIZE * PAGE_SIZE) - sizeof(block_t);
|
||||||
|
freelist->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *kmalloc(size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size = ALIGN_UP(size, 8);
|
||||||
|
|
||||||
|
block_t *prev = NULL;
|
||||||
|
block_t *cur = freelist;
|
||||||
|
|
||||||
|
while (cur)
|
||||||
|
{
|
||||||
|
if (cur->size >= size)
|
||||||
|
{
|
||||||
|
size_t tot_size = sizeof(block_t) + size;
|
||||||
|
|
||||||
|
if (cur->size >= ALIGN_UP(tot_size + sizeof(block_t), 8))
|
||||||
|
{
|
||||||
|
/* do splitting */
|
||||||
|
block_t *new_block = (block_t *)((uint8_t *)cur + tot_size);
|
||||||
|
new_block->size = cur->size - tot_size;
|
||||||
|
new_block->next = cur->next;
|
||||||
|
|
||||||
|
cur->size = size;
|
||||||
|
|
||||||
|
if (prev)
|
||||||
|
prev->next = new_block;
|
||||||
|
else
|
||||||
|
freelist = new_block;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* use entire block */
|
||||||
|
if (prev)
|
||||||
|
prev->next = cur->next;
|
||||||
|
else
|
||||||
|
freelist = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (void *)((uint8_t *)cur + sizeof(block_t));
|
||||||
|
}
|
||||||
|
prev = cur;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void kfree(void *ptr)
|
||||||
|
{
|
||||||
|
if (!ptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* get block header */
|
||||||
|
block_t *block = (block_t *)((uint8_t *)ptr - sizeof(block_t));
|
||||||
|
|
||||||
|
/* insert freed block at head of freelist */
|
||||||
|
block->next = freelist;
|
||||||
|
freelist = block;
|
||||||
|
}
|
18
kernel/src/mm/heap/ff.h
Normal file
18
kernel/src/mm/heap/ff.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
/* EMK 1.0 Copyright (c) 2025 Piraterna */
|
||||||
|
#ifndef FF_H
|
||||||
|
#define FF_H
|
||||||
|
|
||||||
|
/* Kevin's simple First-Fit allocator */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define FF_POOL_SIZE 512 // 2MB, in pages
|
||||||
|
|
||||||
|
typedef struct block
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
struct block *next;
|
||||||
|
} block_t;
|
||||||
|
|
||||||
|
#endif // FF_H
|
Loading…
Add table
Add a link
Reference in a new issue