diff --git a/meta/targets/kernel-riscv32.ld b/meta/targets/kernel-riscv32.ld index 1f806b8..060af29 100644 --- a/meta/targets/kernel-riscv32.ld +++ b/meta/targets/kernel-riscv32.ld @@ -34,9 +34,7 @@ SECTIONS { . += CONSTANT(MAXPAGESIZE); - stack_start_addr = .; . = ALIGN(4); . += 128 * 1024; /* 128KB */ __stack_top = .; - stack_end_addr = .; } diff --git a/src/kernel/core/mod.c b/src/kernel/core/mod.c index 1aac74e..fcfcef6 100644 --- a/src/kernel/core/mod.c +++ b/src/kernel/core/mod.c @@ -1,9 +1,20 @@ +#include <allocators/slab.h> #include <fmt> #include <hal> +#include <kmalloc> #include <logger> +#include <string.h> void kmain(void) { - info$("Hello, World!"); + kmalloc_init(); + + Allocator kmalloc = kmalloc_allocator(); + char* hello = (char*)kmalloc.alloc(&kmalloc, 14); + memset(hello, 0, 14); + strncpy(hello, "Hello, World!", 13); + info$("%s", hello); + kmalloc.free(&kmalloc, hello, 14); + for (;;) ; } diff --git a/src/kernel/hal/manifest.json b/src/kernel/hal/manifest.json index 8fcd516..95166fe 100644 --- a/src/kernel/hal/manifest.json +++ b/src/kernel/hal/manifest.json @@ -4,6 +4,6 @@ "id": "hal", "requires": [ "hal-impl", - "heap" + "allocators" ] } diff --git a/src/kernel/hal/mod.h b/src/kernel/hal/mod.h index 5c7d773..5b96c74 100644 --- a/src/kernel/hal/mod.h +++ b/src/kernel/hal/mod.h @@ -1,6 +1,7 @@ #pragma once #include <dtb> +#include <helpers/errors.h> #include <io> void hal_setup(void); @@ -16,15 +17,17 @@ typedef enum { HAL_MAP_HUGE = 1 << 4, } HalMapFlags; -typedef enum { - HAL_MAP_OK, - HAL_MAP_PHYS_UNALIGNED, - HAL_MAP_VIRT_UNALIGNED, - HAL_MAP_COULDNT_ALLOCATE, - HAL_MAP_ALREADY_MAPPED, -} HalMappingError; +#define MAPPING_ERRORS(ERR) \ + ERR(HAL_MAP_OK, "Operation completed successfully") \ + ERR(HAL_MAP_PHYS_UNALIGNED, "Physical address is unaligned") \ + ERR(HAL_MAP_VIRT_UNALIGNED, "Virtual address is unaligned") \ + ERR(HAL_MAP_COULDNT_ALLOCATE, "Couldn't allocate memory") \ + ERR(HAL_MAP_ALREADY_MAPPED, "Page is already mapped") -typedef struct _page HalPage; +DECLARE_ERROR_ENUM(HalMapping, MAPPING_ERRORS) +DECLARE_ERROR_STRING(HalMapping, MAPPING_ERRORS) + +typedef struct _hal_page HalPage; HalMappingError hal_map_page(HalPage page, uintptr_t virt, uintptr_t phys, size_t length, uint8_t flags); @@ -32,6 +35,16 @@ void hal_switch_space(HalPage space); size_t page_size(void); +void* hal_mmap_l2h(uintptr_t addr); + +void* hal_mmap_h2l(uintptr_t addr); + +/* === TASKS & SCHEDULING === */ + +typedef struct _hal_context HalContext; + +HalContext* hal_create_context(void); + /* === I/O === */ void hal_putc(int ch); diff --git a/src/kernel/hal/rv32/boot.c b/src/kernel/hal/rv32/boot.c index f4d9e00..a58e651 100644 --- a/src/kernel/hal/rv32/boot.c +++ b/src/kernel/hal/rv32/boot.c @@ -1,7 +1,8 @@ +#include <allocators/bump.h> +#include <allocators/slab.h> #include <dtb> #include <hal> #include <handover-dtb> -#include <heap/bump.h> #include <helpers/mem.h> #include <logger> #include <pmm> diff --git a/src/kernel/hal/rv32/boot.s b/src/kernel/hal/rv32/boot.s index 8cbb97b..ca7f99b 100644 --- a/src/kernel/hal/rv32/boot.s +++ b/src/kernel/hal/rv32/boot.s @@ -1,7 +1,9 @@ .section .text.boot + .global rv32_start .type rv32_start, @function + .global _start _start: mv ra, zero diff --git a/src/kernel/hal/rv32/context.c b/src/kernel/hal/rv32/context.c new file mode 100644 index 0000000..7d5c996 --- /dev/null +++ b/src/kernel/hal/rv32/context.c @@ -0,0 +1,8 @@ +#include <hal> +#include <string.h> + +#include "context.h" + +HalContext* hal_context_create(void) { + return NULL; +} diff --git a/src/kernel/hal/rv32/context.h b/src/kernel/hal/rv32/context.h new file mode 100644 index 0000000..2978066 --- /dev/null +++ b/src/kernel/hal/rv32/context.h @@ -0,0 +1,9 @@ +#pragma once + +#include <hal> + +#include "regs.h" + +struct _hal_context { + Stackframe frame; +}; diff --git a/src/kernel/hal/rv32/exception.c b/src/kernel/hal/rv32/exception.c index 8b111bd..438b3b3 100644 --- a/src/kernel/hal/rv32/exception.c +++ b/src/kernel/hal/rv32/exception.c @@ -42,7 +42,7 @@ static void panic_handler(Stackframe* frame, uint32_t scause, uint32_t stval, ui } } -void exception_handler(Stackframe* frame) { +Stackframe* exception_handler(Stackframe* frame) { uint32_t scause = read_csr$(scause); uint32_t stval = read_csr$(stval); uint32_t user_pc = read_csr$(sepc); @@ -52,4 +52,6 @@ void exception_handler(Stackframe* frame) { } else { panic_handler(frame, scause, stval, user_pc); } + + return frame; } diff --git a/src/kernel/hal/rv32/exception.h b/src/kernel/hal/rv32/exception.h index 5ac5518..70fa1e0 100644 --- a/src/kernel/hal/rv32/exception.h +++ b/src/kernel/hal/rv32/exception.h @@ -4,4 +4,4 @@ extern void interrupt_kernel(void); -void exception_handler(Stackframe* frame); +Stackframe* exception_handler(Stackframe* frame); diff --git a/src/kernel/hal/rv32/exception.s b/src/kernel/hal/rv32/exception.s index de5b2cb..3320fa2 100644 --- a/src/kernel/hal/rv32/exception.s +++ b/src/kernel/hal/rv32/exception.s @@ -40,6 +40,7 @@ interrupt_kernel: mv a0, sp call exception_handler + mv sp, a0 lw ra, 4 * 0(sp) lw gp, 4 * 1(sp) diff --git a/src/kernel/hal/rv32/hal.c b/src/kernel/hal/rv32/hal.c index 4ae210c..b8accb4 100644 --- a/src/kernel/hal/rv32/hal.c +++ b/src/kernel/hal/rv32/hal.c @@ -13,3 +13,11 @@ void hal_brkpoint(void) { size_t page_size(void) { return 4096; } + +void* hal_mmap_l2h(uintptr_t addr) { + return (void*)addr; +} + +void* hal_mmap_h2l(uintptr_t addr) { + return (void*)addr; +} diff --git a/src/kernel/hal/rv32/manifest.json b/src/kernel/hal/rv32/manifest.json index 348c2ad..2bab839 100644 --- a/src/kernel/hal/rv32/manifest.json +++ b/src/kernel/hal/rv32/manifest.json @@ -7,5 +7,5 @@ "sys": ["kernel"] }, "provides": ["hal-impl"], - "requires": ["dtb", "pmm", "handover-dtb"] + "requires": ["dtb", "pmm", "handover-dtb", "kmalloc"] } diff --git a/src/kernel/hal/rv32/paging.c b/src/kernel/hal/rv32/paging.c index f91ab66..8ced693 100644 --- a/src/kernel/hal/rv32/paging.c +++ b/src/kernel/hal/rv32/paging.c @@ -4,6 +4,7 @@ #include <pmm> #include <string.h> +#include "base/mod.h" #include "paging.h" #include "regs.h" @@ -13,8 +14,7 @@ extern uint8_t rodata_start_addr[]; extern uint8_t rodata_end_addr[]; extern uint8_t data_start_addr[]; extern uint8_t data_end_addr[]; -extern uint8_t stack_start_addr[]; -extern uint8_t stack_end_addr[]; +extern uint8_t __stack_top[]; static uint32_t* kernel_page_table = NULL; @@ -93,6 +93,7 @@ void hal_switch_space(HalPage space) { __asm__ volatile("sfence.vma"); } +// TODO: Use new error from <helpers/errors.h> void paging_init(void) { PhysObj page_phys = pmm_alloc(page_size()); if (page_phys.base == 0) { @@ -107,7 +108,7 @@ void paging_init(void) { size_t text_end = align_up$((uintptr_t)text_end_addr, page_size()); HalMappingError err = hal_map_page((HalPage){kernel_page_table}, text_start, text_start, text_end - text_start, HAL_MAP_READ | HAL_MAP_EXEC); if (err != HAL_MAP_OK) { - error$("Couldn't map kernel text, cause: %d", err); + error$("Couldn't map kernel text, cause: %s", HalMappingErrorString(err)); hal_brkpoint(); } @@ -115,7 +116,7 @@ void paging_init(void) { size_t rodata_end = align_up$((uintptr_t)rodata_end_addr, page_size()); err = hal_map_page((HalPage){kernel_page_table}, rodata_start, rodata_start, rodata_end - rodata_start, HAL_MAP_READ); if (err != HAL_MAP_OK) { - error$("Couldn't map kernel rodata, cause: %d", err); + error$("Couldn't map kernel rodata, cause: %s", HalMappingErrorString(err)); hal_brkpoint(); } @@ -123,18 +124,23 @@ void paging_init(void) { size_t data_end = align_up$((uintptr_t)data_end_addr, page_size()); err = hal_map_page((HalPage){kernel_page_table}, data_start, data_start, data_end - data_start, HAL_MAP_READ | HAL_MAP_WRITE); if (err != HAL_MAP_OK) { - error$("Couldn't map kernel data, cause: %d", err); + error$("Couldn't map kernel data, cause: %s", HalMappingErrorString(err)); hal_brkpoint(); } - size_t stack_start = align_down$((uintptr_t)stack_start_addr, page_size()); - size_t stack_end = align_up$((uintptr_t)stack_end_addr, page_size()); + size_t stack_start = align_down$((uintptr_t)__stack_top - kib$(128), page_size()); + size_t stack_end = align_up$((uintptr_t)__stack_top, page_size()); err = hal_map_page((HalPage){kernel_page_table}, stack_start, stack_start, stack_end - stack_start, HAL_MAP_READ | HAL_MAP_WRITE); if (err != HAL_MAP_OK) { - error$("Couldn't map kernel stack, cause: %d", err); + error$("Couldn't map kernel stack, cause: %s", HalMappingErrorString(err)); hal_brkpoint(); } + HandoverRecord rec; + handover_foreach_record(handover(), rec) { + hal_map_page((HalPage){kernel_page_table}, rec.start, rec.start, rec.size, HAL_MAP_READ | HAL_MAP_WRITE); + } + debug$("Switching to page table %p", kernel_page_table); hal_switch_space((HalPage){kernel_page_table}); } diff --git a/src/kernel/hal/rv32/paging.h b/src/kernel/hal/rv32/paging.h index 3b69ad0..38c2958 100644 --- a/src/kernel/hal/rv32/paging.h +++ b/src/kernel/hal/rv32/paging.h @@ -31,7 +31,7 @@ enum mapping_flags { MAPPING_USER = 1 << 4, }; -struct _page { +struct _hal_page { uint32_t* ptr; } __attribute__((packed)); diff --git a/src/kernel/kmalloc/manifest.json b/src/kernel/kmalloc/manifest.json new file mode 100644 index 0000000..9960178 --- /dev/null +++ b/src/kernel/kmalloc/manifest.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", + "type": "lib", + "id": "kmalloc", + "requires": [ + "allocators", + "traits" + ] +} diff --git a/src/kernel/kmalloc/manifest.sync-conflict-20250504-125402-L4Z4EYX.json b/src/kernel/kmalloc/manifest.sync-conflict-20250504-125402-L4Z4EYX.json new file mode 100644 index 0000000..d303096 --- /dev/null +++ b/src/kernel/kmalloc/manifest.sync-conflict-20250504-125402-L4Z4EYX.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", + "id": "kmalloc", + "type": "lib", + "requires": [ + "allocators", + "traits" + ] +} diff --git a/src/kernel/kmalloc/mod.c b/src/kernel/kmalloc/mod.c new file mode 100644 index 0000000..340bb71 --- /dev/null +++ b/src/kernel/kmalloc/mod.c @@ -0,0 +1,70 @@ +#include <allocators/slab.h> +#include <logger> +#include <pmm> + +static SlabAllocator slabs[6] = {0}; + +void kmalloc_init(void) { + Allocator pmm = pmm_allocator(); + + slabs[0] = slab_create(8, &pmm); + slabs[1] = slab_create(16, &pmm); + slabs[2] = slab_create(32, &pmm); + slabs[3] = slab_create(64, &pmm); + slabs[4] = slab_create(128, &pmm); + slabs[5] = slab_create(256, &pmm); +} + +static void* _alloc(__attribute__((unused)) void* ctx, size_t len) { + Allocator* alloc = NULL; + + if (len <= 8) { + alloc = &slabs[0].base; + } else if (len <= 16) { + alloc = &slabs[1].base; + } else if (len <= 32) { + alloc = &slabs[2].base; + } else if (len <= 64) { + alloc = &slabs[3].base; + } else if (len <= 128) { + alloc = &slabs[4].base; + } else if (len <= 256) { + alloc = &slabs[5].base; + } else { + Allocator pmm = pmm_allocator(); + alloc = &pmm; + } + + return alloc->alloc(alloc, len); +} + +static void _free(__attribute__((unused)) void* ctx, void* ptr, size_t len) { + Allocator* alloc = NULL; + + if (len <= 8) { + alloc = &slabs[0].base; + } else if (len <= 16) { + alloc = &slabs[1].base; + } else if (len <= 32) { + alloc = &slabs[2].base; + } else if (len <= 64) { + alloc = &slabs[3].base; + } else if (len <= 128) { + alloc = &slabs[4].base; + } else if (len <= 256) { + alloc = &slabs[5].base; + } else { + Allocator pmm = pmm_allocator(); + alloc = &pmm; + } + + alloc->free(alloc, ptr, len); +} + +Allocator kmalloc_allocator(void) { + return (Allocator){ + .alloc = _alloc, + .free = _free, + .realloc = NULL, + }; +} diff --git a/src/kernel/kmalloc/mod.h b/src/kernel/kmalloc/mod.h new file mode 100644 index 0000000..4b20725 --- /dev/null +++ b/src/kernel/kmalloc/mod.h @@ -0,0 +1,7 @@ +#pragma once + +#include <traits/allocator.h> + +void kmalloc_init(void); + +Allocator kmalloc_allocator(void); diff --git a/src/kernel/kmalloc/mod.sync-conflict-20250504-125402-L4Z4EYX.h b/src/kernel/kmalloc/mod.sync-conflict-20250504-125402-L4Z4EYX.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/src/kernel/kmalloc/mod.sync-conflict-20250504-125402-L4Z4EYX.h @@ -0,0 +1 @@ +#pragma once diff --git a/src/kernel/libs/libc/string.c b/src/kernel/libs/libc/string.c index 8ab67df..9c9b930 100644 --- a/src/kernel/libs/libc/string.c +++ b/src/kernel/libs/libc/string.c @@ -48,3 +48,14 @@ void* memcpy(void* s1, void const* s2, size_t n) { return s1; } + +char* strncpy(char* s1, char const* s2, size_t n) { + size_t i = 0; + + while (s2[i] != 0 && i < n) { + s1[i] = s2[i]; + i++; + } + + return s1; +} diff --git a/src/kernel/libs/libc/string.h b/src/kernel/libs/libc/string.h index 81704f1..db1c94d 100644 --- a/src/kernel/libs/libc/string.h +++ b/src/kernel/libs/libc/string.h @@ -3,6 +3,11 @@ #include <stddef.h> size_t strlen(char const* s); + void* memset(void* s, int c, size_t n); + int strncmp(char const* s1, char const* s2, size_t n); + +char* strncpy(char* s1, char const* s2, size_t n); + void* memcpy(void* s1, void const* s2, size_t n); diff --git a/src/kernel/libs/libc/unistd.c b/src/kernel/libs/libc/unistd.c new file mode 100644 index 0000000..a69214a --- /dev/null +++ b/src/kernel/libs/libc/unistd.c @@ -0,0 +1,7 @@ +#include <hal> + +#include "unistd.h" + +int getpagesize(void) { + return page_size(); +} diff --git a/src/kernel/libs/libc/unistd.h b/src/kernel/libs/libc/unistd.h new file mode 100644 index 0000000..985cce7 --- /dev/null +++ b/src/kernel/libs/libc/unistd.h @@ -0,0 +1,3 @@ +#pragma once + +int getpagesize(void); diff --git a/src/kernel/pmm/mod.c b/src/kernel/pmm/mod.c index 5475871..df2b07b 100644 --- a/src/kernel/pmm/mod.c +++ b/src/kernel/pmm/mod.c @@ -4,6 +4,7 @@ #include <logger> #include <string.h> +#include "base/mod.h" #include "mod.h" static PmmBitmap bitmap = {0}; @@ -50,6 +51,13 @@ void pmm_init(void) { if (record.tag == HANDOVER_FREE && record.size >= bitmap.len) { debug$("Bitmap base: %p", record.start); bitmap.bitmap = (uint8_t*)record.start; + + handover_append(handover(), (HandoverRecord){ + .tag = HANDOVER_RESERVED, + .start = record.start, + .size = bitmap.len, + }); + record.start += bitmap.len; record.size -= bitmap.len; break; @@ -109,3 +117,27 @@ PhysObj pmm_alloc(size_t len) { void pmm_free(PhysObj obj) { pmm_mark_free(obj.base, obj.len); } + +// === ALLOCATOR === + +static void* _alloc(__attribute__((unused)) void* ctx, size_t len) { + PhysObj obj = pmm_alloc(len); + if (obj.len == 0) { + return NULL; + } + + return hal_mmap_l2h(obj.base); +} + +static void _free(__attribute__((unused)) void* ctx, void* ptr, size_t len) { + PhysObj obj = {.base = (uintptr_t)hal_mmap_h2l((uintptr_t)ptr), .len = len}; + pmm_free(obj); +} + +Allocator pmm_allocator(void) { + return (Allocator){ + .alloc = _alloc, + .free = _free, + .realloc = NULL, + }; +} diff --git a/src/kernel/pmm/mod.h b/src/kernel/pmm/mod.h index e230c5d..a4db132 100644 --- a/src/kernel/pmm/mod.h +++ b/src/kernel/pmm/mod.h @@ -3,6 +3,7 @@ #include <stdbool.h> #include <stddef.h> #include <stdint.h> +#include <traits/allocator.h> typedef struct { @@ -25,3 +26,7 @@ struct pmm_alloc_param { PhysObj pmm_alloc(size_t pages); void pmm_init(void); + +void pmm_free(PhysObj obj); + +Allocator pmm_allocator(void); diff --git a/src/kernel/sched/manifest.json b/src/kernel/sched/manifest.json new file mode 100644 index 0000000..7d37590 --- /dev/null +++ b/src/kernel/sched/manifest.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", + "type": "lib", + "id": "sched", + "requires": [] +} diff --git a/src/kernel/sched/mod.c b/src/kernel/sched/mod.c new file mode 100644 index 0000000..dbc62b5 --- /dev/null +++ b/src/kernel/sched/mod.c @@ -0,0 +1,7 @@ +#include "mod.h" + +static size_t pid = 0; + +size_t sched_next_pid(void) { + return pid++; +} diff --git a/src/kernel/sched/mod.h b/src/kernel/sched/mod.h new file mode 100644 index 0000000..42f0a93 --- /dev/null +++ b/src/kernel/sched/mod.h @@ -0,0 +1,7 @@ +#pragma once + +#include <stddef.h> + +void sched_init(void); + +size_t sched_next_pid(void); diff --git a/src/kernel/task/manifest.json b/src/kernel/task/manifest.json new file mode 100644 index 0000000..1982f84 --- /dev/null +++ b/src/kernel/task/manifest.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", + "type": "lib", + "id": "task", + "requires": ["sched"] +} diff --git a/src/kernel/task/mod.c b/src/kernel/task/mod.c new file mode 100644 index 0000000..f0651fb --- /dev/null +++ b/src/kernel/task/mod.c @@ -0,0 +1,23 @@ +#include <helpers/math.h> +#include <sched> +#include <string.h> + +#include "mod.h" + +TaskError task_new(char const* name, HalPage* page_table, uintptr_t ip, Allocator* alloc) { + Task* task = alloc->alloc(alloc, sizeof(Task)); + + if (task == NULL) { + return TASK_COULDNT_ALLOC; + } + + if (page_table == NULL) { + return TASK_PAGE_TABLE_NULL; + } + + task->pid = sched_next_pid(); + task->page_table = page_table; + strncpy(task->name, name, min$(strlen(name), TASK_NAME_LIMIT - 1)); + + return TASK_OK; +} diff --git a/src/kernel/task/mod.h b/src/kernel/task/mod.h new file mode 100644 index 0000000..f4ed9b8 --- /dev/null +++ b/src/kernel/task/mod.h @@ -0,0 +1,25 @@ +#pragma once + +#include <hal> +#include <helpers/errors.h> +#include <stddef.h> +#include <traits/allocator.h> + +#define TASK_NAME_LIMIT (256) + +typedef struct { + char name[TASK_NAME_LIMIT]; + size_t pid; + HalPage* page_table; + HalContext* context; +} Task; + +#define TASK_ERRORS(ERR) \ + ERR(TASK_OK, "Operation completed successfully") \ + ERR(TASK_COULDNT_ALLOC, "Couldn't allocate memory") \ + ERR(TASK_PAGE_TABLE_NULL, "The provided page table is NULL") + +DECLARE_ERROR_ENUM(Task, TASK_ERRORS) +DECLARE_ERROR_STRING(Task, TASK_ERRORS) + +TaskError task_new(char const* name, HalPage* page_table, uintptr_t ip, Allocator* alloc); diff --git a/src/libs/heap/bump.c b/src/libs/allocators/bump.c similarity index 90% rename from src/libs/heap/bump.c rename to src/libs/allocators/bump.c index 448210e..7f7682a 100644 --- a/src/libs/heap/bump.c +++ b/src/libs/allocators/bump.c @@ -1,7 +1,8 @@ -#include "bump.h" #include <helpers/mem.h> #include <logger> +#include "bump.h" + static void* alloc(void* ctx, size_t len) { size_t aligned_len = len & 7 ? align_up$(len, 8) : len; @@ -17,7 +18,7 @@ static void* alloc(void* ctx, size_t len) { return (void*)ptr; } -static void free(void* ctx, __attribute__((unused)) void* ptr) { +static void free(void* ctx, __attribute__((unused)) void* ptr, __attribute__((unused)) size_t len) { BumpAllocator* self = (BumpAllocator*)ctx; self->allocations--; diff --git a/src/libs/heap/bump.h b/src/libs/allocators/bump.h similarity index 100% rename from src/libs/heap/bump.h rename to src/libs/allocators/bump.h diff --git a/src/libs/heap/manifest.json b/src/libs/allocators/manifest.json similarity index 82% rename from src/libs/heap/manifest.json rename to src/libs/allocators/manifest.json index 2640f03..5f2334f 100644 --- a/src/libs/heap/manifest.json +++ b/src/libs/allocators/manifest.json @@ -1,5 +1,5 @@ { "$schema": "https://schemas.cute.engineering/stable/cutekit.manifest.component.v1", - "id": "heap", + "id": "allocators", "type": "lib" } diff --git a/src/libs/allocators/slab.c b/src/libs/allocators/slab.c new file mode 100644 index 0000000..d1cc716 --- /dev/null +++ b/src/libs/allocators/slab.c @@ -0,0 +1,91 @@ +#include <allocators/bump.h> +#include <helpers/mem.h> +#include <logger> +#include <unistd.h> + +#include "slab.h" + +static size_t page_amount(size_t size) { + if (size <= 64) { + return 64; + } else if (size <= 128) { + return 32; + } else if (size <= 512) { + return 16; + } else if (size <= 1024) { + return 8; + } else { + return 4; + } +} + +static void* _alloc(void* ctx, __attribute__((unused)) size_t len) { + SlabAllocator* alloc = (SlabAllocator*)ctx; + if (alloc->root == NULL) { + return NULL; + } + + void* ptr = (void*)(alloc->root->ptr + sizeof(Slab)); + alloc->root = alloc->root->next; + return ptr; +} + +static void _free(void* ctx, void* ptr, __attribute__((unused)) size_t len) { + SlabAllocator* alloc = (SlabAllocator*)ctx; + Slab* free = (Slab*)((uintptr_t)ptr - sizeof(Slab)); + + if (free->ptr + sizeof(Slab) != (uintptr_t)ptr) { + error$("Invalid free %p != %p", free->ptr, ptr); + return; + } + + Slab* slab = alloc->root; + + while (1) { + if (slab->next == NULL) { + break; + } + + slab = slab->next; + } + + slab->next = free; +} + +SlabAllocator slab_create(uintptr_t size, Allocator* page_alloc) { + size_t n_page = page_amount(size + sizeof(Slab)); + void* page = page_alloc->alloc(page_alloc, n_page * getpagesize()); + + if (page == NULL) { + return (SlabAllocator){0}; + } + + size_t sz = align_up$(sizeof(Slab) + size, sizeof(void*)); + BumpAllocator bump = bump_allocator_create(page, n_page * getpagesize()); + Slab* root = bump.base.alloc(&bump, sz); + root->ptr = (uintptr_t)root; + + Slab* slab = root; + + while (1) { + void* ptr = bump.base.alloc(&bump, sz); + + if (ptr == NULL) { + slab->next = NULL; + break; + } + + slab->next = ptr; + slab->next->ptr = (uintptr_t)ptr; + slab = slab->next; + } + + return (SlabAllocator){ + .base = { + .alloc = _alloc, + .free = _free, + .realloc = 0, + }, + .root = root, + }; +} diff --git a/src/libs/allocators/slab.h b/src/libs/allocators/slab.h new file mode 100644 index 0000000..b012881 --- /dev/null +++ b/src/libs/allocators/slab.h @@ -0,0 +1,18 @@ +#pragma once + +#include <stdint.h> +#include <traits/allocator.h> + +#define PAGE_SIZE 4096 + +typedef struct _slab { + uintptr_t ptr; + struct _slab* next; +} Slab; + +typedef struct { + Allocator base; + Slab* root; +} SlabAllocator; + +SlabAllocator slab_create(uintptr_t size, Allocator* page_alloc); diff --git a/src/libs/handover/dtb/mod.c b/src/libs/handover/dtb/mod.c index cc16ba3..b249db6 100644 --- a/src/libs/handover/dtb/mod.c +++ b/src/libs/handover/dtb/mod.c @@ -1,10 +1,7 @@ #include <helpers/mem.h> #include <stdio.h> #include <stdlib.h> -#include <string.h> -#include "handover/base/mod.h" -#include "logger/mod.h" #include "mod.h" static DTBNode* dtb_root = NULL; diff --git a/src/libs/helpers/errors.h b/src/libs/helpers/errors.h new file mode 100644 index 0000000..9469df3 --- /dev/null +++ b/src/libs/helpers/errors.h @@ -0,0 +1,18 @@ +#pragma once + +#define ENUM_ITEM(name, msg) name, +#define STRINGIFY(name, msg) #msg, + +#define DECLARE_ERROR_ENUM(PREFIX, LIST) \ + typedef enum { \ + LIST(ENUM_ITEM) \ + } PREFIX##Error; + +#define DECLARE_ERROR_STRING(PREFIX, LIST) \ + __attribute__((used)) static const char* PREFIX##ErrorStrings[] = { \ + LIST(STRINGIFY) \ + }; \ + \ + inline static char const* PREFIX##ErrorString(PREFIX##Error err) { \ + return PREFIX##ErrorStrings[err]; \ + } diff --git a/src/libs/helpers/math.h b/src/libs/helpers/math.h new file mode 100644 index 0000000..671f722 --- /dev/null +++ b/src/libs/helpers/math.h @@ -0,0 +1,5 @@ +#pragma once + +#define min$(x, y) ((x) < (y) ? (x) : (y)) + +#define max$(x, y) ((x) > (y) ? (x) : (y)) diff --git a/src/libs/traits/allocator.h b/src/libs/traits/allocator.h index f2095ba..9c88e14 100644 --- a/src/libs/traits/allocator.h +++ b/src/libs/traits/allocator.h @@ -5,5 +5,5 @@ typedef struct { void* (*alloc)(void* ctx, size_t len); void* (*realloc)(void* ctx, void* ptr, size_t len); - void (*free)(void* ctx, void* ptr); + void (*free)(void* ctx, void* ptr, size_t len); } Allocator;