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.
This commit is contained in:
RaphProductions 2025-05-19 17:56:29 +02:00
parent 16246cc167
commit dcea7360d2
18 changed files with 205 additions and 34 deletions

View file

@ -5,4 +5,12 @@ This is a carefully rewritten version of Soaplin, that should be held with super
## Features ## Features
* Support for compiling the kernel on armv8, RISC-V, and LoongArch64 (even though the kernel doesn't do anything on these architectures) * 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 * Free list PMM with lazy loading
* x86_64 paging * x86_64 paging
## To do
* ACPI & MADT
* IOAPIC / LAPIC
* SMP
* Multithreaded scheduler
* VFS
* Tar file system

43
kernel/src/acpi/acpi.c Normal file
View file

@ -0,0 +1,43 @@
/*
* The Soaplin Kernel
* Copyright (C) 2025 The SILD Project
*
* acpi.c - ACPI table lookup
*/
#include <stdbool.h>
#include <acpi/acpi.h>
#include <arch/cpu.h>
#include <boot/limine.h>
#include <lib/log.h>
#include <mm/memop.h>
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");
}

28
kernel/src/acpi/acpi.h Normal file
View file

@ -0,0 +1,28 @@
/*
* The Soaplin Kernel
* Copyright (C) 2025 The SILD Project
*
* acpi.h - ACPI definitions
*/
#pragma once
#include <stdint.h>
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();

View file

@ -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) {
} }

View file

@ -16,7 +16,7 @@ void arch_init_stage1();
void cpu_load_pm(pagemap_t pm); void cpu_load_pm(pagemap_t pm);
// Invalidate a page table entry // 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. // Disable interrupts and halt the system.
void hcf(); void hcf();

View file

@ -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) {
} }

View file

@ -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) {
} }

View file

@ -25,23 +25,7 @@ void cpu_load_pm(pagemap_t pm) {
__asm__ volatile("mov %0, %%cr3" : : "r"(physical((uint64_t)pm)) : "memory"); __asm__ volatile("mov %0, %%cr3" : : "r"(physical((uint64_t)pm)) : "memory");
} }
static uint64_t read_cr3(void) void cpu_invalidate_page(uint64_t vaddr) {
{
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;
}
asm volatile ( "invlpg (%0)" : : "b"(vaddr) : "memory" ); asm volatile ( "invlpg (%0)" : : "b"(vaddr) : "memory" );
} }

View file

@ -54,7 +54,7 @@ void gdt_init() {
gdt_reload_segments(); gdt_reload_segments();
debug("arch: GDT & TSS initialized.\n"); trace("arch: GDT & TSS initialized.\n");
} }
#endif #endif

View file

@ -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("r11: %p, r12: %p, r13: %p\n", regs->r11, regs->r12, regs->r13);
fatal("r14: %p, r15: %p\n", regs->r14, regs->r15); 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("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); __panic_display_bt(regs);
hcf(); hcf();
} }
@ -103,7 +103,7 @@ void idt_init() {
__asm__ volatile ("lidt %0" : : "m"(idtr)); __asm__ volatile ("lidt %0" : : "m"(idtr));
__asm__ volatile ("sti"); __asm__ volatile ("sti");
debug("arch: IDT loaded successfully\n"); trace("arch: IDT loaded successfully\n");
} }
#endif #endif

View file

@ -63,6 +63,12 @@ static volatile struct limine_paging_mode_request pgmode_req = {
.revision = 0 .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"))) __attribute__((used, section(".limine_requests_start")))
static volatile LIMINE_REQUESTS_START_MARKER; 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_hhdm_offset() { return hhdm_req.response->offset; }
uint64_t limine_get_kernel_vaddr() { return kaddr_req.response->virtual_base; } 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_paddr() { return kaddr_req.response->physical_base; }
uint64_t limine_get_kernel_ehdr_addr() { return (uint64_t)execfile_req.response->executable_file->address; } 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(); }

View file

@ -34,4 +34,5 @@ struct limine_memmap_response *limine_get_memmap();
uint64_t limine_get_hhdm_offset(); uint64_t limine_get_hhdm_offset();
uint64_t limine_get_kernel_vaddr(); uint64_t limine_get_kernel_vaddr();
uint64_t limine_get_kernel_paddr(); uint64_t limine_get_kernel_paddr();
uint64_t limine_get_kernel_ehdr_addr(); uint64_t limine_get_kernel_ehdr_addr();
uint64_t limine_get_rsdp();

View file

@ -9,6 +9,7 @@
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <acpi/acpi.h>
#include <arch/cpu.h> #include <arch/cpu.h>
#include <boot/limine.h> #include <boot/limine.h>
#include <config.h> #include <config.h>
@ -19,6 +20,7 @@
#include <mm/memop.h> #include <mm/memop.h>
#include <mm/pmm.h> #include <mm/pmm.h>
#include "mm/paging.h" #include "mm/paging.h"
#include "mm/vma.h"
void kmain(void) { void kmain(void) {
tty_init(); tty_init();
@ -26,7 +28,7 @@ void kmain(void) {
log_register_output(sklogoutput_tty); log_register_output(sklogoutput_tty);
limine_bootinfo_t *bi = limine_get_bootinfo(); 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); bi->arch, bi->bl_name, bi->bl_ver, bi->fw_type);
arch_init_stage1(); arch_init_stage1();
@ -34,7 +36,8 @@ void kmain(void) {
pmm_init(); pmm_init();
pg_init(); pg_init();
acpi_init();
// We're done, just hang... // We're done, just hang... for now.
hcf(); hcf();
} }

View file

@ -109,6 +109,24 @@ static uint64_t *__pg_get_next_lvl(uint64_t *level, uint64_t entry,
return NULL; 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) { void pg_map(pagemap_t pm, uint64_t vaddr, uint64_t paddr, uint64_t flags) {
if (!pm) return; if (!pm) return;
@ -156,7 +174,7 @@ void pg_unmap(pagemap_t pm, uint64_t vaddr) {
if (!pml1) return; if (!pml1) return;
pml1[pml1_entry] = 0; 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) { void pg_protect(pagemap_t pm, uint64_t vaddr, uint64_t flags) {

View file

@ -10,7 +10,7 @@
// Page flags // Page flags
#include <stdint.h> #include <stdint.h>
#define PTE_ADDR_MASK 0x000ffffffffff000 #define PTE_ADDR_MASK 0x000ffffffffff000ull
#define PTE_GET_ADDR(VALUE) ((VALUE) & PTE_ADDR_MASK) #define PTE_GET_ADDR(VALUE) ((VALUE) & PTE_ADDR_MASK)
#define PTE_GET_FLAGS(VALUE) ((VALUE) & ~PTE_ADDR_MASK) #define PTE_GET_FLAGS(VALUE) ((VALUE) & ~PTE_ADDR_MASK)
@ -21,11 +21,17 @@
typedef uint64_t *pagemap_t; typedef uint64_t *pagemap_t;
extern pagemap_t pg_kernel_pm;
extern pagemap_t pg_current_pm;
void pg_init(); void pg_init();
pagemap_t pg_alloc_pm(); pagemap_t pg_alloc_pm();
void pg_free_pm(pagemap_t pm); void pg_free_pm(pagemap_t pm);
void pg_load_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(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, void pg_map_user(pagemap_t pm, uint64_t vaddr, uint64_t paddr,
uint64_t flags); uint64_t flags);

View file

@ -81,7 +81,7 @@ void pmm_init() {
if (entry->type == LIMINE_MEMMAP_USABLE || if (entry->type == LIMINE_MEMMAP_USABLE ||
entry->type == LIMINE_MEMMAP_BOOTLOADER_RECLAIMABLE) 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); uint64_t newlen = ALIGN_DOWN(entry->length, PMM_PAGE_SIZE);

View file

@ -8,6 +8,8 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "lib/log.h"
#include "mm/memop.h"
#include <mm/paging.h> #include <mm/paging.h>
#include "mm/vma.h" #include "mm/vma.h"
#include "mm/pmm.h" #include "mm/pmm.h"
@ -28,6 +30,74 @@ vma_ctx_t *vma_alloc_ctx(pagemap_t pm, uint64_t start) {
return ctx; 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) { void vma_free_ctx(vma_ctx_t *ctx) {
if (!ctx || if (!ctx ||
!ctx->pm || !ctx->pm ||
@ -37,7 +107,7 @@ void vma_free_ctx(vma_ctx_t *ctx) {
vma_region_t *reg = ctx->root; vma_region_t *reg = ctx->root;
while (reg) { while (reg) {
vma_region_t *next = reg->next; vma_region_t *next = reg->next;
pmm_free_page((void*)physical((uint64_t)reg)); __vma_free_region(ctx, reg);
reg = next; reg = next;
} }

View file

@ -8,6 +8,7 @@
#pragma once #pragma once
#include "mm/paging.h" #include "mm/paging.h"
#include <stddef.h>
typedef struct __vma_region { typedef struct __vma_region {
uint64_t start; uint64_t start;
@ -25,4 +26,6 @@ typedef struct {
} vma_ctx_t; } vma_ctx_t;
vma_ctx_t *vma_alloc_ctx(pagemap_t pm, uint64_t start); 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); void vma_free_ctx (vma_ctx_t *ctx);