diff --git a/paw/stos/head/mm/vad.h b/paw/stos/head/mm/vad.h new file mode 100644 index 0000000..24853e0 --- /dev/null +++ b/paw/stos/head/mm/vad.h @@ -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 + +#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_ */ diff --git a/paw/stos/head/mm/vmm.h b/paw/stos/head/mm/vmm.h index 38b2da5..b0181c8 100644 --- a/paw/stos/head/mm/vmm.h +++ b/paw/stos/head/mm/vmm.h @@ -24,4 +24,13 @@ */ 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_ */ diff --git a/paw/stos/mm/vad.c b/paw/stos/mm/vad.c new file mode 100644 index 0000000..c41bdfc --- /dev/null +++ b/paw/stos/mm/vad.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2026, Chloe M. + * Provided under the BSD-3 clause. + * + * Description: VAD management + * Author: Chloe M. + */ + +#include + +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; +} diff --git a/paw/stos/mm/vmm.c b/paw/stos/mm/vmm.c index ced5259..e09b293 100644 --- a/paw/stos/mm/vmm.c +++ b/paw/stos/mm/vmm.c @@ -7,14 +7,117 @@ */ #include +#include +#include #include +#include #include #include +#include +#include + +#define VALLOC_MAX_PAGES 8192 +#define VALLOC_MAX (VALLOC_BASE + (VALLOC_MAX_PAGES * PAGESIZE)) +#define PAGES_PER_GRAB 16 #define DTRACE(Fmt, ...) \ TRACE("[ VMM ]: " Fmt, ##__VA_ARGS__) 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 MmInitVmm(VOID) @@ -32,4 +135,5 @@ MmInitVmm(VOID) HalMmuWriteVas(&KernelVas); DTRACE("ah!~... [ok @ %p]\n", VAS_BASE(&KernelVas)); + BumpPtr = VALLOC_BASE; }