1
0
Fork 0

feat/kernel: Started on valloc implementation for amd64

This commit is contained in:
Kevin Alavik 2025-05-15 15:57:14 +02:00
parent 91fc826022
commit 3aa5a1bb86
Signed by: cmpsb
GPG key ID: 10D1CC0526FDC6D7
6 changed files with 132 additions and 6 deletions

View file

@ -6,6 +6,9 @@
"limine.h": "c", "limine.h": "c",
"stddef.h": "c", "stddef.h": "c",
"stdint.h": "c", "stdint.h": "c",
"typeinfo": "c" "typeinfo": "c",
"log.h": "c",
"pmm.h": "c",
"paging.h": "c"
} }
} }

View file

@ -2,7 +2,7 @@
MAKEFLAGS += -rR MAKEFLAGS += -rR
.SUFFIXES: .SUFFIXES:
QEMUFLAGS := -m 2G -serial stdio -display none QEMUFLAGS := -m 2G -serial stdio # -display none
IMAGE_NAME := release/emk IMAGE_NAME := release/emk
HOST_CC := cc HOST_CC := cc

View file

@ -253,5 +253,10 @@ void paging_init(void)
} }
} }
for (uint64_t gb4 = 0; gb4 < 0x100000000; gb4 += PAGE_SIZE)
{
vmap(kernel_pagemap, (uint64_t)HIGHER_HALF(gb4), gb4, VMM_PRESENT | VMM_WRITE);
}
pmset(kernel_pagemap); pmset(kernel_pagemap);
} }

View file

@ -11,6 +11,7 @@
#include <sys/kpanic.h> #include <sys/kpanic.h>
#include <mm/pmm.h> #include <mm/pmm.h>
#include <arch/paging.h> #include <arch/paging.h>
#include <mm/vmm.h>
__attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3); __attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3);
__attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = { __attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = {
@ -67,7 +68,7 @@ void emk_entry(void)
hhdm_offset = hhdm_request.response->offset; hhdm_offset = hhdm_request.response->offset;
log_early("HHDM Offset: %llx", hhdm_offset); log_early("HHDM Offset: %llx", hhdm_offset);
pmm_init(); pmm_init();
log_early("Initialized PMM"); log_early("Initialized physical page manager");
/* Test allocate a single physical page */ /* Test allocate a single physical page */
char *a = palloc(1, true); char *a = palloc(1, true);
@ -89,5 +90,22 @@ void emk_entry(void)
paging_init(); paging_init();
log_early("Initialized paging"); log_early("Initialized paging");
/* Kernel Virtual Memory Context, not to be confused with KVM */
vpm_ctx_t *kvm_ctx = vmm_init(kernel_pagemap);
if (!kvm_ctx)
{
kpanic(NULL, "Failed to create kernel VMM context");
}
log_early("Initialized virtual page manager");
char *b = valloc(kvm_ctx, 1, VMM_PRESENT | VMM_WRITE);
if (!b)
{
kpanic(NULL, "Failed to allocate single virtual page");
}
*b = 32;
log_early("Allocated 1 virtual page: %llx", (uint64_t)b);
hlt(); hlt();
} }

94
kernel/src/mm/vmm.c Normal file
View file

@ -0,0 +1,94 @@
/* EMK 1.0 Copyright (c) 2025 Piraterna */
#include <mm/vmm.h>
#include <mm/pmm.h>
#include <util/log.h>
#include <util/align.h>
#include <boot/emk.h>
#include <arch/paging.h>
vpm_ctx_t *vmm_init(uint64_t *pm)
{
if (!pm || !IS_PAGE_ALIGNED(PHYSICAL(pm)))
return NULL;
vpm_ctx_t *ctx = (vpm_ctx_t *)palloc(1, true);
if (!ctx)
return NULL;
ctx->pagemap = pm;
ctx->root = NULL; /* valloc creates the root if not present */
return ctx;
}
void *valloc(vpm_ctx_t *ctx, size_t pages, uint64_t flags)
{
if (!ctx || !pages)
return NULL;
/* Allocate physical pages */
void *phys = palloc(pages, true);
if (!phys)
return NULL;
uint64_t virt = VPM_MIN_ADDR;
vm_region_t *prev = NULL;
vm_region_t *curr = ctx->root;
while (curr)
{
uint64_t curr_end = curr->start + (curr->pages * PAGE_SIZE);
if (virt + (pages * PAGE_SIZE) <= curr->start)
{
/* Found a gap */
break;
}
virt = curr_end;
prev = curr;
curr = curr->next;
}
/* Map the virtual to physical pages */
for (size_t i = 0; i < pages; i++)
{
uint64_t vaddr = virt + (i * PAGE_SIZE);
uint64_t paddr = (uint64_t)phys + (i * PAGE_SIZE);
if (vmap(ctx->pagemap, vaddr, paddr, flags) != 0)
{
/* Mapping failed, unmap any mapped pages and free physical memory */
for (size_t j = 0; j < i; j++)
{
vunmap(ctx->pagemap, virt + (j * PAGE_SIZE));
}
pfree(phys, pages);
return NULL;
}
}
/* Create new region */
vm_region_t *region = (vm_region_t *)palloc(1, true);
if (!region)
{
/* Region allocation failed, clean up */
for (size_t i = 0; i < pages; i++)
{
vunmap(ctx->pagemap, virt + (i * PAGE_SIZE));
}
pfree(phys, pages);
return NULL;
}
region->start = virt;
region->pages = pages;
region->next = curr;
if (prev)
{
prev->next = region;
}
else
{
ctx->root = region;
}
return (void *)virt;
}

View file

@ -3,6 +3,11 @@
#define VMM_H #define VMM_H
#include <stdint.h> #include <stdint.h>
#include <stddef.h>
#ifndef VPM_MIN_ADDR
#define VPM_MIN_ADDR 0x1000
#endif // VPM_MIN_ADDR
typedef struct vm_region typedef struct vm_region
{ {
@ -12,12 +17,13 @@ typedef struct vm_region
/* TOOD: Maybe store flags */ /* TOOD: Maybe store flags */
} vm_region_t; } vm_region_t;
typedef struct vma_ctx typedef struct vpm_ctx
{ {
vm_region_t *root; vm_region_t *root;
uint64_t *pagemap; uint64_t *pagemap;
} vma_ctx_t; } vpm_ctx_t;
void vmm_init(); vpm_ctx_t *vmm_init(uint64_t *pm);
void *valloc(vpm_ctx_t *ctx, size_t pages, uint64_t flags);
#endif // VMM_H #endif // VMM_H