From db9b7cdbd54767a6d4c7f64d9d2772679d1ad8bf Mon Sep 17 00:00:00 2001 From: Karina Date: Mon, 29 Dec 2025 08:41:51 +0400 Subject: [PATCH] feat: heap, dbg command (currently heap test there) --- kernel/inc/drivers/console.h | 1 + kernel/inc/mm/heap.h | 28 ++++++++++ kernel/inc/mm/memory.h | 3 +- kernel/inc/mm/vmm.h | 4 +- kernel/inc/shell/builtins.h | 1 + kernel/inc/shell/dbgcmd.h | 9 +++ kernel/src/drivers/console.c | 2 +- kernel/src/kmain.c | 21 ++++--- kernel/src/mm/heap.c | 105 +++++++++++++++++++++++++++++++++++ kernel/src/mm/memory.c | 19 +++++++ kernel/src/mm/vmm.c | 18 ++++-- kernel/src/shell/builtins.c | 6 ++ kernel/src/shell/dbgcmd.c | 89 +++++++++++++++++++++++++++++ kernel/src/shell/ksh.c | 3 + 14 files changed, 294 insertions(+), 15 deletions(-) create mode 100644 kernel/inc/mm/heap.h create mode 100644 kernel/inc/shell/dbgcmd.h create mode 100644 kernel/src/mm/heap.c create mode 100644 kernel/src/shell/dbgcmd.c diff --git a/kernel/inc/drivers/console.h b/kernel/inc/drivers/console.h index 5eb948b..6efaa64 100644 --- a/kernel/inc/drivers/console.h +++ b/kernel/inc/drivers/console.h @@ -14,6 +14,7 @@ SG_Point console_get_dimensions(); void console_set_color(u32 color); void console_set_default_color(u32 color); void console_set_cursor_pos(SG_Point *p); +char console_getc(); void kprint(const char *str); void kprintf(const char *fmt, ...); void kgets(char* buff, u32 lim); diff --git a/kernel/inc/mm/heap.h b/kernel/inc/mm/heap.h new file mode 100644 index 0000000..c2f15cc --- /dev/null +++ b/kernel/inc/mm/heap.h @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2025 0xKarinyash + +#ifndef HEAP_H +#define HEAP_H + +#include + +#define KERNEL_HEAP_START 0xFFFFFFFFC0000000 +#define PHYS_TO_HEAP(phys) ((phys) + KERNEL_HEAP_START) +#define HEAP_TO_PHYS(phys) ((phys) - KERNEL_HEAP_START) + +#define HEADER_MAGIC 0x1CE + +typedef struct block_header { + u64 magic; + struct block_header* next; + struct block_header* prev; + u64 size; + bool is_free; +} block_header; + +void heap_init(); +void* malloc(u64 size); +void free(void* ptr); +void* realloc(void* ptr, u64 new_size); + +#endif \ No newline at end of file diff --git a/kernel/inc/mm/memory.h b/kernel/inc/mm/memory.h index 1db35e2..16ec828 100644 --- a/kernel/inc/mm/memory.h +++ b/kernel/inc/mm/memory.h @@ -6,6 +6,7 @@ #include -void *memset(void *ptr, int value, usize num); +void* memset(void* ptr, int value, usize num); +void* memcpy(void* dest, const void* src, u64 n); #endif \ No newline at end of file diff --git a/kernel/inc/mm/vmm.h b/kernel/inc/mm/vmm.h index bdce29b..e6f0bbf 100644 --- a/kernel/inc/mm/vmm.h +++ b/kernel/inc/mm/vmm.h @@ -31,11 +31,13 @@ #define KERNEL_VMA 0xFFFFFFFF80000000 #define HHDM_OFFSET 0xFFFF888000000000 #define FB_VIRT_BASE 0xFFFFFFFFFC000000 + #define KERNEL_VIRT_TO_PHYS(virt) ((virt) - KERNEL_VMA) #define PHYS_TO_HHDM(phys) ((phys) + HHDM_OFFSET) #define HHDM_TO_PHYS(virt) ((virt) - HHDM_OFFSET) + void vmm_init(Bootinfo* info); -void vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags); +u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags); #endif \ No newline at end of file diff --git a/kernel/inc/shell/builtins.h b/kernel/inc/shell/builtins.h index 2950f0b..58d1b96 100644 --- a/kernel/inc/shell/builtins.h +++ b/kernel/inc/shell/builtins.h @@ -10,6 +10,7 @@ void cmd_help(); void cmd_regs(); void print_regs(); void cmd_sleep(); +void cmd_debug(); int rectest(int a); #endif \ No newline at end of file diff --git a/kernel/inc/shell/dbgcmd.h b/kernel/inc/shell/dbgcmd.h new file mode 100644 index 0000000..6c07834 --- /dev/null +++ b/kernel/inc/shell/dbgcmd.h @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2025 0xKarinyash + +#ifndef DBGCMD_H +#define DBGCMD_H + +void debug(); + +#endif \ No newline at end of file diff --git a/kernel/src/drivers/console.c b/kernel/src/drivers/console.c index 4bb30f6..5233e5d 100644 --- a/kernel/src/drivers/console.c +++ b/kernel/src/drivers/console.c @@ -234,7 +234,7 @@ void console_set_default_color(u32 color) { s_def_color = color; } -static char console_getc() { +char console_getc() { while (kb_buf.head == kb_buf.tail) __asm__ volatile ("sti; hlt"); __asm__ volatile ("cli"); char temp = kb_buf.buffer[kb_buf.tail]; diff --git a/kernel/src/kmain.c b/kernel/src/kmain.c index a6e9592..0e22a9c 100644 --- a/kernel/src/kmain.c +++ b/kernel/src/kmain.c @@ -2,7 +2,6 @@ // Copyright (c) 2025 0xKarinyash #include "bootinfo.h" -#include "drivers/timer.h" #include #include @@ -10,6 +9,7 @@ #include #include #include +#include #include #include @@ -17,8 +17,10 @@ #include #include #include + #include #include +#include #define FG_COLOR 0xffffff #define BG_COLOR 0x111111 @@ -30,18 +32,22 @@ void kmain(Bootinfo* info) { serial_init(); serial_write("Kernel started\n"); + console_init(&sg_ctx); + gdt_init(); - serial_write("GDT initialized\n"); + kprintf("GDT initialized\n"); idt_init(); - serial_write("IDT initialized\n"); + kprintf("IDT initialized\n"); pic_remap(); - serial_write("PIC remapped\n"); + kprintf("PIC remapped\n"); pmm_init(&info->mem); - serial_write("PMM initialized\n"); + kprintf("PMM initialized\n"); vmm_init(info); - serial_write("VMM initialized\n"); + kprintf("VMM initialized\n"); timer_init(1000); - serial_write("Timer initialized\n"); + kprintf("Timer initialized\n"); + heap_init(); + kprintf("Heap initialized\n"); info = (Bootinfo*)PHYS_TO_HHDM((u64)info); @@ -53,7 +59,6 @@ void kmain(Bootinfo* info) { sg_ctx.width = info->framebuffer.width; sg_ctx.pitch = info->framebuffer.pitch; - console_init(&sg_ctx); console_clear(BG_COLOR); console_set_color(FG_COLOR); console_set_default_color(FG_COLOR); diff --git a/kernel/src/mm/heap.c b/kernel/src/mm/heap.c new file mode 100644 index 0000000..57cb173 --- /dev/null +++ b/kernel/src/mm/heap.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2025 0xKarinyash + +#include +#include +#include +#include +#include +#include + +#define HEAP_SIZE_PAGES 32 + +extern u64* pml4_kernel; +static block_header* heap_list_head = nullptr; + +void combine_forward(block_header* curr) { + if (!curr->next || !curr->next->is_free) return; + curr->size += sizeof(block_header) + curr->next->size; + curr->next = curr->next->next; + if (curr->next) curr->next->prev = curr; // what the fuck +} + +void heap_init() { + u64 heap_start = KERNEL_HEAP_START; + + for (u64 i = 0; i < HEAP_SIZE_PAGES; i++) { + u64 phys = (u64)pmm_alloc_page(); + if (!phys) panic("OOM during heap init"); + + u64 virt = heap_start + (i * PAGE_SIZE); + vmm_map_page(pml4_kernel, phys, virt, PTE_PRESENT | PTE_RW); + } + + heap_list_head = (block_header*)heap_start; + heap_list_head->magic = HEADER_MAGIC; + heap_list_head->size = (HEAP_SIZE_PAGES * PAGE_SIZE) - sizeof(block_header); + heap_list_head->is_free = true; + heap_list_head->next = nullptr; + heap_list_head->prev = nullptr; +} + +void* malloc(u64 size) { + if (size == 0) return nullptr; + u64 aligned_size = (size + 15) & ~15; + + block_header* curr = heap_list_head; + while (curr) { + if (curr->is_free && curr->size >= aligned_size) { + if (curr->size > aligned_size + sizeof(block_header) + 16) { + block_header* new_block = (block_header*)((u64)curr + sizeof(block_header) + aligned_size); + new_block->size = curr->size - aligned_size - sizeof(block_header); + new_block->is_free = true; + new_block->next = curr->next; + new_block->prev = curr; + new_block->magic = HEADER_MAGIC; + + if (curr->next) curr->next->prev = new_block; + curr->next = new_block; + curr->size = aligned_size; + } + curr->is_free = false; + return (void*)((u64)curr + sizeof(block_header)); + } + curr = curr->next; + } + + return nullptr; +} + +void free(void* ptr) { + if (!ptr) return; + + block_header* curr = (block_header*)((u64)ptr - sizeof(block_header)); + if (curr->magic != HEADER_MAGIC) return; + + curr->is_free = true; + if (curr->next && curr->next->is_free) combine_forward(curr); + if (curr->prev && curr->prev->is_free) combine_forward(curr->prev); +} + +void* realloc(void* ptr, u64 new_size) { + if (!ptr) return malloc(new_size); + if (new_size == 0) { + free(ptr); + return nullptr; + } + + block_header* curr = (block_header*)((u64)ptr - sizeof(block_header)); + if (curr->size >= new_size) return ptr; + + if (curr->next && + curr->next->is_free && + (curr->size + sizeof(block_header) + curr->next->size) >= new_size) { // why ts shit so fucking unreadable + combine_forward(curr); + return ptr; + } + + void* new_ptr = malloc(new_size); + if (!new_ptr) return nullptr; + + memcpy(new_ptr, ptr, curr->size); + free(ptr); + + return new_ptr; +} \ No newline at end of file diff --git a/kernel/src/mm/memory.c b/kernel/src/mm/memory.c index fa836b6..95f21ba 100644 --- a/kernel/src/mm/memory.c +++ b/kernel/src/mm/memory.c @@ -10,4 +10,23 @@ void *memset(void *ptr, int value, usize num) { *p++ = (u8)value; } return ptr; +} + +void* memcpy(void* dest, const void* src, u64 n) { + u8* d = (u8*)dest; + const u8* s = (const u8*)src; + + while (n >= 8) { + *(u64*)d = *(const u64*)s; + d += 8; + s += 8; + n -= 8; + } + + while (n > 0) { + *d++ = *s++; + n--; + } + + return dest; } \ No newline at end of file diff --git a/kernel/src/mm/vmm.c b/kernel/src/mm/vmm.c index 6338a19..8415fd9 100644 --- a/kernel/src/mm/vmm.c +++ b/kernel/src/mm/vmm.c @@ -28,24 +28,29 @@ static u64* get_table_virt(u64 phys) { return (u64*)phys; } -void vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) { +u64* vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) { u64 pt_idx = VMM_PT_INDEX(virt); u64 pd_idx = VMM_PD_INDEX(virt); u64 pdpt_idx = VMM_PDPT_INDEX(virt); u64 pml4_idx = VMM_PML4_INDEX(virt); - if (!(pml4[pml4_idx] & PTE_PRESENT)) { + u64* pml4_virt = pml4; + if (is_initialized) pml4_virt = (u64*)PHYS_TO_HHDM((u64)pml4); + + if (!(pml4_virt[pml4_idx] & PTE_PRESENT)) { u64* addr = pmm_alloc_page(); + if (!addr) return nullptr; u64* addr_virt = get_table_virt((u64)addr); memset(addr_virt, 0, PAGE_SIZE); - pml4[pml4_idx] = (u64)addr | PTE_PRESENT | PTE_RW; + pml4_virt[pml4_idx] = (u64)addr | PTE_PRESENT | PTE_RW; } - u64* pdpt = (u64*)PTE_GET_ADDR(pml4[pml4_idx]); + u64* pdpt = (u64*)PTE_GET_ADDR(pml4_virt[pml4_idx]); u64* pdpt_virt = get_table_virt((u64)pdpt); if (!(pdpt_virt[pdpt_idx] & PTE_PRESENT)) { u64* addr = pmm_alloc_page(); + if (!addr) return nullptr; u64* addr_virt = get_table_virt((u64)addr); memset(addr_virt, 0, PAGE_SIZE); pdpt_virt[pdpt_idx] = (u64)addr | PTE_PRESENT | PTE_RW; @@ -56,6 +61,7 @@ void vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) { if (!(pd_virt[pd_idx] & PTE_PRESENT)) { u64* addr = pmm_alloc_page(); + if (!addr) return nullptr; u64* addr_virt = get_table_virt((u64)addr); memset(addr_virt, 0, PAGE_SIZE); pd_virt[pd_idx] = (u64)addr | PTE_PRESENT | PTE_RW; @@ -64,6 +70,10 @@ void vmm_map_page(u64* pml4, u64 phys, u64 virt, u64 flags) { u64* pt = (u64*)PTE_GET_ADDR(pd_virt[pd_idx]); u64* pt_virt = get_table_virt((u64)pt); pt_virt[pt_idx] = phys | flags; + + __asm__ volatile("invlpg (%0)" :: "r" (virt) : "memory"); + + return (u64*)virt; } void vmm_unmap_page(u64* pml4, u64 virt) { diff --git a/kernel/src/shell/builtins.c b/kernel/src/shell/builtins.c index f112502..14c458c 100644 --- a/kernel/src/shell/builtins.c +++ b/kernel/src/shell/builtins.c @@ -8,6 +8,7 @@ #include #include "../data/cats.h" +#include "shell/dbgcmd.h" const char* ascii_logo[] = { " /\\___/\\ ", @@ -74,4 +75,9 @@ void print_regs(Registers *regs) { void cmd_sleep() { sleep(3000); +} + +void cmd_debug() { + debug(); + return; } \ No newline at end of file diff --git a/kernel/src/shell/dbgcmd.c b/kernel/src/shell/dbgcmd.c new file mode 100644 index 0000000..20c20cb --- /dev/null +++ b/kernel/src/shell/dbgcmd.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// Copyright (c) 2025 0xKarinyash +// contents of this file will be changed CONSTANTLY +// im just testing new stuff here + +#include +#include +#include +#include + +#define VECTOR_BUFFER_SIZE 8 + +typedef struct { + i32* data; + u64 size; + u64 capacity; +} Vector; + +void vector_init(Vector* vec) { + vec->data = nullptr; + vec->size = 0; + vec->capacity = 0; +} + +u8 vector_append(Vector* vec, const i32 num) { + if (vec->size >= vec->capacity) { + u64 new_cap = (vec->capacity == 0) ? VECTOR_BUFFER_SIZE : vec->capacity * 2; + + i32* new_data = realloc(vec->data, new_cap * sizeof(i32)); + if (!new_data) return 2; // Out of memory + + vec->data = new_data; + vec->capacity = new_cap; + } + vec->data[vec->size] = num; + vec->size++; + + return 0; +} + +void vector_reset(Vector* vec) { + vec->size = 0; +} + +u8 vector_reserve(Vector* vec, u64 new_cap) { + if (new_cap <= vec->capacity) return 0; + i32* new_data = realloc(vec->data, new_cap * sizeof(i32)); + if (!new_data) return 2; + + vec->data = new_data; + vec->capacity = new_cap; + + return 0; +} + +void vector_free(Vector* vec) { + free(vec->data); + vec->data = nullptr; + vec->size = vec->capacity = 0; +} + +void render_list(Vector* numbers) { + kprintf("\nNumbers [%d/%d]: [", numbers->size, numbers->capacity); + if (numbers->size == 0) kprintf("]"); + for (u64 i = 0; i < numbers->size; i++) { + kprintf("%d", numbers->data[i]); + if (i + 1 >= numbers->size) { + kprintf("]"); + break; + } + kprintf(", "); + } +} + +void debug() { + Vector nums; + vector_init(&nums); + kprintf("Heap test\n"); + kprintf("press any key to add 1 number press 'q' to exit\n"); + char c = 'd'; + u64 i = 0; + while (c != 'q') { + render_list(&nums); + vector_append(&nums, i); + i++; + c = console_getc(); + } + vector_free(&nums); +} \ No newline at end of file diff --git a/kernel/src/shell/ksh.c b/kernel/src/shell/ksh.c index 6131123..565519d 100644 --- a/kernel/src/shell/ksh.c +++ b/kernel/src/shell/ksh.c @@ -27,6 +27,7 @@ typedef enum { TOKEN_SLEEP, TOKEN_REGS, + TOKEN_DEBUG, TOKEN_RECTEST, TOKEN_PANIC, TOKEN_PANIC_UD2, @@ -58,6 +59,7 @@ static const ksh_command_map token_map[] = { {"neofetch", TOKEN_KFETCH}, {"sleep", TOKEN_SLEEP}, + {"dbg", TOKEN_DEBUG}, {"regs", TOKEN_REGS}, {"rectest", TOKEN_RECTEST}, {"panic", TOKEN_PANIC}, @@ -87,6 +89,7 @@ void ksh() { case TOKEN_QUIT: return; // that'll cause panic lol case TOKEN_SLEEP: cmd_sleep(); break; + case TOKEN_DEBUG: cmd_debug(); break; case TOKEN_REGS: cmd_regs(); break; case TOKEN_RECTEST: rectest(0); break; case TOKEN_PANIC: panic("Manually initiated panic");