feat/kernel: Started on valloc implementation for amd64
This commit is contained in:
parent
91fc826022
commit
3aa5a1bb86
6 changed files with 132 additions and 6 deletions
|
@ -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);
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#include <sys/kpanic.h>
|
||||
#include <mm/pmm.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 struct limine_memmap_request memmap_request = {
|
||||
|
@ -67,7 +68,7 @@ void emk_entry(void)
|
|||
hhdm_offset = hhdm_request.response->offset;
|
||||
log_early("HHDM Offset: %llx", hhdm_offset);
|
||||
pmm_init();
|
||||
log_early("Initialized PMM");
|
||||
log_early("Initialized physical page manager");
|
||||
|
||||
/* Test allocate a single physical page */
|
||||
char *a = palloc(1, true);
|
||||
|
@ -89,5 +90,22 @@ void emk_entry(void)
|
|||
paging_init();
|
||||
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();
|
||||
}
|
94
kernel/src/mm/vmm.c
Normal file
94
kernel/src/mm/vmm.c
Normal 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;
|
||||
}
|
|
@ -3,6 +3,11 @@
|
|||
#define VMM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef VPM_MIN_ADDR
|
||||
#define VPM_MIN_ADDR 0x1000
|
||||
#endif // VPM_MIN_ADDR
|
||||
|
||||
typedef struct vm_region
|
||||
{
|
||||
|
@ -12,12 +17,13 @@ typedef struct vm_region
|
|||
/* TOOD: Maybe store flags */
|
||||
} vm_region_t;
|
||||
|
||||
typedef struct vma_ctx
|
||||
typedef struct vpm_ctx
|
||||
{
|
||||
vm_region_t *root;
|
||||
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
|
Loading…
Add table
Add a link
Reference in a new issue