stos: mm: Add virtual page allocation
Signed-off-by: Chloe M. <chloe@mensia.org>
This commit is contained in:
@@ -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_ */
|
||||||
@@ -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_ */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user