stos: mm: Add virtual page allocation

Signed-off-by: Chloe M. <chloe@mensia.org>
This commit is contained in:
Chloe M.
2026-06-23 09:52:44 +00:00
parent 333331171d
commit d337a3d55b
4 changed files with 224 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause.
*
* Description: VAD management
* Author: Chloe M.
*/
#ifndef _MM_VAD_H_
#define _MM_VAD_H_ 1
#include <stdef.h>
#define VAD_FROM_VMA(VMA) \
((MM_VAD *)(VMA))
/*
* A virtual address descriptor represents a specific
* page of memory.
*
* @Next: Next free page
* @Prev: Previous free page
*/
typedef struct _MM_VAD {
struct _MM_VAD *Next;
struct _MM_VAD *Prev;
} MM_VAD;
/*
* Represents a virtual address descriptor list
*
* @First: First entry in VAD list
* @Last: Last entry in VAD list
*/
typedef struct {
MM_VAD *First;
MM_VAD *Last;
} MM_VAD_LIST;
/*
* Append a VAD to VAD list
*
* @List: VAD list to append to
* @Vad: VAD list to append
*/
VOID MmVadListAppend(MM_VAD_LIST *List, MM_VAD *Vad);
/*
* Pop a VAD from a VAD list
*
* @List: VAD list to pop from
*
* Returns NULL if no more entries
*/
MM_VAD *MmVadListPop(MM_VAD_LIST *List);
#endif /* !_MM_VAD_H_ */
+9
View File
@@ -24,4 +24,13 @@
*/ */
VOID MmInitVmm(VOID); VOID MmInitVmm(VOID);
/*
* Allocate a number of contiguous pages
*
* @Count: Number of pages to allocate
*
* Returns NULL on failure
*/
VOID *MmAllocPages(USIZE Count);
#endif /* !_MM_VMM_H_ */ #endif /* !_MM_VMM_H_ */
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2026, Chloe M.
* Provided under the BSD-3 clause.
*
* Description: VAD management
* Author: Chloe M.
*/
#include <mm/vad.h>
VOID
MmVadListAppend(MM_VAD_LIST *List, MM_VAD *Vad)
{
MM_VAD *Last;
if (List == NULL || Vad == NULL) {
return;
}
Vad->Next = NULL;
Vad->Prev = NULL;
if (List->Last == NULL || List->First == NULL) {
List->Last = Vad;
List->First = Vad;
} else {
Last = List->Last;
Vad->Prev = Last;
Last->Next = Vad;
List->Last = Vad;
}
}
MM_VAD *
MmVadListPop(MM_VAD_LIST *List)
{
MM_VAD *Last;
if (List == NULL) {
return NULL;
}
if (List->Last == NULL) {
return NULL;
}
Last = List->Last;
if (Last->Prev != NULL) {
Last->Prev->Next = NULL;
}
List->Last = Last->Prev;
return Last;
}
+104
View File
@@ -7,14 +7,117 @@
*/ */
#include <mm/vmm.h> #include <mm/vmm.h>
#include <mm/vad.h>
#include <mm/pmm.h>
#include <hal/mmu.h> #include <hal/mmu.h>
#include <hal/page.h>
#include <ex/trace.h> #include <ex/trace.h>
#include <ke/knot.h> #include <ke/knot.h>
#include <stapi/status.h>
#include <string.h>
#define VALLOC_MAX_PAGES 8192
#define VALLOC_MAX (VALLOC_BASE + (VALLOC_MAX_PAGES * PAGESIZE))
#define PAGES_PER_GRAB 16
#define DTRACE(Fmt, ...) \ #define DTRACE(Fmt, ...) \
TRACE("[ VMM ]: " Fmt, ##__VA_ARGS__) TRACE("[ VMM ]: " Fmt, ##__VA_ARGS__)
static MMU_VAS KernelVas; static MMU_VAS KernelVas;
static MM_VAD_LIST VadList;
static UPTR BumpPtr;
/*
* TODO: Add some locking around this
*/
static ST_STATUS
MmGrabPages(VOID)
{
USIZE MaxOff;
UPTR AllocBase;
MMU_VAS Vas;
MM_PFN AllocPfn;
ST_STATUS Status;
MaxOff = PAGES_PER_GRAB * PAGESIZE;
HalMmuReadVas(&Vas);
for (USIZE Off = 0; Off < MaxOff; Off += PAGESIZE) {
/* Don't blast past the limit */
if ((BumpPtr + Off) >= VALLOC_MAX) {
return STATUS_NO_MEMORY;
}
AllocBase = BumpPtr + Off;
AllocPfn = MmRequestFrame();
if (AllocPfn == 0) {
return STATUS_NO_MEMORY;
}
Status = HalMmuMapSingle(
&Vas,
AllocBase,
AllocPfn << LOG2_PAGESIZE,
PAGE_READWRITE,
PAGESIZE_4K
);
if (Status != STATUS_SUCCESS) {
return Status;
}
MmVadListAppend(&VadList, VAD_FROM_VMA(AllocBase));
}
BumpPtr = AllocBase;
return STATUS_SUCCESS;
}
/*
* TODO: Consider locking
*/
VOID *
MmAllocPages(USIZE Count)
{
MM_VAD *First, *Vad;
ST_STATUS Status;
if (Count == 0) {
return NULL;
}
First = NULL;
/*
* Request a VAD from the allocation VAD list and pull in
* more pages if we need to.
*
* XXX: We need to consider how we'll deal with fragmentation
* here, once it fills up it may become fragmented.
*/
for (USIZE Iter = 0; Iter < Count; ++Iter) {
Vad = MmVadListPop(&VadList);
if (Vad == NULL) {
Status = MmGrabPages();
if (Status != STATUS_SUCCESS)
return NULL;
Vad = MmVadListPop(&VadList);
}
/* Still no pages? */
if (Vad == NULL) {
return NULL;
}
if (First == NULL) {
First = Vad;
}
}
RtlMemSet(First, 0, sizeof(*First));
return (VOID *)First;
}
VOID VOID
MmInitVmm(VOID) MmInitVmm(VOID)
@@ -32,4 +135,5 @@ MmInitVmm(VOID)
HalMmuWriteVas(&KernelVas); HalMmuWriteVas(&KernelVas);
DTRACE("ah!~... [ok @ %p]\n", VAS_BASE(&KernelVas)); DTRACE("ah!~... [ok @ %p]\n", VAS_BASE(&KernelVas));
BumpPtr = VALLOC_BASE;
} }