From 4e40a040ddd65ea064ea1e4750ecf5babf6b6518 Mon Sep 17 00:00:00 2001 From: ssimnb <250598700+ssimnb@users.noreply.github.com> Date: Thu, 22 Jan 2026 08:05:47 +0100 Subject: [PATCH] Initial commit - slab allocator, kmalloc, other re factors --- .vscode/settings.json | 6 + Makefile | 7 +- autodebug.sh | 3 +- slaballoc.c | 64 ----- slaballoc.h | 38 --- src/drivers/ahci.c | 6 +- src/drivers/pmt.c | 6 +- src/drivers/serial.c | 4 +- src/hal/apic.c | 6 +- src/hal/gdt.c | 2 +- src/hal/idt.c | 14 +- src/hal/ioapic.c | 4 +- src/hal/smp.c | 8 +- src/hal/timer.c | 4 +- src/hal/tsc.c | 2 +- src/include/SFB25.h | 2 + src/include/kmath.h | 1 + src/include/{stdio.h => kprint.h} | 2 +- src/include/lock.h | 4 +- src/lib/{stdio.c => kprint.c} | 37 +-- src/lib/spinlock.c | 6 +- src/lib/string.c | 2 +- src/main.c | 76 ++++-- src/mm/kmalloc.c | 188 +++---------- src/mm/kmalloc.h | 9 +- src/mm/page.c | 61 +++++ src/mm/page.h | 10 + src/mm/pmm.c | 14 +- src/mm/pmm.h | 3 +- src/mm/slab.c | 437 ++++++++++++++++++++++++++++++ src/mm/slab.h | 57 ++++ src/mm/vmm.c | 99 +++++-- src/mm/vmm.h | 10 +- src/scheduler/sched.c | 4 +- src/sys/acpi.c | 18 +- src/sys/pci.c | 20 +- src/sys/rand.c | 36 +++ src/sys/rand.h | 3 + src/uacpi_kernel_api.c | 2 +- 39 files changed, 863 insertions(+), 412 deletions(-) create mode 100644 .vscode/settings.json delete mode 100644 slaballoc.c delete mode 100644 slaballoc.h create mode 100644 src/include/kmath.h rename src/include/{stdio.h => kprint.h} (95%) rename src/lib/{stdio.c => kprint.c} (88%) create mode 100644 src/mm/page.c create mode 100644 src/mm/page.h create mode 100644 src/mm/slab.c create mode 100644 src/mm/slab.h create mode 100644 src/sys/rand.c create mode 100644 src/sys/rand.h diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..84954c5 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "clangd.arguments": [ + "--background-index" + ] + +} \ No newline at end of file diff --git a/Makefile b/Makefile index cb8b5b5..17add98 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ all: $(CC) -c src/flanterm/src/flanterm.c -o $(BUILD_DIR)/flanterm.o $(CFLAGS) $(CC) -c src/flanterm/src/flanterm_backends/fb.c -o $(BUILD_DIR)/fb.o $(CFLAGS) $(CC) -c src/lib/string.c -o $(BUILD_DIR)/string.o $(CFLAGS) - $(CC) -c src/lib/stdio.c -o $(BUILD_DIR)/stdio.o $(CFLAGS) + $(CC) -c src/lib/kprint.c -o $(BUILD_DIR)/kprint.o $(CFLAGS) $(CC) -c src/lib/io.c -o $(BUILD_DIR)/io.o $(CFLAGS) $(CC) -c src/lib/spinlock.c -o $(BUILD_DIR)/spinlock.o $(CFLAGS) @@ -61,8 +61,11 @@ all: $(CC) -c src/hal/timer.c -o $(BUILD_DIR)/timer.o $(CFLAGS) $(CC) -c src/hal/smp.c -o $(BUILD_DIR)/smp.o $(CFLAGS) $(CC) -c src/hal/tsc.c -o $(BUILD_DIR)/tsc.o $(CFLAGS) + $(CC) -c src/sys/rand.c -o $(BUILD_DIR)/rand.o $(CFLAGS) $(CC) -c src/mm/pmm.c -o $(BUILD_DIR)/pmm.o $(CFLAGS) $(CC) -c src/mm/vmm.c -o $(BUILD_DIR)/vmm.o $(CFLAGS) + $(CC) -c src/mm/page.c -o $(BUILD_DIR)/page.o $(CFLAGS) + $(CC) -c src/mm/slab.c -o $(BUILD_DIR)/slab.o $(CFLAGS) $(CC) -c src/mm/kmalloc.c -o $(BUILD_DIR)/kmalloc.o $(CFLAGS) $(CC) -c src/sys/acpi.c -o $(BUILD_DIR)/acpi.o $(CFLAGS) $(CC) -c src/sys/pci.c -o $(BUILD_DIR)/pci.o $(CFLAGS) @@ -100,3 +103,5 @@ disk: dd if=/dev/zero of=disk.img bs=1M count=128 elftest: $(CC) src/elf/elftest.c -o $(BUILD_DIR)/elftest -ffreestanding -Isrc/include -static -fPIE -nostdlib +clean: + rm -r build/ diff --git a/autodebug.sh b/autodebug.sh index 7199ded..88ab342 100755 --- a/autodebug.sh +++ b/autodebug.sh @@ -3,11 +3,12 @@ # Args are fed to QEMU, then GDB and everything else does shit automagically # 1st arg: terminal name to spawn GDB # 2nd arg: place to breakpoint in +# 3rd+ arguments all get passed to QEMU termname=$1 breakpoint=$2 shift 2 -qemu-system-x86_64 "$@" & +qemu-system-x86_64 -s -S "$@" & sleep 1 diff --git a/slaballoc.c b/slaballoc.c deleted file mode 100644 index e7a37b5..0000000 --- a/slaballoc.c +++ /dev/null @@ -1,64 +0,0 @@ -#include -#include -#include "slaballoc.h" - -char memory[4096 * 10]; - -int cnt = 0; - -struct ma_kcache *head = NULL; // create standard sizes - - -uint64_t *alloc_contigious_pages(int num){ - uint64_t *ret = (uint64_t*)(memory + cnt*4096); - cnt+=num; - return ret; -} - - -struct ma_slab *_ma_alloc_initial_slab(struct ma_kcache *kcache){ - uint64_t *p = alloc_contigious_pages(1); - - int bufnum = (4096 - sizeof(struct ma_slab)) / kcache->objsize; // Calculate the number of buffers in this slab - - for(int i = 0; i < bufnum; i++){ - (uint64_t*)((uint64_t)p + i * kcache->objsize) - } - -} - -struct ma_kcache *ma_cache_create(char *name, size_t size, uint32_t flags, void (*constructor)(void *, size_t), void (*destructor)(void *, size_t)){ - - struct ma_kcache *kcache = (struct ma_kcache*)alloc_contigious_pages(1); - - head->next = kcache; - kcache->prev = head; - head = kcache; - - int bufnum = (4096 - sizeof(struct ma_slab)) / size; // Calculate the number of buffers in this slab - - struct ma_slab *slab_structure = (struct ma_slab*)((uint64_t)kcache - sizeof(struct ma_slab)); - - kcache->slabs_free = slab_structure; - - return kcache; - - -} - -void *ma_cache_alloc(struct ma_kcache *cache, uint64_t flags){ - - if(cache->slabs_free == NULL){ - if(cache->slabs_partial == NULL){ - - } - } - - common: - - -} - -int main(){ - -} diff --git a/slaballoc.h b/slaballoc.h deleted file mode 100644 index 9d4da4e..0000000 --- a/slaballoc.h +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include -#define KCACHE_NAME_LEN 5 - - -struct ma_bufctrl { - struct ma_bufctrl *next; - size_t *startaddr; -}; - - -struct ma_slab { - struct ma_slab *next; - struct ma_slab *prev; - - struct ma_bufctrl *buf_list; - - uint32_t refcount; - -}; - -struct ma_kcache { - struct ma_kcache *next; - struct ma_kcache *prev; - - uint32_t objsize; - uint32_t flags; - uint32_t num; - - struct ma_slab *slabs_free; - struct ma_slab *slabs_partial; - struct ma_slab *slabs_used; - - struct ma_bufctrl *bufctrl_arr; - - char name[KCACHE_NAME_LEN]; -}; \ No newline at end of file diff --git a/src/drivers/ahci.c b/src/drivers/ahci.c index 4ecdb89..33bbc20 100644 --- a/src/drivers/ahci.c +++ b/src/drivers/ahci.c @@ -1,6 +1,6 @@ #include -#include +#include #include "../hal/apic.h" #include "../sys/pci.h" #include "../mm/vmm.h" @@ -34,7 +34,7 @@ void ahci_init(){ pci_header_0_t *header = (pci_header_0_t *)pci_find_device(AHCI_CLASS_ID, AHCI_SUBCLASS_ID); if(!header){ - klog(LOG_ERROR, __func__, "AHCI controller not found!"); + klog(__func__, "AHCI controller not found!"); kkill(); } @@ -50,7 +50,7 @@ void ahci_init(){ header->header.command |= AHCI_MSE | AHCI_BME | AHCI_INT_ENABLED; /* Map the AHCI registers */ - kernel_map_pages((uint64_t*)ahci_base_address, 1, PTE_BIT_RW | PTE_BIT_NX | PTE_BIT_UNCACHABLE); + kmap_pages((uint64_t*)ahci_base_address, 1, PTE_BIT_RW | PTE_BIT_NX | PTE_BIT_UNCACHABLE); ahci_base_address += hhdmoffset; diff --git a/src/drivers/pmt.c b/src/drivers/pmt.c index 9ef5656..18f93aa 100644 --- a/src/drivers/pmt.c +++ b/src/drivers/pmt.c @@ -1,5 +1,5 @@ #include "../sys/acpi.h" -#include +#include #include #include @@ -27,7 +27,7 @@ uint64_t pmt_read_reg(gas_t X_PMTimerBlock){ return inl(X_PMTimerBlock.address); }else{ serial_kprintf("address id: 0x{xn}", X_PMTimerBlock.address_space_id); - klog(LOG_ERROR, __func__, "X_PMTimerBlock address space id isn't supported!"); + klog(__func__, "X_PMTimerBlock address space id isn't supported!"); return 0; } } @@ -36,7 +36,7 @@ int pmt_init(){ fadt = (fadt_t*)((uint64_t)find_acpi_table("FACP")); if(!fadt){ - klog(LOG_ERROR, __func__, "Didn't find FADT table"); + klog(__func__, "Didn't find FADT table"); kkill(); } diff --git a/src/drivers/serial.c b/src/drivers/serial.c index a18caf6..749e3da 100644 --- a/src/drivers/serial.c +++ b/src/drivers/serial.c @@ -1,7 +1,7 @@ #include "../sys/acpi.h" #include "../hal/ioapic.h" #include -#include +#include #define COM1 0x3F8 @@ -43,7 +43,7 @@ void serial_init(){ outb(COM1, 0xAE); if(inb(COM1) != 0xAE){ - klog(LOG_WARN, __func__, "Serial controller failed test, serial output will not work"); + klog(__func__, "Serial controller failed test, serial output will not work"); return; } diff --git a/src/hal/apic.c b/src/hal/apic.c index d09af97..d6e9eeb 100644 --- a/src/hal/apic.c +++ b/src/hal/apic.c @@ -4,7 +4,7 @@ #include "timer.h" #include "ioapic.h" #include -#include +#include #include #include // GCC specific @@ -55,7 +55,7 @@ void apic_sleep(uint64_t ms){ atomic_flag lapic_timer_flag = ATOMIC_FLAG_INIT; void lapic_timer_init(int us){ - acquire_lock(&lapic_timer_flag); + acquire_spinlock(&lapic_timer_flag); /* Stop the APIC timer */ lapic_write_reg(LAPIC_TIMER_INITIAL_CNT_REG, 0); @@ -80,7 +80,7 @@ void lapic_timer_init(int us){ /* Set the inital count to the calibration */ lapic_write_reg(LAPIC_TIMER_INITIAL_CNT_REG, calibration); - free_lock(&lapic_timer_flag); + free_spinlock(&lapic_timer_flag); } diff --git a/src/hal/gdt.c b/src/hal/gdt.c index 6275900..b051484 100644 --- a/src/hal/gdt.c +++ b/src/hal/gdt.c @@ -1,5 +1,5 @@ #include "gdt.h" -#include +#include gdt_descriptor gdt[5] = {0}; diff --git a/src/hal/idt.c b/src/hal/idt.c index 6ab37fe..bc4d015 100644 --- a/src/hal/idt.c +++ b/src/hal/idt.c @@ -1,7 +1,7 @@ #include "idt.h" #include "error.h" #include "timer.h" -#include +#include #include #include idt_descriptor idt[256] = {0}; @@ -60,10 +60,10 @@ atomic_flag irq_register_lock = ATOMIC_FLAG_INIT; /* Registers an IRQ with the specified vector. */ kstatus register_irq_vector(uint8_t vector, void *base, uint8_t flags){ - acquire_lock(&irq_register_lock); + acquire_spinlock(&irq_register_lock); if(!irq_list[vector].in_use){ - free_lock(&irq_register_lock); + free_spinlock(&irq_register_lock); return KERNEL_STATUS_ERROR; } @@ -74,27 +74,27 @@ kstatus register_irq_vector(uint8_t vector, void *base, uint8_t flags){ s_load_idt(); - free_lock(&irq_register_lock); + free_spinlock(&irq_register_lock); return KERNEL_STATUS_SUCCESS; } /* Registers an IRQ and returns the vector */ int register_irq(void *base, uint8_t flags){ - acquire_lock(&irq_register_lock); + acquire_spinlock(&irq_register_lock); for(size_t i = 0; i < MAX_IRQ; i++){ if(!irq_list[i].in_use) { set_idt_descriptor(i, base, flags); irq_list[i].base = base; irq_list[i].in_use = true; - free_lock(&irq_register_lock); + free_spinlock(&irq_register_lock); s_load_idt(); return i; } } - free_lock(&irq_register_lock); + free_spinlock(&irq_register_lock); return -1; } diff --git a/src/hal/ioapic.c b/src/hal/ioapic.c index f98c569..8553ff6 100644 --- a/src/hal/ioapic.c +++ b/src/hal/ioapic.c @@ -1,6 +1,6 @@ #include -#include +#include #include #include "../sys/acpi.h" #include "error.h" @@ -53,7 +53,7 @@ void ioapic_init(void){ ioapic_t *ioapic = (ioapic_t*) find_ics(0x1); if(!ioapic){ - klog(LOG_ERROR, __func__, "IOAPIC ICS not found\n"); + klog(__func__, "IOAPIC ICS not found\n"); kkill(); } diff --git a/src/hal/smp.c b/src/hal/smp.c index 773f8f2..a1247f7 100644 --- a/src/hal/smp.c +++ b/src/hal/smp.c @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include "gdt.h" #include "smp.h" @@ -42,7 +42,7 @@ atomic_flag ap_init_lock = ATOMIC_FLAG_INIT; void ap_init(struct limine_smp_info *smp_info){ - acquire_lock(&ap_init_lock); + acquire_spinlock(&ap_init_lock); /* Load the GDT */ s_load_gdt(); @@ -71,7 +71,7 @@ void ap_init(struct limine_smp_info *smp_info){ /* Initialize APIC & APIC timer */ ap_apic_init(); - free_lock(&ap_init_lock); + free_spinlock(&ap_init_lock); for(;;); @@ -81,7 +81,7 @@ void ap_init(struct limine_smp_info *smp_info){ void smp_init(){ if(!smp_request.response){ - klog(LOG_ERROR, __func__, "Failed to get SMP request"); + klog(__func__, "Failed to get SMP request"); kkill(); } diff --git a/src/hal/timer.c b/src/hal/timer.c index 0106eb5..7c67cb3 100644 --- a/src/hal/timer.c +++ b/src/hal/timer.c @@ -3,7 +3,7 @@ #include "../hal/apic.h" #include "../drivers/pmt.h" #include "timer.h" -#include +#include #include /* Determines which timer will be used for calibration */ @@ -11,7 +11,7 @@ int calibration_timer = -1; void timer_init(void){ if(pmt_init() == -1){ - klog(LOG_INFO, __func__, "PMT Timer not found, falling back"); + klog(__func__, "PMT Timer not found, falling back"); /* Fall back to PIT */ }else{ calibration_timer = PMT; diff --git a/src/hal/tsc.c b/src/hal/tsc.c index 62b3bc9..ebbd60b 100644 --- a/src/hal/tsc.c +++ b/src/hal/tsc.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include "error.h" #include "../drivers/pmt.h" diff --git a/src/include/SFB25.h b/src/include/SFB25.h index 1617261..105f7ab 100644 --- a/src/include/SFB25.h +++ b/src/include/SFB25.h @@ -15,4 +15,6 @@ typedef char link_symbol_ptr[]; #define PAGE_ROUND_UP(size) ALIGN_UP(size, PAGE_SIZE) #define PAGE_ROUND_DOWN(size) ALIGN_DOWN(size, PAGE_SIZE) +#define SIZE_IN_PAGES(size) size/PAGE_SIZE + void *kmalloc(uint64_t size); \ No newline at end of file diff --git a/src/include/kmath.h b/src/include/kmath.h new file mode 100644 index 0000000..6c21df0 --- /dev/null +++ b/src/include/kmath.h @@ -0,0 +1 @@ +#define abs(x) (x<0) ? -x : x \ No newline at end of file diff --git a/src/include/stdio.h b/src/include/kprint.h similarity index 95% rename from src/include/stdio.h rename to src/include/kprint.h index 2f1fdf8..0c2e07b 100644 --- a/src/include/stdio.h +++ b/src/include/kprint.h @@ -8,7 +8,7 @@ enum { LOG_SUCCESS, }; -void klog(int level, const char *func, const char *msg); +void klog(const char *func, const char *msg); int kprintf(const char *format_string, ...); diff --git a/src/include/lock.h b/src/include/lock.h index 18ef1cf..1bb2aea 100644 --- a/src/include/lock.h +++ b/src/include/lock.h @@ -3,7 +3,7 @@ #ifndef SPINLOCK_H #define SPINLOCK_H -void acquire_lock(atomic_flag *lock); -void free_lock(atomic_flag *lock); +void acquire_spinlock(atomic_flag *lock); +void free_spinlock(atomic_flag *lock); #endif \ No newline at end of file diff --git a/src/lib/stdio.c b/src/lib/kprint.c similarity index 88% rename from src/lib/stdio.c rename to src/lib/kprint.c index ae0c62a..12cd964 100644 --- a/src/lib/stdio.c +++ b/src/lib/kprint.c @@ -3,7 +3,7 @@ #include #include #include -#include "../include/stdio.h" +#include "../include/kprint.h" #include "../drivers/serial.h" #include "../hal/tsc.h" @@ -22,39 +22,14 @@ extern bool serial_enabled; -void klog(int level, const char *func, const char *msg){ - switch (level) { - case LOG_INFO: - kprintf("[{d}] info: {s}: {sn}", tsc_get_timestamp(), func, msg); - if(serial_enabled){ - serial_kprintf("{k}KLOG_INFO{k}: {s}: {sn}", ANSI_COLOR_MAGENTA, ANSI_COLOR_RESET, func, msg); - } - return; - case LOG_WARN: - kprintf("[{d}] {k}warning{k}: {s}: {sn}", tsc_get_timestamp(), ANSI_COLOR_YELLOW, ANSI_COLOR_RESET, func, msg); - if(serial_enabled){ - serial_kprintf("{k}KLOG_WARN{k}: {s}: {sn}", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET, func, msg); - } - return; - case LOG_ERROR: - kprintf("[{d}] {k}error{k}: {s}: {sn}", tsc_get_timestamp(), ANSI_COLOR_RED, ANSI_COLOR_RESET, func, msg); - if(serial_enabled){ - serial_kprintf("{k}KLOG_ERROR{k}: {s}: {sn}", ANSI_COLOR_RED, ANSI_COLOR_RESET, func, msg); - } - return; - case LOG_SUCCESS: - kprintf("[{d}] {k}success{k}: {s}: {sn}", tsc_get_timestamp(), ANSI_COLOR_GREEN, ANSI_COLOR_RESET, func, msg); - if(serial_enabled){ - serial_kprintf("{k}KLOG_SUCCESS{k}: {s}: {sn}", ANSI_COLOR_GREEN, ANSI_COLOR_RESET, func, msg); - } - return; - } +void klog(const char *func, const char *msg){ + kprintf("{ksk}: {s}\n", ANSI_COLOR_MAGENTA, func, ANSI_COLOR_RESET, msg); + serial_kprintf("{ksk}: {s}\n", ANSI_COLOR_MAGENTA, func, ANSI_COLOR_RESET, msg); return; } - atomic_flag printf_lock = ATOMIC_FLAG_INIT; /* @@ -75,7 +50,7 @@ atomic_flag printf_lock = ATOMIC_FLAG_INIT; int kprintf(const char *format_string, ...){ extern struct flanterm_context *ft_ctx; - acquire_lock(&printf_lock); + acquire_spinlock(&printf_lock); int state = NORMAL; va_list a_list; va_start(a_list, format_string); @@ -138,7 +113,7 @@ int kprintf(const char *format_string, ...){ } va_end(a_list); - free_lock(&printf_lock); + free_spinlock(&printf_lock); return 0; } diff --git a/src/lib/spinlock.c b/src/lib/spinlock.c index b5919b1..8dafc4b 100644 --- a/src/lib/spinlock.c +++ b/src/lib/spinlock.c @@ -1,8 +1,8 @@ #include #include -#include +#include -void acquire_lock(atomic_flag *lock){ +void acquire_spinlock(atomic_flag *lock){ while(atomic_flag_test_and_set_explicit(lock, memory_order_acquire)){ asm volatile("nop"); } @@ -10,6 +10,6 @@ void acquire_lock(atomic_flag *lock){ atomic_thread_fence(memory_order_acquire); } -void free_lock(atomic_flag *lock){ +void free_spinlock(atomic_flag *lock){ atomic_flag_clear_explicit(lock, memory_order_release); } \ No newline at end of file diff --git a/src/lib/string.c b/src/lib/string.c index e217d53..7b15214 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -1,6 +1,6 @@ #include #include -#include +#include void *memset(void *dest, int c, uint64_t n){ uint8_t *p = (uint8_t *)dest; diff --git a/src/main.c b/src/main.c index 4042c34..5e0fdf7 100644 --- a/src/main.c +++ b/src/main.c @@ -1,8 +1,10 @@ #include #include #include +#include +#include +#include "error.h" #include "limine.h" -#include "include/stdio.h" #include "../flanterm/src/flanterm.h" #include "flanterm/src/flanterm_backends/fb.h" #include "hal/gdt.h" @@ -12,7 +14,9 @@ #include "hal/smp.h" #include "hal/tsc.h" #include "mm/pmm.h" +#include "mm/slab.h" #include "mm/vmm.h" +#include "mm/page.h" #include "mm/kmalloc.h" #include "sys/acpi.h" #include "sys/pci.h" @@ -20,6 +24,7 @@ #include "drivers/pmt.h" #include "drivers/ahci.h" #include "scheduler/sched.h" +#include "sys/rand.h" static volatile struct limine_framebuffer_request framebuffer_request = { .id = LIMINE_FRAMEBUFFER_REQUEST, @@ -77,46 +82,73 @@ void _start(void){ extern link_symbol_ptr text_start_addr, text_end_addr; - klog(LOG_INFO, "serial", "Initalizing serial controller"); serial_init(); - klog(LOG_SUCCESS, "serial", "Done!"); - - klog(LOG_INFO, "gdt", "Setting up the GDT"); + krand_init(); set_gdt(); - klog(LOG_SUCCESS, "gdt", "Done!"); - - klog(LOG_INFO, "idt", "Setting up the IDT"); set_idt(); - klog(LOG_SUCCESS, "idt", "Done!");; - klog(LOG_INFO, "acpi", "Reading ACPI tables"); + klog("acpi", "Reading ACPI tables"); acpi_init(); - klog(LOG_SUCCESS, "acpi", "Done!"); - klog(LOG_INFO, "apic", "Initalizing APIC"); + + klog("apic", "Initalizing APIC"); apic_init(); - klog(LOG_SUCCESS, "apic", "Done!"); + tsc_init(); - klog(LOG_INFO, "pmm", "Setting up the PMM"); + klog("pmm", "Setting up the PMM"); pmm_init(); - klog(LOG_SUCCESS, "pmm", "Done!"); - klog(LOG_INFO, "vmm", "Setting up the page tables"); + + klog("vmm", "Setting up the page tables"); vmm_init(); - klog(LOG_SUCCESS, "vmm", "Done!"); + init_page_array(); - kernel_heap_init(); - klog(LOG_INFO, "smp", "Starting APs"); + //struct ma_kcache *cache = ma_cache_create("bird", 1048576, 0, 0, 0); + + //uint64_t *d = ma_cache_alloc(cache, 0); + + //cache_info(cache); + + //memset(d, 0, 1048576); + + //for(;;); + + //cache_info(cache); + + _kmalloc_init(); + + int *my_int; + + for(int i = 0;i < 3000;i++){ + my_int = kmalloc(512); + *my_int = rand(); + kprintf("my int: {d} on iter: {d}\n", *my_int, i); + kstatus status = kfree(my_int); + if(status != KERNEL_STATUS_SUCCESS){ + kprintf("status: {d}\n", status); + } + + } + + + + kprintf("my int: {d}\n", *my_int); + + + + + //for(;;){} + + klog("smp", "Starting APs"); smp_init(); - klog(LOG_SUCCESS, "smp", "Done!"); - klog(LOG_INFO, "pci", "Getting le pci"); + + klog("pci", "Getting le pci"); pci_init(); - klog(LOG_SUCCESS, "pci", "Done!"); scheduler_init(); diff --git a/src/mm/kmalloc.c b/src/mm/kmalloc.c index f56e965..5bee45a 100644 --- a/src/mm/kmalloc.c +++ b/src/mm/kmalloc.c @@ -1,167 +1,51 @@ -#include -#include -#include -#include -#include -#include -#include -#include "pmm.h" -#include "vmm.h" -#include "kmalloc.h" +#include "slab.h" +#include +#include +#include +struct ma_kcache *kmalloc_caches[14] = {0}; -#define KERNEL_MAX_BLOCK 512 - -typedef struct block_t { - uint64_t addr; - uint32_t size; - bool free; -} block_t; - -block_t *base = NULL; -uint64_t *heap_addr = NULL; - -void kernel_heap_init(){ - extern struct limine_memmap_response *memmap_response; - extern uint64_t pmm_page_count; - - /* Allocate memory for the blocks*/ - base = kernel_allocate_memory(KERNEL_MAX_BLOCK * sizeof(block_t), PTE_BIT_RW | PTE_BIT_NX); - - if(!base){ - klog(LOG_ERROR, __func__, "Failed to allocate memory for kernel heap blocks"); - kkill(); - } - - memset(base, 0, KERNEL_MAX_BLOCK * sizeof(block_t)); - - /* Allocate memory for the heap */ - heap_addr = kernel_allocate_memory(KERNEL_HEAP_SIZE, PTE_BIT_RW | PTE_BIT_NX); - - if(!heap_addr){ - klog(LOG_ERROR, __func__, "Failed to allocate memory for the kernel heap"); - kkill(); - } - - base->free = true; +// Create various sizes of caches to be used by kmalloc +void _kmalloc_init(void){ + kmalloc_caches[0] = ma_cache_create("kmalloc16", 16, 0, NULL, NULL); + kmalloc_caches[1] = ma_cache_create("kmalloc32", 32, 0, NULL, NULL); + kmalloc_caches[2] = ma_cache_create("kmalloc64", 64, 0, NULL, NULL); + kmalloc_caches[3] = ma_cache_create("kmalloc128", 128, 0, NULL, NULL); + kmalloc_caches[4] = ma_cache_create("kmalloc256", 256, 0, NULL, NULL); + kmalloc_caches[5] = ma_cache_create("kmalloc512", 512, 0, NULL, NULL); + kmalloc_caches[6] = ma_cache_create("kmalloc1K", 1024, 0, NULL, NULL); + kmalloc_caches[7] = ma_cache_create("kmalloc4K", 4096, 0, NULL, NULL); + kmalloc_caches[8] = ma_cache_create("kmalloc8K", 8192, 0, NULL, NULL); + kmalloc_caches[9] = ma_cache_create("kmalloc32K", 32768, 0, NULL, NULL); + kmalloc_caches[10] = ma_cache_create("kmalloc64K", 65536, 0, NULL, NULL); + kmalloc_caches[11] = ma_cache_create("kmalloc131K", 131072, 0, NULL, NULL); + kmalloc_caches[12] = ma_cache_create("kmalloc524K", 524288, 0, NULL, NULL); + kmalloc_caches[13] = ma_cache_create("kmalloc1M", 1048576, 0, NULL, NULL); } -void *kmalloc(uint64_t size){ +size_t sizes[14] = {16, 32, 64, 128, 256, 512, 1024, 4096, 8192, 32768, 65536, 131072, 524288, 1048756}; - /* First check if there is a free block which fits the size requirement */ - for(int i = 0; i < KERNEL_MAX_BLOCK; i++){ - if(base[i].addr && base[i].free && base[i].size >= size){ - base[i].free = false; - return (void*)base[i].addr; - } - } - - int i = 0; - /* Parse the list until you find the next free block */ - while (!base[i].free && !base[i].addr){ - if(i > KERNEL_MAX_BLOCK){ - /* Over max block limit */ - return NULL; - } - - i++; - } - - /* Fill this block in */ - uint64_t addr = (uint64_t)heap_addr; - - /* Calculate address offset */ - for(int j = 0; j < i; j++){ - if(addr > ((uint64_t)heap_addr + KERNEL_HEAP_SIZE)){ - /* Out of heap memory */ - return NULL; - } - - addr += base[j].size; - } - - memset((uint64_t*)addr, 0, size); - - base[i].addr = addr; - base[i].free = false; - base[i].size = size; - - return (void*)addr; -} - -void kfree(void *addr){ - for(int i = 0; i < KERNEL_MAX_BLOCK; i++){ - if(base[i].addr == (uint64_t)addr){ - base[i].free = true; - memset((void*)base[i].addr, 0, base[i].size); - return; - } - } - - kprintf("kfree: attempted to free non-heap address!\n"); - kkill(); -} - -void *krealloc(void *addr, uint64_t size) { - if (addr == NULL) { - return kmalloc(size); - } - - if (size == 0) { - kfree(addr); +void *kmalloc(size_t size){ + if(size > 1048576){ + klog(__func__, "Attempted to allocate more than max size (1M)"); return NULL; } - // Find the block corresponding to the pointer - int i; - for (i = 0; i < KERNEL_MAX_BLOCK; i++) { - if (base[i].addr == (uint64_t)addr) { + void *addr = NULL; + for(int i = 0; i < 14; i++){ + if(sizes[i] >= size){ + addr = ma_cache_alloc(kmalloc_caches[i], 0); break; } } - - if (i == KERNEL_MAX_BLOCK) { - kprintf("krealloc: attempted to realloc non-heap address!\n"); - kkill(); + + if(addr == NULL){ + klog(__func__, "Failed to allocate heap memory!"); } - block_t *block = &base[i]; - uint64_t old_size = block->size; + return addr; - // If the current size is already sufficient, return the same pointer - if (old_size >= size) { - return addr; - } +} - // Check if this block is the last allocated block in the array - bool is_last = true; - for (int j = i + 1; j < KERNEL_MAX_BLOCK; j++) { - if (base[j].addr != 0) { - is_last = false; - break; - } - } - - // If it's the last block, check if there's enough space to expand - if (is_last) { - uint64_t current_end = block->addr + block->size; - uint64_t heap_end = (uint64_t)heap_addr + KERNEL_HEAP_SIZE; - uint64_t available = heap_end - current_end; - - if (available >= (size - old_size)) { - // Expand the block in place - block->size = size; - return addr; - } - } - - // Allocate a new block, copy data, and free the old block - void *new_ptr = kmalloc(size); - if (!new_ptr) { - return NULL; // Allocation failed - } - - memcpy(new_ptr, addr, old_size); - kfree(addr); - - return new_ptr; +kstatus kfree(void *addr){ + return ma_cache_dealloc(addr); } \ No newline at end of file diff --git a/src/mm/kmalloc.h b/src/mm/kmalloc.h index 50b3d4a..c92a68f 100644 --- a/src/mm/kmalloc.h +++ b/src/mm/kmalloc.h @@ -1,10 +1,7 @@ +#include "error.h" #include -void kernel_heap_init(); -void heap_free(uint64_t *addr); -uint64_t *heap_alloc(); +void _kmalloc_init(void); void *kmalloc(uint64_t size); -void kfree(void *addr); - -#define KERNEL_HEAP_SIZE 0x10000000 \ No newline at end of file +kstatus kfree(void *addr); diff --git a/src/mm/page.c b/src/mm/page.c new file mode 100644 index 0000000..b3724be --- /dev/null +++ b/src/mm/page.c @@ -0,0 +1,61 @@ +#include "page.h" +#include +#include "vmm.h" +#include +#include +#include +#include +#include +#include + +struct page *pages; // "virtually sparse array", it holds all the pages between the start of the first usable address to the last one. + +extern struct limine_memmap_response *memmap_response; + +extern uint64_t hhdmoffset; + +// Get the page object which is associated with the page that the address `addr` resides in +struct page *get_page(void *addr){ + void *canonical_addr = (void*)PAGE_ROUND_DOWN((uint64_t)addr); + uint64_t phys_addr = kget_phys_addr(canonical_addr); + + if(phys_addr == 0){ + return NULL; + } + + uint64_t index = phys_addr / PAGE_SIZE; + return &pages[index]; +} + +void init_page_array(){ + + struct limine_memmap_entry **entries = memmap_response->entries; + + size_t firstaddr = 0; + size_t lastaddr = 0; + + for(size_t i = 0; i < memmap_response->entry_count; i++){ + switch(entries[i]->type){ + case LIMINE_MEMMAP_USABLE: + if(firstaddr == 0){ + firstaddr = entries[i]->base; + + }else{ + lastaddr = entries[i]->base + entries[i]->length; + } + } + } + + size_t page_count = (lastaddr - firstaddr) / PAGE_SIZE; + + pages = va_alloc_contigious_pages((page_count * sizeof(struct page)) / PAGE_SIZE); + + if(pages == NULL){ + klog(__func__, "Couldn't allocate page structure"); + kkill(); + return; + } + + memset(pages, 0, (page_count * sizeof(struct page)) / PAGE_SIZE); + +} \ No newline at end of file diff --git a/src/mm/page.h b/src/mm/page.h new file mode 100644 index 0000000..f3e54a3 --- /dev/null +++ b/src/mm/page.h @@ -0,0 +1,10 @@ +#include "slab.h" + +typedef struct page { + struct ma_bufctl *bufctls; // The bufctls associated with the slab stored on this page. NULL if page isn't associated with a slab + struct ma_slab *slab; +}page; + +struct page *get_page(void *addr); + +void init_page_array(); \ No newline at end of file diff --git a/src/mm/pmm.c b/src/mm/pmm.c index 216898b..9fb7acd 100644 --- a/src/mm/pmm.c +++ b/src/mm/pmm.c @@ -1,7 +1,6 @@ #include -#include +#include #include -#include #include #include "pmm.h" #include "kmalloc.h" @@ -25,7 +24,7 @@ uint64_t *free_list = NULL; atomic_flag pmm_lock = ATOMIC_FLAG_INIT; void pmm_free(uint64_t *addr){ - acquire_lock(&pmm_lock); + acquire_spinlock(&pmm_lock); uint64_t *virt_addr = (uint64_t*)((uint64_t)addr+hhdmoffset); /* Make the given page point to the previous free page */ @@ -35,12 +34,12 @@ void pmm_free(uint64_t *addr){ free_list = virt_addr; pmm_free_page_count++; - free_lock(&pmm_lock); + free_spinlock(&pmm_lock); return; } uint64_t *pmm_alloc(){ - acquire_lock(&pmm_lock); + acquire_spinlock(&pmm_lock); if(pmm_free_page_count <= 0){ return NULL; } @@ -49,20 +48,19 @@ uint64_t *pmm_alloc(){ uint64_t *addr = (uint64_t*)((uint64_t)free_list - hhdmoffset); free_list = (uint64_t*)(*free_list); pmm_free_page_count--; - free_lock(&pmm_lock); + free_spinlock(&pmm_lock); return addr; } void pmm_init(){ if(memmap_request.response == NULL){ - klog(LOG_ERROR, __func__, "Memmap response is null"); + klog(__func__, "Memmap response is null"); kkill(); } memmap_response = memmap_request.response; - struct limine_memmap_entry **entries = memmap_response->entries; for(uint64_t i = 0; i < memmap_response->entry_count; i++){ diff --git a/src/mm/pmm.h b/src/mm/pmm.h index 06c870a..d898fdf 100644 --- a/src/mm/pmm.h +++ b/src/mm/pmm.h @@ -10,5 +10,4 @@ typedef struct free_page_t { void pmm_init(void); uint64_t *pmm_alloc(); -void pmm_free(uint64_t *addr); - +void pmm_free(uint64_t *addr); \ No newline at end of file diff --git a/src/mm/slab.c b/src/mm/slab.c new file mode 100644 index 0000000..d77aa83 --- /dev/null +++ b/src/mm/slab.c @@ -0,0 +1,437 @@ +#include +#include +#include +#include +#include "error.h" +#include "vmm.h" +#include "page.h" +#include "slab.h" +#include +#include +#include + +struct ma_kcache *caches = NULL; + +atomic_flag caches_lock = ATOMIC_FLAG_INIT; + + +enum SLAB_STATE { + FREE = 0, + PARTIAL, + USED +}; + + +// Gets free object from slab and handles stuff +uint64_t *_ma_slab_get_free_obj(struct ma_slab *slab){ + if(slab->free == NULL){ + return NULL; + } + + uint64_t *addr = slab->free->startaddr; + + if(addr == NULL){ + return NULL; + } + + if(slab->free->next != NULL){ + + slab->free = slab->free->next; + }else{ + slab->free = NULL; + } + + // Move the slab from the free to the partial list on the first time it's allocated from + if(slab->refcount == 0){ + if(slab->prev != NULL){ + slab->prev->next = slab->next; + }else{ + slab->cache->slabs_free = NULL; + } + + /* If there is a partial slab head then make it the head and do other stuff */ + if(slab->cache->slabs_partial != NULL){ + slab->cache->slabs_partial->next = slab; + slab->prev = slab->cache->slabs_partial; + } + + slab->next = NULL; + slab->cache->slabs_partial = slab; + } + + slab->refcount++; + + return addr; + +} + +kstatus _ma_alloc_slab(struct ma_kcache *kcache){ + struct ma_slab *slab_structure = (struct ma_slab*)va_alloc_contigious_pages(1); + memset(slab_structure, 0, PAGE_SIZE); + + // Put the addresses in the slab structure into the bufctls + if(kcache->objsize >= 512){ + + slab_structure->free = (struct ma_bufctl*)(va_alloc_contigious_pages(1)); // Store the bufctls off-page + memset(slab_structure->free, 0, 4096); + + uint64_t slabsize = kcache->slabsize; + void *mstart = va_alloc_contigious_pages(kcache->slabsize); + + for(size_t j = 0; j < kcache->slabsize; j++){ + get_page((void*)((uint64_t)mstart + j*PAGE_SIZE))->slab = slab_structure; + get_page((void*)((uint64_t)mstart + j*PAGE_SIZE))->bufctls = slab_structure->free; + } + + for(size_t i = 0; i < (PAGE_SIZE * slabsize)/kcache->objsize; i++){ + ((struct ma_bufctl*)((uint64_t)slab_structure->free + sizeof(struct ma_bufctl)*(i)))->startaddr = (size_t*)((uint64_t)mstart + i * kcache->objsize); + ((struct ma_bufctl*)((uint64_t)slab_structure->free + sizeof(struct ma_bufctl)*(i)))->next = (struct ma_bufctl*)((uint64_t)slab_structure->free + sizeof(struct ma_bufctl)*(i+1)); + } + + }else{ + /* In this case the objects acts as bufctl structures. Small downside: there will always be a max of 252 objects per slab, no matter the size of the object, since + * they have to have enough space to store a bufctl structure (16 bytes). + * + * Their startaddr is the same as the address of the bufctl, since the objects act as the bufctls. + */ + + slab_structure->free = va_alloc_contigious_pages(kcache->slabsize); + + get_page(slab_structure->free)->slab = slab_structure; + get_page(slab_structure->free)->bufctls = slab_structure->free; + + uint64_t size = (kcache->objsize >= sizeof(struct ma_bufctl)) ? kcache->objsize : sizeof(struct ma_bufctl); + + for(size_t i = 0; i < kcache->num; i++){ + ((struct ma_bufctl*)((uint64_t)slab_structure->free + size*i))->startaddr = (size_t*)((uint64_t)slab_structure->free + i * size); + if(i+1 < kcache->num){ + ((struct ma_bufctl*)((uint64_t)slab_structure->free + size*i))->next = (struct ma_bufctl*)((uint64_t)slab_structure->free + size*(i+1)); + }else{ + ((struct ma_bufctl*)((uint64_t)slab_structure->free + size*i))->next = NULL; + } + + } + } + + if(kcache->slabs_free == NULL){ + kcache->slabs_free = slab_structure; + }else{ + // Change head + kcache->slabs_free->next = slab_structure; + slab_structure->prev = kcache->slabs_free; + kcache->slabs_free = slab_structure; + } + + slab_structure->cache = kcache; + + return KERNEL_STATUS_SUCCESS; + +} + +void _ma_move_slab(struct ma_slab *slab, enum SLAB_STATE newstate){ + struct ma_kcache *cache = slab->cache; + struct ma_slab *sb = 0; + switch (newstate) { + case FREE: + if(cache->slabs_partial != NULL){ + sb = cache->slabs_partial; + while(sb != NULL){ + if(sb == slab){ + goto free_common; + } + sb = sb->prev; + } + } + + if(cache->slabs_used != NULL){ + sb = cache->slabs_used; + while(sb != NULL){ + if(sb == slab){ + goto free_common; + } + sb = sb->prev; + } + } + return; + case PARTIAL: + if(cache->slabs_free != NULL){ + sb = cache->slabs_free; + while(sb != NULL){ + if(sb == slab){ + goto partial_common; + } + sb = sb->prev; + } + } + + if(cache->slabs_used != NULL){ + sb = cache->slabs_used; + while(sb != NULL){ + if(sb == slab){ + goto partial_common; + } + sb = sb->prev; + } + } + return; + + case USED: + if(cache->slabs_free != NULL){ + sb = cache->slabs_free; + while(sb != NULL){ + if(sb == slab){ + goto used_common; + } + sb = sb->prev; + } + } + + if(cache->slabs_partial != NULL){ + sb = cache->slabs_partial; + while(sb != NULL){ + if(sb == slab){ + goto used_common; + } + sb = sb->prev; + } + } + return; + } + + free_common: + // Preserve the linkage + if(sb->prev != NULL){ + if(sb->next != NULL){ + sb->next->prev = sb->prev; + } + sb->prev->next = sb->next; + } + + if(cache->slabs_free != NULL){ + cache->slabs_free->next = slab; + slab->prev = cache->slabs_free; + } + + cache->slabs_free = slab; + + return; + partial_common: + if(sb->prev != NULL){ + if(sb->next != NULL){ + sb->next->prev = sb->prev; + } + sb->prev->next = sb->next; + } + + if(cache->slabs_partial != NULL){ + cache->slabs_partial->next = slab; + slab->prev = cache->slabs_partial; + } + + cache->slabs_partial = slab; + + return; + used_common: + if(sb->prev != NULL){ + if(sb->next != NULL){ + sb->next->prev = sb->prev; + } + sb->prev->next = sb->next; + } + + if(cache->slabs_used != NULL){ + cache->slabs_used->next = slab; + slab->prev = cache->slabs_used; + } + + cache->slabs_used = slab; + + return; + +} + +struct ma_kcache *ma_cache_create(char *name, size_t size, uint32_t flags, void (*constructor)(void *, size_t), void (*destructor)(void *, size_t)){ + + acquire_spinlock(&caches_lock); + + struct ma_kcache *kcache = (struct ma_kcache*)va_alloc_contigious_pages(1); + memset(kcache, 0, 4096); + + memcpy(kcache->name, name, 16); + kcache->slabsize = (size / PAGE_SIZE) + 1; + kcache->num = (4096 * kcache->slabsize - sizeof(struct ma_slab)) / ((size >= sizeof(struct ma_bufctl)) ? size : sizeof(struct ma_bufctl)); // Calculate the number of buffers in this slab + kcache->objsize = size; + memset(&kcache->lock, 0, sizeof(atomic_flag)); + + _ma_alloc_slab(kcache); + + if(caches != NULL){ + caches->next = kcache; + kcache->prev = caches; + } + + caches = kcache; + + free_spinlock(&caches_lock); + + return kcache; + +} + +void *ma_cache_alloc(struct ma_kcache *kcache, uint32_t flags){ + + acquire_spinlock(&kcache->lock); + + struct ma_slab *slab = NULL; + + if(kcache->slabs_free == NULL){ + if(kcache->slabs_partial == NULL){ + _ma_alloc_slab(kcache); + slab = kcache->slabs_free; + }else{ + slab = kcache->slabs_partial; + } + }else{ + slab = kcache->slabs_free; + } + + uint64_t *addr = _ma_slab_get_free_obj(slab); + + if(addr == NULL){ + slab->free = NULL; + + if(kcache->slabs_partial->prev != NULL){ + kcache->slabs_partial = kcache->slabs_partial->prev; + }else{ + kcache->slabs_partial = NULL; + } + + if(kcache->slabs_used != NULL){ + kcache->slabs_used->next = slab; + slab->prev = kcache->slabs_used; + kcache->slabs_used = slab; + }else{ + kcache->slabs_used = slab; + } + + _ma_alloc_slab(kcache); + addr = _ma_slab_get_free_obj(kcache->slabs_free); + } + + free_spinlock(&kcache->lock); + + return addr; + +} + +void cache_info(struct ma_kcache *cache){ + kprintf("name: {s}\n", cache->name); + kprintf("objsize: {d}\n", cache->objsize); + kprintf("num: {d}\n", cache->num); + kprintf("slabsize: {d}\n", cache->slabsize); + + int slabsfreecnt = 0; + if(cache->slabs_free == NULL){ + kprintf("slabsfree: 0\n"); + }else{ + if(cache->slabs_free->prev == NULL){ + kprintf("slabsfree: 1\n"); + }else{ + struct ma_slab *slab = cache->slabs_free; + + while(slab->prev != NULL){ + slab = slab->prev; + slabsfreecnt++; + } + + kprintf("slabsfree : {d}\n", slabsfreecnt); + } + } + + int slabspartcnt = 0; + if(cache->slabs_partial == NULL){ + kprintf("slabspartial: 0\n"); + }else{ + if(cache->slabs_partial->prev == NULL){ + kprintf("slabspartial: 1\n"); + }else{ + struct ma_slab *slab = cache->slabs_partial; + while(slab->prev != NULL){ + slab = slab->prev; + slabspartcnt++; + } + kprintf("slabspartial: {d}\n", slabspartcnt+1); + } + } + + int slabsfullcnt = 0; + if(cache->slabs_used == NULL){ + kprintf("slabsused: 0\n"); + }else{ + if(cache->slabs_used->prev == NULL){ + kprintf("slabsused: 1\n"); + }else{ + struct ma_slab *slab = cache->slabs_used; + while(slab->prev != NULL){ + slab = slab->prev; + slabsfullcnt++; + } + + + kprintf("slabsused : {d}\n", slabsfullcnt); + } + } +} + +struct ma_bufctl *addr_to_bufctl(void *object){ + struct ma_slab *slab = get_page(object)->slab; + + if(slab == NULL){ + return NULL; + } + + struct ma_bufctl *bufs = get_page(object)->bufctls; + + if(bufs == NULL){ + return NULL; + } + + for(size_t i = 0; i < slab->cache->num; i++){ + if((bufs + i)->startaddr == object){ + return (bufs + i); + } + } + + return NULL; +} + +kstatus ma_cache_dealloc(void *object){ + + struct ma_slab *slab = get_page(object)->slab; + + if(slab == NULL){ + klog(__func__, "slab == null"); + return KERNEL_STATUS_ERROR; + } + + struct ma_bufctl *buf = addr_to_bufctl(object); + + if(buf == NULL){ + klog(__func__, "bufctl not found"); + return KERNEL_STATUS_ERROR; + } + + buf->next = slab->free; + slab->free = buf; + + slab->refcount--; + + if(slab->refcount == slab->cache->num - 1){ + _ma_move_slab(slab, PARTIAL); + }else if(slab->refcount == 0){ + _ma_move_slab(slab, FREE); + } + + return KERNEL_STATUS_SUCCESS; + +} diff --git a/src/mm/slab.h b/src/mm/slab.h new file mode 100644 index 0000000..b42c558 --- /dev/null +++ b/src/mm/slab.h @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include + +#pragma once +#define KCACHE_NAME_LEN 16 + + +struct ma_bufctl { + struct ma_bufctl *next; + size_t *startaddr; +}; + +struct ma_slab { + struct ma_kcache *cache; + + struct ma_slab *next; + struct ma_slab *prev; + + uint32_t refcount; // The amount of active (not free) objects in the slabs + + struct ma_bufctl *free; // Linked list of free buffers in the slab. Is equal to NULL once there are no more free objects +}; + +/* objrefs are used to be able to quickly find out which slab and cache a object belongs to. objrefs belonging to the same slab are kept in one page, there is no mixing. */ +struct ma_objref { + struct ma_objref *next; + struct ma_objref *prev; + void *addr; // Addr of the object + struct ma_slab *slab; // The slab which the obj belongs to + struct ma_kcache *kcache; // The cache which the obj belongs to +}; + +struct ma_kcache { + struct ma_kcache *next; + struct ma_kcache *prev; + + uint32_t objsize; // Size of the object which the cache stores + uint16_t flags; // Not useful yet + uint32_t num; // Number of objects per slab + uint32_t slabsize; // How many pages does a single slab take up. Useful for objects > PAGE_SIZE + + struct ma_slab *slabs_free; + struct ma_slab *slabs_partial; + struct ma_slab *slabs_used; + + atomic_flag lock; + + char name[KCACHE_NAME_LEN]; +}; + +void *ma_cache_alloc(struct ma_kcache *kcache, uint32_t flags); +kstatus ma_cache_dealloc(void *object); +struct ma_kcache *ma_cache_create(char *name, size_t size, uint32_t flags, void (*constructor)(void *, size_t), void (*destructor)(void *, size_t)); +void cache_info(struct ma_kcache *cache); \ No newline at end of file diff --git a/src/mm/vmm.c b/src/mm/vmm.c index da6d683..9c9fc2d 100644 --- a/src/mm/vmm.c +++ b/src/mm/vmm.c @@ -1,6 +1,7 @@ #include +#include #include -#include +#include #include #include #include @@ -38,13 +39,13 @@ void vmm_init(){ struct limine_kernel_address_response *kernel_address = kernel_addr_request.response; if(!kernel_address){ - klog(LOG_ERROR, __func__, "Kernel address not recieved"); + klog(__func__, "Kernel address not recieved"); } kernel_page_map = (uint64_t*)((uint64_t)pmm_alloc() + hhdmoffset); if(!kernel_page_map){ - klog(LOG_ERROR, __func__, "Allocating block for page map failed"); + klog(__func__, "Allocating block for page map failed"); } memset(kernel_page_map, 0, PAGE_SIZE); @@ -157,7 +158,7 @@ uint64_t *get_lower_table(uint64_t *page_map, uint64_t offset){ uint64_t *ret = pmm_alloc(); if(!ret){ - klog(LOG_ERROR, __func__, "Failed to allocate page table"); + klog(__func__, "Failed to allocate page table"); kprintf("page_map: 0x{xn}", (uint64_t)page_map); kprintf("offset: 0x{xn}", offset); @@ -177,7 +178,7 @@ atomic_flag page_table_lock = ATOMIC_FLAG_INIT; void vmm_map_page(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags){ /* Probably slow, fix in future */ - acquire_lock(&page_table_lock); + acquire_spinlock(&page_table_lock); uint64_t pml4_offset = (virt_addr >> 39) & 0x1ff; uint64_t pdp_offset = (virt_addr >> 30) & 0x1ff; @@ -187,24 +188,28 @@ void vmm_map_page(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, ui uint64_t *pdp = get_lower_table(page_map, pml4_offset); if(!pdp){ - klog(LOG_ERROR, __func__, "Failed to allocate PDP"); + klog( __func__, "Failed to allocate PDP"); kkill(); } uint64_t *pd = get_lower_table(pdp, pdp_offset); if(!pd){ - klog(LOG_ERROR, __func__, "Failed to allocate PD"); + klog(__func__, "Failed to allocate PD"); kkill(); } uint64_t *pt = get_lower_table(pd, pd_offset); if(!pt){ - klog(LOG_ERROR, __func__, "Failed to allocate PT"); + klog( __func__, "Failed to allocate PT"); kkill(); } + if(pt[pt_offset] != 0){ + goto end; + } + pt[pt_offset] = phys_addr | flags; asm volatile( @@ -213,7 +218,9 @@ void vmm_map_page(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, ui : : : "rax" ); - free_lock(&page_table_lock); + end: + + free_spinlock(&page_table_lock); } @@ -227,14 +234,14 @@ void vmm_free_page(uint64_t *page_map, uint64_t virt_addr){ if(!pdp){ - klog(LOG_ERROR, __func__, "Failed to allocate PDP"); + klog(__func__, "Failed to allocate PDP"); kkill(); } uint64_t *pd = get_lower_table(pdp, pdp_offset); if(!pd){ - klog(LOG_ERROR, __func__, "Failed to allocate PD"); + klog( __func__, "Failed to allocate PD"); kkill(); } @@ -242,7 +249,7 @@ void vmm_free_page(uint64_t *page_map, uint64_t virt_addr){ uint64_t *pt = get_lower_table(pd, pd_offset); if(!pt){ - klog(LOG_ERROR, __func__, "Failed to allocate PT"); + klog(__func__, "Failed to allocate PT"); kkill(); } @@ -259,8 +266,37 @@ void vmm_free_page(uint64_t *page_map, uint64_t virt_addr){ ); } +uint64_t vmm_get_phys_addr(uint64_t *page_map, uint64_t virt_addr){ + uint64_t pml4_offset = (virt_addr >> 39) & 0x1ff; + uint64_t pdp_offset = (virt_addr >> 30) & 0x1ff; + uint64_t pd_offset = (virt_addr >> 21) & 0x1ff; + uint64_t pt_offset = (virt_addr >> 12) & 0x1ff; + + uint64_t pml4e = page_map[pml4_offset]; + if (!(pml4e & 1)) return 0; // + uint64_t *pdp = (uint64_t *)((pml4e & 0x000ffffffffff000) + hhdmoffset); + + uint64_t pdpe = pdp[pdp_offset]; + if (!(pdpe & 1)) return 0; + uint64_t *pd = (uint64_t *)((pdpe & 0x000ffffffffff000) + hhdmoffset); + + uint64_t pde = pd[pd_offset]; + if (!(pde & 1)) return 0; + uint64_t *pt = (uint64_t *)((pde & 0x000ffffffffff000) + hhdmoffset); + + uint64_t pte = pt[pt_offset]; + if (!(pte & 1)) return 0; + + return pte & 0x000ffffffffff000; +} + +uint64_t kget_phys_addr(uint64_t *virt_addr){ + return vmm_get_phys_addr(kernel_page_map, (uint64_t)virt_addr); +} + + /* Maps `size` number of free pages at the specified virtual address */ -int vmm_map_continous_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags){ +int vmm_map_contigious_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags){ for(uint64_t i = 0; i < size; i++){ vmm_map_page(page_map, virt_addr + i * PAGE_SIZE, (uint64_t)phys_addr, flags); } @@ -268,38 +304,49 @@ int vmm_map_continous_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phy return 0; } +#define VA_BASE 0x800815000 +uint64_t va_base = VA_BASE; +atomic_flag va_lock = ATOMIC_FLAG_INIT; +/* Allocates some pages from the PMM and makes them contigious in the kernels memory map. */ +void *va_alloc_contigious_pages(size_t pages){ + acquire_spinlock(&va_lock); -/* Allocates and maps memory into the kernel address space */ -void *kernel_allocate_memory(uint64_t size, uint64_t flags){ - - if(size == 0){ + if(pages == 0){ + free_spinlock(&va_lock); return NULL; } - void *ret = NULL; - for(uint64_t i = 0; i < size; i += PAGE_SIZE){ - ret = pmm_alloc(); + size_t i; + for(i = 0; i < pages; i++){ + void *t = pmm_alloc(); - - if(!ret){ + if(t == NULL){ + free_spinlock(&va_lock); return NULL; } - vmm_map_page(kernel_page_map, (uint64_t)ret + hhdmoffset, (uint64_t)ret, PTE_BIT_PRESENT | flags); + vmm_map_page(kernel_page_map, va_base+hhdmoffset+i*PAGE_SIZE, (uint64_t)t, PTE_BIT_RW | PTE_BIT_PRESENT); } + + uint64_t va_base_old = va_base; + + va_base += i*PAGE_SIZE; + + free_spinlock(&va_lock); + + return (void*)(va_base_old+hhdmoffset); - return (void*)((uint64_t)ret + hhdmoffset); } /* Maps pages from phys_addr to phys_addr+size into the kernels address space */ -void kernel_map_pages(void *phys_addr, uint64_t size, uint64_t flags){ +void kmap_pages(void *phys_addr, uint64_t size, uint64_t flags){ for(uint64_t i = 0; i < size; i++){ vmm_map_page(kernel_page_map, (uint64_t)phys_addr + hhdmoffset + (i * PAGE_SIZE), (uint64_t)phys_addr + (i * PAGE_SIZE), PTE_BIT_PRESENT | flags); } } -void kernel_unmap_pages(void *addr, uint64_t size){ +void kunmap_pages(void *addr, uint64_t size){ for(uint64_t i = 0; i < size; i++){ vmm_free_page(kernel_page_map, (uint64_t)addr + i*PAGE_SIZE); } diff --git a/src/mm/vmm.h b/src/mm/vmm.h index 2c2df7d..0480a64 100644 --- a/src/mm/vmm.h +++ b/src/mm/vmm.h @@ -11,13 +11,15 @@ void tlb_flush(void); void vmm_map_page(uint64_t *page_map, uint64_t virt_address, uint64_t phys_address, uint64_t flags); -int vmm_map_continous_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags); +int vmm_map_contigious_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags); void vmm_free_page(uint64_t *page_map, uint64_t virt_addr); void vmm_init(); void vmm_set_ctx(uint64_t *page_map); -void *kernel_allocate_memory(uint64_t size, uint64_t flags); -void kernel_map_pages(void *phys_addr, uint64_t size, uint64_t flags); -void kernel_unmap_pages(void *addr, uint64_t size); +uint64_t vmm_get_phys_addr(uint64_t *page_map, uint64_t virt_addr); +uint64_t kget_phys_addr(uint64_t *virt_addr); +void *va_alloc_contigious_pages(uint64_t size); +void kmap_pages(void *phys_addr, uint64_t size, uint64_t flags); +void kunmap_pages(void *addr, uint64_t size); typedef char link_symbol_ptr[]; diff --git a/src/scheduler/sched.c b/src/scheduler/sched.c index ab0d4fe..c32d992 100644 --- a/src/scheduler/sched.c +++ b/src/scheduler/sched.c @@ -1,4 +1,4 @@ -#include +#include #include #include #include "../hal/smp.h" @@ -61,7 +61,7 @@ kstatus add_task(uint64_t *entry){ proc *proc = alloc_process(); if (proc == NULL) { - klog(LOG_ERROR, __func__, "proc == null!"); + klog(__func__, "proc == null!"); kkill(); } diff --git a/src/sys/acpi.c b/src/sys/acpi.c index 8e30d70..f9ca211 100644 --- a/src/sys/acpi.c +++ b/src/sys/acpi.c @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include @@ -53,7 +53,7 @@ uint64_t *find_acpi_table(char *signature){ void acpi_init(void){ if(rsdp_request.response == NULL){ - klog(LOG_ERROR, "acpi", "RSDP request is NULL"); + klog("acpi", "RSDP request is NULL"); kkill(); } @@ -65,21 +65,21 @@ void acpi_init(void){ if(rsdp->revision >= 2){ rsdt = NULL; xsdt = (xsdt_t*)(rsdp->xsdt_address + hhdmoffset); - klog(LOG_INFO, "acpi", "Using XSDT header"); - kprintf("XSDT address: 0x{xn}", (uint64_t)xsdt); - kprintf("OEMID: {ccccccn}", xsdt->header.oemid[0], xsdt->header.oemid[1], xsdt->header.oemid[2], xsdt->header.oemid[3], xsdt->header.oemid[4], xsdt->header.oemid[5]); + klog("acpi", "Using XSDT header"); + kprintf("XSDT address: 0x{x}\n", (uint64_t)xsdt); + kprintf("OEMID: {cccccc}\n", xsdt->header.oemid[0], xsdt->header.oemid[1], xsdt->header.oemid[2], xsdt->header.oemid[3], xsdt->header.oemid[4], xsdt->header.oemid[5]); }else{ xsdt = NULL; rsdt = (rsdt_t*)(rsdp->rsdt_address + hhdmoffset); - klog(LOG_INFO, "acpi", "Using RSDT header"); - kprintf("RSDT address: 0x{xn}", (uint64_t)rsdt); - kprintf("OEMID: {ccccccn}", rsdt->header.oemid[0], rsdt->header.oemid[1], rsdt->header.oemid[2], rsdt->header.oemid[3], rsdt->header.oemid[4], rsdt->header.oemid[5]); + klog("acpi", "Using RSDT header"); + kprintf("RSDT address: 0x{x}\n", (uint64_t)rsdt); + kprintf("OEMID: {cccccc}\n", rsdt->header.oemid[0], rsdt->header.oemid[1], rsdt->header.oemid[2], rsdt->header.oemid[3], rsdt->header.oemid[4], rsdt->header.oemid[5]); } madt = (madt_t*)find_acpi_table("APIC"); if(!madt){ - klog(LOG_ERROR, __func__, "MADT table not found"); + klog(__func__, "MADT table not found"); kkill(); } } diff --git a/src/sys/pci.c b/src/sys/pci.c index 7b0486e..508abd9 100644 --- a/src/sys/pci.c +++ b/src/sys/pci.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include "acpi.h" @@ -34,13 +34,13 @@ extern uint64_t *kernel_page_map; atomic_flag pci_array_lock = ATOMIC_FLAG_INIT; void pci_add_device(pci_structure structure){ - acquire_lock(&pci_array_lock); + acquire_spinlock(&pci_array_lock); int i = 0; /* Find first unused space */ while(pci_array[i].func_addr[0] != 0){ if(i >= PCI_DEVICE_BUS){ - klog(LOG_ERROR, __func__, "No more space in the PCI array!"); + klog(__func__, "No more space in the PCI array!"); kkill(); } i++; @@ -56,24 +56,24 @@ void pci_add_device(pci_structure structure){ } } - free_lock(&pci_array_lock); + free_spinlock(&pci_array_lock); return; } pci_structure *pci_get_device(pci_structure structure){ - acquire_lock(&pci_array_lock); + acquire_spinlock(&pci_array_lock); pci_structure ret = {0}; for(int i = 0; i < PCI_DEVICE_BUS; i++){ if( structure.segment == pci_array[i].segment && structure.bus == pci_array[i].bus && structure.device == pci_array[i].device){ + free_spinlock(&pci_array_lock); return &pci_array[i]; - free_lock(&pci_array_lock); } } - free_lock(&pci_array_lock); + free_spinlock(&pci_array_lock); return NULL; } @@ -170,7 +170,7 @@ void pci_init(){ mcfg = (mcfg_t*)find_acpi_table("MCFG"); if(!mcfg){ - klog(LOG_ERROR, __func__, "Failed to find MCFG table"); + klog(__func__, "Failed to find MCFG table"); kprintf("pci: device: PCIe not supported! Halting"); kkill(); } @@ -180,13 +180,13 @@ void pci_init(){ parse_conf_space(); /* Map the config space */ - kernel_map_pages((uint64_t*)(config_space_base_addr - hhdmoffset), (PCIE_CONF_SPACE_WIDTH * end_pci_num) / PAGE_SIZE, PTE_BIT_RW | PTE_BIT_NX); + kmap_pages((uint64_t*)(config_space_base_addr - hhdmoffset), (PCIE_CONF_SPACE_WIDTH * end_pci_num) / PAGE_SIZE, PTE_BIT_RW | PTE_BIT_NX); /* Stores enough for an entire configuration space */ pci_array = kmalloc((256 * 32) * sizeof(pci_structure)); if(!pci_array){ - klog(LOG_ERROR, __func__, "Failed to allocate memory for PCI structures!"); + klog(__func__, "Failed to allocate memory for PCI structures!"); kkill(); } diff --git a/src/sys/rand.c b/src/sys/rand.c new file mode 100644 index 0000000..1973c6a --- /dev/null +++ b/src/sys/rand.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +uint32_t next = 0; + +uint16_t rand(void){ + next = next * 1103515245 + 12345; + return (size_t) (next / 65536) % 32768; +} + +void srand(uint32_t seed){ + next = seed; +} + +void krand_init(){ + uint32_t unused, ecx; + __get_cpuid(0x01, &unused, &unused, &ecx, &unused); + + ecx = (ecx & 2) >> 1; + + if(ecx == 1){ + /* RDRAND supported */ + klog(__func__, "using RDRAND for random number seed\n"); + uint32_t rand; + asm volatile ( + "rdrand %0" + : "=r" (rand) + ); + srand(rand); + }else{ + next = 0; + } + + +} diff --git a/src/sys/rand.h b/src/sys/rand.h new file mode 100644 index 0000000..49726da --- /dev/null +++ b/src/sys/rand.h @@ -0,0 +1,3 @@ +#include +void krand_init(); +size_t rand(void); \ No newline at end of file diff --git a/src/uacpi_kernel_api.c b/src/uacpi_kernel_api.c index 7af0834..9fde5ee 100644 --- a/src/uacpi_kernel_api.c +++ b/src/uacpi_kernel_api.c @@ -3,7 +3,7 @@ #include "mm/vmm.h" #include "mm/kmalloc.h" #include -#include +#include #include #include