From dcea7360d2be2f926db937297e379b12726c8468 Mon Sep 17 00:00:00 2001 From: RaphProductions <81994075+RaphProductions@users.noreply.github.com> Date: Mon, 19 May 2025 17:56:29 +0200 Subject: [PATCH] vma: Implement VMA. + acpi: Start implementation of table lookup + cpu: Remove useless argument to "cpu_invalidate_page" + cpu (x86_64): Removed "read_cr3" + arch/x86_64: Replace debug with trace for GDT & IDT initialization. --- README.md | 10 ++++- kernel/src/acpi/acpi.c | 43 +++++++++++++++++++++ kernel/src/acpi/acpi.h | 28 ++++++++++++++ kernel/src/arch/aarch64/cpu.c | 2 +- kernel/src/arch/cpu.h | 2 +- kernel/src/arch/la64/cpu.c | 2 +- kernel/src/arch/riscv/cpu.c | 2 +- kernel/src/arch/x86_64/cpu.c | 18 +-------- kernel/src/arch/x86_64/gdt.c | 2 +- kernel/src/arch/x86_64/idt.c | 4 +- kernel/src/boot/limine.c | 9 ++++- kernel/src/boot/limine.h | 3 +- kernel/src/main.c | 7 +++- kernel/src/mm/paging.c | 20 +++++++++- kernel/src/mm/paging.h | 10 ++++- kernel/src/mm/pmm.c | 2 +- kernel/src/mm/vma.c | 72 ++++++++++++++++++++++++++++++++++- kernel/src/mm/vma.h | 3 ++ 18 files changed, 205 insertions(+), 34 deletions(-) create mode 100644 kernel/src/acpi/acpi.c create mode 100644 kernel/src/acpi/acpi.h diff --git a/README.md b/README.md index a21ce3d..24de99e 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,12 @@ This is a carefully rewritten version of Soaplin, that should be held with super ## Features * Support for compiling the kernel on armv8, RISC-V, and LoongArch64 (even though the kernel doesn't do anything on these architectures) * Free list PMM with lazy loading -* x86_64 paging \ No newline at end of file +* x86_64 paging + +## To do +* ACPI & MADT +* IOAPIC / LAPIC +* SMP +* Multithreaded scheduler +* VFS +* Tar file system \ No newline at end of file diff --git a/kernel/src/acpi/acpi.c b/kernel/src/acpi/acpi.c new file mode 100644 index 0000000..81e1efb --- /dev/null +++ b/kernel/src/acpi/acpi.c @@ -0,0 +1,43 @@ +/* + * The Soaplin Kernel + * Copyright (C) 2025 The SILD Project + * + * acpi.c - ACPI table lookup + */ + +#include + +#include +#include +#include +#include +#include + +static bool __acpi_use_xsdt; +static uint64_t __acpi_rsdt_addr; + +void acpi_init() { + acpi_rsdp_t *rsdp = (acpi_rsdp_t*)limine_get_rsdp(); + if (memcmp(rsdp->sign, "RSD PTR ", 8)) + { + fatal("acpi: ACPI RSDP is corrupt\n"); + hcf(); + } + + if (rsdp->rev >= 2) + { + trace("acpi: ACPI v2.0 or later detected: Using XSDT.\n"); + + acpi_xsdp_t *xsdp = (acpi_xsdp_t *)rsdp; + __acpi_use_xsdt = 1; + __acpi_rsdt_addr = xsdp->xsdt_addr; + + goto initialized; + } + + __acpi_use_xsdt = 0; + __acpi_rsdt_addr = rsdp->rsdt_addr; // Do not use a pointer, to shut up the compiler. + +initialized: + trace("acpi: Initialized!\n"); +} \ No newline at end of file diff --git a/kernel/src/acpi/acpi.h b/kernel/src/acpi/acpi.h new file mode 100644 index 0000000..5a929da --- /dev/null +++ b/kernel/src/acpi/acpi.h @@ -0,0 +1,28 @@ +/* + * The Soaplin Kernel + * Copyright (C) 2025 The SILD Project + * + * acpi.h - ACPI definitions + */ + +#pragma once + +#include + +typedef struct { + char sign[8]; + char chksum; + char oemid[6]; + char rev; + uint32_t rsdt_addr; +} acpi_rsdp_t; + +typedef struct { + acpi_rsdp_t base; + uint32_t len; + uint64_t xsdt_addr; + char chksumex; +} acpi_xsdp_t; + +void acpi_init(); +void acpi_init(); \ No newline at end of file diff --git a/kernel/src/arch/aarch64/cpu.c b/kernel/src/arch/aarch64/cpu.c index f2d3feb..0e0f378 100644 --- a/kernel/src/arch/aarch64/cpu.c +++ b/kernel/src/arch/aarch64/cpu.c @@ -16,7 +16,7 @@ void cpu_load_pm(pagemap_t pm) { } -void cpu_invalidate_page(pagemap_t pm, uint64_t vaddr) { +void cpu_invalidate_page(uint64_t vaddr) { } diff --git a/kernel/src/arch/cpu.h b/kernel/src/arch/cpu.h index 87d4114..97b5307 100644 --- a/kernel/src/arch/cpu.h +++ b/kernel/src/arch/cpu.h @@ -16,7 +16,7 @@ void arch_init_stage1(); void cpu_load_pm(pagemap_t pm); // Invalidate a page table entry -void cpu_invalidate_page(pagemap_t pm, uint64_t vaddr); +void cpu_invalidate_page(uint64_t vaddr); // Disable interrupts and halt the system. void hcf(); \ No newline at end of file diff --git a/kernel/src/arch/la64/cpu.c b/kernel/src/arch/la64/cpu.c index 5c41bca..8b2fd40 100644 --- a/kernel/src/arch/la64/cpu.c +++ b/kernel/src/arch/la64/cpu.c @@ -16,7 +16,7 @@ void cpu_load_pm(pagemap_t pm) { } -void cpu_invalidate_page(pagemap_t pm, uint64_t vaddr) { +void cpu_invalidate_page(uint64_t vaddr) { } diff --git a/kernel/src/arch/riscv/cpu.c b/kernel/src/arch/riscv/cpu.c index 3dcdf96..e671ac9 100644 --- a/kernel/src/arch/riscv/cpu.c +++ b/kernel/src/arch/riscv/cpu.c @@ -16,7 +16,7 @@ void cpu_load_pm(pagemap_t pm) { } -void cpu_invalidate_page(pagemap_t pm, uint64_t vaddr) { +void cpu_invalidate_page(uint64_t vaddr) { } diff --git a/kernel/src/arch/x86_64/cpu.c b/kernel/src/arch/x86_64/cpu.c index 1b4378a..858beca 100644 --- a/kernel/src/arch/x86_64/cpu.c +++ b/kernel/src/arch/x86_64/cpu.c @@ -25,23 +25,7 @@ void cpu_load_pm(pagemap_t pm) { __asm__ volatile("mov %0, %%cr3" : : "r"(physical((uint64_t)pm)) : "memory"); } -static uint64_t read_cr3(void) -{ - unsigned long val; - asm volatile ( "mov %%cr3, %0" : "=r"(val) ); - return val; -} - -void cpu_invalidate_page(pagemap_t pm, uint64_t vaddr) { - uint64_t cr3 = read_cr3(); - if (physical((uint64_t)pm) != cr3) - { - // load the provided PM in cr3, invalidate the page and return into the previous cr3. - cpu_load_pm(pm); - asm volatile ( "invlpg (%0)" : : "b"(vaddr) : "memory" ); - cpu_load_pm((pagemap_t)cr3); - return; - } +void cpu_invalidate_page(uint64_t vaddr) { asm volatile ( "invlpg (%0)" : : "b"(vaddr) : "memory" ); } diff --git a/kernel/src/arch/x86_64/gdt.c b/kernel/src/arch/x86_64/gdt.c index f916dfe..97b04a4 100644 --- a/kernel/src/arch/x86_64/gdt.c +++ b/kernel/src/arch/x86_64/gdt.c @@ -54,7 +54,7 @@ void gdt_init() { gdt_reload_segments(); - debug("arch: GDT & TSS initialized.\n"); + trace("arch: GDT & TSS initialized.\n"); } #endif \ No newline at end of file diff --git a/kernel/src/arch/x86_64/idt.c b/kernel/src/arch/x86_64/idt.c index 664b958..520c0b3 100644 --- a/kernel/src/arch/x86_64/idt.c +++ b/kernel/src/arch/x86_64/idt.c @@ -70,7 +70,7 @@ void idt_interrupt_handler(registers_t *regs) { fatal("r11: %p, r12: %p, r13: %p\n", regs->r11, regs->r12, regs->r13); fatal("r14: %p, r15: %p\n", regs->r14, regs->r15); fatal("rip: %p, cs: %p, ss: %p\n", regs->rip, regs->cs, regs->ss); - fatal("rflags: %p, err: %p, rsp: %p\n", regs->rflags, regs->err_code, regs->rsp); + fatal("rflags: %p, err: %d, rsp: %p\n", regs->rflags, regs->err_code, regs->rsp); __panic_display_bt(regs); hcf(); } @@ -103,7 +103,7 @@ void idt_init() { __asm__ volatile ("lidt %0" : : "m"(idtr)); __asm__ volatile ("sti"); - debug("arch: IDT loaded successfully\n"); + trace("arch: IDT loaded successfully\n"); } #endif \ No newline at end of file diff --git a/kernel/src/boot/limine.c b/kernel/src/boot/limine.c index a41457b..d936ffd 100644 --- a/kernel/src/boot/limine.c +++ b/kernel/src/boot/limine.c @@ -63,6 +63,12 @@ static volatile struct limine_paging_mode_request pgmode_req = { .revision = 0 }; +__attribute__((used, section(".limine_requests"))) +static volatile struct limine_rsdp_request rsdp_req = { + .id = LIMINE_RSDP_REQUEST, + .revision = 0 +}; + __attribute__((used, section(".limine_requests_start"))) static volatile LIMINE_REQUESTS_START_MARKER; @@ -109,4 +115,5 @@ limine_bootinfo_t *limine_get_bootinfo() { uint64_t limine_get_hhdm_offset() { return hhdm_req.response->offset; } uint64_t limine_get_kernel_vaddr() { return kaddr_req.response->virtual_base; } uint64_t limine_get_kernel_paddr() { return kaddr_req.response->physical_base; } -uint64_t limine_get_kernel_ehdr_addr() { return (uint64_t)execfile_req.response->executable_file->address; } \ No newline at end of file +uint64_t limine_get_kernel_ehdr_addr() { return (uint64_t)execfile_req.response->executable_file->address; } +uint64_t limine_get_rsdp() { return rsdp_req.response->address + limine_get_hhdm_offset(); } \ No newline at end of file diff --git a/kernel/src/boot/limine.h b/kernel/src/boot/limine.h index d65ed79..f264a30 100644 --- a/kernel/src/boot/limine.h +++ b/kernel/src/boot/limine.h @@ -34,4 +34,5 @@ struct limine_memmap_response *limine_get_memmap(); uint64_t limine_get_hhdm_offset(); uint64_t limine_get_kernel_vaddr(); uint64_t limine_get_kernel_paddr(); -uint64_t limine_get_kernel_ehdr_addr(); \ No newline at end of file +uint64_t limine_get_kernel_ehdr_addr(); +uint64_t limine_get_rsdp(); \ No newline at end of file diff --git a/kernel/src/main.c b/kernel/src/main.c index 6dfce8c..daa02d2 100644 --- a/kernel/src/main.c +++ b/kernel/src/main.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include "mm/paging.h" +#include "mm/vma.h" void kmain(void) { tty_init(); @@ -26,7 +28,7 @@ void kmain(void) { log_register_output(sklogoutput_tty); limine_bootinfo_t *bi = limine_get_bootinfo(); - trace("%s %s-%s (booted using %s %s, with firmware type %d)\n", KERNEL_NAME, KERNEL_VER, + info("%s %s-%s (booted using %s %s, with firmware type %d)\n", KERNEL_NAME, KERNEL_VER, bi->arch, bi->bl_name, bi->bl_ver, bi->fw_type); arch_init_stage1(); @@ -34,7 +36,8 @@ void kmain(void) { pmm_init(); pg_init(); + acpi_init(); - // We're done, just hang... + // We're done, just hang... for now. hcf(); } diff --git a/kernel/src/mm/paging.c b/kernel/src/mm/paging.c index 8c7f181..6ef555d 100644 --- a/kernel/src/mm/paging.c +++ b/kernel/src/mm/paging.c @@ -109,6 +109,24 @@ static uint64_t *__pg_get_next_lvl(uint64_t *level, uint64_t entry, return NULL; } +uint64_t pg_physical(pagemap_t pm, uint64_t vaddr) { + if (!pm) return 0; + + uint64_t pml4_entry = (vaddr >> 39) & 0x1ff; + uint64_t pml3_entry = (vaddr >> 30) & 0x1ff; + uint64_t pml2_entry = (vaddr >> 21) & 0x1ff; + uint64_t pml1_entry = (vaddr >> 12) & 0x1ff; + + uint64_t *pml3 = __pg_get_next_lvl(pm , pml4_entry, 0, false); + if (!pml3) return 0; + uint64_t *pml2 = __pg_get_next_lvl(pml3, pml3_entry, 0, false); + if (!pml2) return 0; + uint64_t *pml1 = __pg_get_next_lvl(pml2, pml2_entry, 0, false); + if (!pml1) return 0; + + return pml1[pml1_entry] & PTE_ADDR_MASK; +} + void pg_map(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) { if (!pm) return; @@ -156,7 +174,7 @@ void pg_unmap(pagemap_t pm, uint64_t vaddr) { if (!pml1) return; pml1[pml1_entry] = 0; - cpu_invalidate_page(pm, vaddr); + cpu_invalidate_page(vaddr); } void pg_protect(pagemap_t pm, uint64_t vaddr, uint64_t flags) { diff --git a/kernel/src/mm/paging.h b/kernel/src/mm/paging.h index 2426208..c41eec2 100644 --- a/kernel/src/mm/paging.h +++ b/kernel/src/mm/paging.h @@ -10,7 +10,7 @@ // Page flags #include -#define PTE_ADDR_MASK 0x000ffffffffff000 +#define PTE_ADDR_MASK 0x000ffffffffff000ull #define PTE_GET_ADDR(VALUE) ((VALUE) & PTE_ADDR_MASK) #define PTE_GET_FLAGS(VALUE) ((VALUE) & ~PTE_ADDR_MASK) @@ -21,11 +21,17 @@ typedef uint64_t *pagemap_t; +extern pagemap_t pg_kernel_pm; +extern pagemap_t pg_current_pm; + + void pg_init(); + pagemap_t pg_alloc_pm(); void pg_free_pm(pagemap_t pm); - void pg_load_pm(pagemap_t pm); + +uint64_t pg_physical(pagemap_t pm, uint64_t vaddr); void pg_map(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags); void pg_map_user(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags); diff --git a/kernel/src/mm/pmm.c b/kernel/src/mm/pmm.c index 1959403..7cac5c4 100644 --- a/kernel/src/mm/pmm.c +++ b/kernel/src/mm/pmm.c @@ -81,7 +81,7 @@ void pmm_init() { if (entry->type == LIMINE_MEMMAP_USABLE || entry->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE) { - trace("pmm: found a usable memory block: %p-%p\n", entry->base, entry->base + entry->length); + trace("pmm: Found an usable memory block: %p-%p\n", entry->base, entry->base + entry->length); uint64_t newlen = ALIGN_DOWN(entry->length, PMM_PAGE_SIZE); diff --git a/kernel/src/mm/vma.c b/kernel/src/mm/vma.c index af7638b..d22caf3 100644 --- a/kernel/src/mm/vma.c +++ b/kernel/src/mm/vma.c @@ -8,6 +8,8 @@ #include #include +#include "lib/log.h" +#include "mm/memop.h" #include #include "mm/vma.h" #include "mm/pmm.h" @@ -28,6 +30,74 @@ vma_ctx_t *vma_alloc_ctx(pagemap_t pm, uint64_t start) { return ctx; } +void *vma_alloc(vma_ctx_t *ctx, size_t length, uint64_t flags) { + if (!ctx || !ctx->pm || !ctx->root) + return NULL; + + vma_region_t *current = ctx->root; + while (current) { + if (current->next == NULL || current->start + (current->length * PMM_PAGE_SIZE) < current->next->start) + { + vma_region_t *reg = (vma_region_t*)higher_half((uint64_t)pmm_alloc_page()); + memset((void*)reg, 0, sizeof(vma_region_t)); + reg->start = current->start + (current->length * PMM_PAGE_SIZE); + reg->length = length; + reg->pflags = flags; + reg->next = current->next; + current->next = reg; + + // Now, allocate the memory + for (uint64_t i = 0; i < length; i++) { + uint64_t physical = (uint64_t)pmm_alloc_page(); + pg_map(ctx->pm, reg->start + (i * PMM_PAGE_SIZE), physical, flags); + } + + return (void*)reg->start; + } + + current = current->next; + } + return NULL; +} + +static void __vma_free_region(vma_ctx_t *ctx, vma_region_t *target) { + for (uint64_t i = 0; i < target->length; i++) { + uint64_t vaddr = target->start + (i * PMM_PAGE_SIZE); + uint64_t paddr = pg_physical(ctx->pm, vaddr); + pg_unmap(ctx->pm, vaddr); + pmm_free_page((void*)paddr); + } + + pmm_free_page((void*)physical((uint64_t)target)); +} + +void vma_free(vma_ctx_t *ctx, void *addr) { + if (!ctx || !ctx->pm || !ctx->root || !addr) + return; + + vma_region_t *last = NULL; + vma_region_t *target = ctx->root; + + while (target) { + if (target->start == (uint64_t)addr) + break; + + last = target; + target = target->next; + } + + if (!target) + return; + + if (last) + last->next = target->next; + else + ctx->root = target->next; + + // Unallocate the memory + __vma_free_region(ctx, target); +} + void vma_free_ctx(vma_ctx_t *ctx) { if (!ctx || !ctx->pm || @@ -37,7 +107,7 @@ void vma_free_ctx(vma_ctx_t *ctx) { vma_region_t *reg = ctx->root; while (reg) { vma_region_t *next = reg->next; - pmm_free_page((void*)physical((uint64_t)reg)); + __vma_free_region(ctx, reg); reg = next; } diff --git a/kernel/src/mm/vma.h b/kernel/src/mm/vma.h index f3174f9..3b6e123 100644 --- a/kernel/src/mm/vma.h +++ b/kernel/src/mm/vma.h @@ -8,6 +8,7 @@ #pragma once #include "mm/paging.h" +#include typedef struct __vma_region { uint64_t start; @@ -25,4 +26,6 @@ typedef struct { } vma_ctx_t; vma_ctx_t *vma_alloc_ctx(pagemap_t pm, uint64_t start); +void *vma_alloc(vma_ctx_t *ctx, size_t length, uint64_t flags); +void vma_free(vma_ctx_t *ctx, void *addr); void vma_free_ctx (vma_ctx_t *ctx); \ No newline at end of file