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:
parent
16246cc167
commit
dcea7360d2
18 changed files with 205 additions and 34 deletions
43
kernel/src/acpi/acpi.c
Normal file
43
kernel/src/acpi/acpi.c
Normal 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
28
kernel/src/acpi/acpi.h
Normal 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();
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ void gdt_init() {
|
|||
|
||||
gdt_reload_segments();
|
||||
|
||||
debug("arch: GDT & TSS initialized.\n");
|
||||
trace("arch: GDT & TSS initialized.\n");
|
||||
}
|
||||
|
||||
#endif
|
|
@ -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
|
|
@ -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; }
|
||||
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(); }
|
|
@ -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();
|
||||
uint64_t limine_get_kernel_ehdr_addr();
|
||||
uint64_t limine_get_rsdp();
|
|
@ -9,6 +9,7 @@
|
|||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <acpi/acpi.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <boot/limine.h>
|
||||
#include <config.h>
|
||||
|
@ -19,6 +20,7 @@
|
|||
#include <mm/memop.h>
|
||||
#include <mm/pmm.h>
|
||||
#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();
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// Page flags
|
||||
#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_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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "lib/log.h"
|
||||
#include "mm/memop.h"
|
||||
#include <mm/paging.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "mm/paging.h"
|
||||
#include <stddef.h>
|
||||
|
||||
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);
|
Loading…
Add table
Add a link
Reference in a new issue