ptos: pm: Add frame allocation and reclamation
Signed-off-by: Chloe M <chloe@yiffware.org>
This commit is contained in:
@@ -12,6 +12,9 @@
|
|||||||
#include <ptdef.h>
|
#include <ptdef.h>
|
||||||
#include <hal/page.h>
|
#include <hal/page.h>
|
||||||
|
|
||||||
|
/* Used when out of memory */
|
||||||
|
#define PFN_ERROR 0
|
||||||
|
|
||||||
/* Page frame number type */
|
/* Page frame number type */
|
||||||
typedef USIZE MM_PFN;
|
typedef USIZE MM_PFN;
|
||||||
|
|
||||||
@@ -29,4 +32,18 @@ typedef USIZE MM_PFN;
|
|||||||
*/
|
*/
|
||||||
VOID MmPmInit(VOID);
|
VOID MmPmInit(VOID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Request a single frame of memory
|
||||||
|
*
|
||||||
|
* Returns PFN_ERROR on failure
|
||||||
|
*/
|
||||||
|
MM_PFN MmRequestFrame(VOID);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reclaim a single frame of memory
|
||||||
|
*
|
||||||
|
* @Pfn: Page frame number to reclaim
|
||||||
|
*/
|
||||||
|
VOID MmReclaimFrame(MM_PFN Pfn);
|
||||||
|
|
||||||
#endif /* !_MM_PM_H_ */
|
#endif /* !_MM_PM_H_ */
|
||||||
|
|||||||
+142
-3
@@ -7,8 +7,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <mm/pm.h>
|
#include <mm/pm.h>
|
||||||
|
#include <mm/vm.h>
|
||||||
#include <ke/bpal.h>
|
#include <ke/bpal.h>
|
||||||
#include <ex/trace.h>
|
#include <ex/trace.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#define DTRACE(Fmt, ...) \
|
#define DTRACE(Fmt, ...) \
|
||||||
TRACE("[ PM ]: " Fmt, ##__VA_ARGS__)
|
TRACE("[ PM ]: " Fmt, ##__VA_ARGS__)
|
||||||
@@ -34,6 +36,88 @@ static const CHAR *PmRegionTable[] = {
|
|||||||
[MEMORY_ACPI_TABLES] = "acpi tables"
|
[MEMORY_ACPI_TABLES] = "acpi tables"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A page frame descriptor is an entry within the physical memory
|
||||||
|
* freelist.
|
||||||
|
*
|
||||||
|
* @Next: Next PFD in freelist
|
||||||
|
* @Prev: Previous PFD in freelist
|
||||||
|
*/
|
||||||
|
typedef struct _MM_PFD {
|
||||||
|
struct _MM_PFD *Next;
|
||||||
|
struct _MM_PFD *Prev;
|
||||||
|
} MM_PFD;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A page frame descriptor list holds many page frame
|
||||||
|
* descriptors and marks the start and end of a physical
|
||||||
|
* memory freelist.
|
||||||
|
*
|
||||||
|
* @First: First entry in freelist
|
||||||
|
* @Last: Last entry in freelist
|
||||||
|
*
|
||||||
|
* TODO: Add a lock to this structure
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
MM_PFD *First;
|
||||||
|
MM_PFD *Last;
|
||||||
|
} MM_PFD_LIST;
|
||||||
|
|
||||||
|
/* Standard usable memory list */
|
||||||
|
static MM_PFD_LIST AvlList;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Appends a page frame descriptor to a page frame descriptor
|
||||||
|
* list.
|
||||||
|
*
|
||||||
|
* @List: Page frame descriptor list to append to
|
||||||
|
* @Pfd: Page frame descriptor to append
|
||||||
|
*/
|
||||||
|
static VOID
|
||||||
|
PmPfdListAppend(MM_PFD_LIST *List, MM_PFD *Pfd)
|
||||||
|
{
|
||||||
|
MM_PFD *LastPfd;
|
||||||
|
|
||||||
|
if (List == NULL || Pfd == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pfd->Next = NULL;
|
||||||
|
Pfd->Prev = NULL;
|
||||||
|
|
||||||
|
if (List->First == NULL || List->Last == NULL) {
|
||||||
|
List->First = Pfd;
|
||||||
|
List->Last = Pfd;
|
||||||
|
} else {
|
||||||
|
LastPfd = List->Last;
|
||||||
|
LastPfd->Next = Pfd;
|
||||||
|
Pfd->Prev = LastPfd;
|
||||||
|
List->Last = Pfd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pop a page frame descriptor from the beginning of a page
|
||||||
|
* frame descriptor list.
|
||||||
|
*
|
||||||
|
* @List: Page frame descriptor list to pop from
|
||||||
|
*
|
||||||
|
* Returns NULL on failure
|
||||||
|
*/
|
||||||
|
static MM_PFD *
|
||||||
|
PmPfdListPop(MM_PFD_LIST *List)
|
||||||
|
{
|
||||||
|
MM_PFD *FirstPfd;
|
||||||
|
|
||||||
|
if (List == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FirstPfd = List->First;
|
||||||
|
List->First = FirstPfd->Next;
|
||||||
|
return FirstPfd;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Probe physical memory for usable regions and list
|
* Probe physical memory for usable regions and list
|
||||||
* installed memory.
|
* installed memory.
|
||||||
@@ -44,8 +128,10 @@ PmProbe(VOID)
|
|||||||
PT_STATUS Status;
|
PT_STATUS Status;
|
||||||
BPAL_HANDLE BpalHandle;
|
BPAL_HANDLE BpalHandle;
|
||||||
MEMMAP_ENTRY Entry;
|
MEMMAP_ENTRY Entry;
|
||||||
UPTR Start, End;
|
UPTR Start, End, Off;
|
||||||
USIZE Index;
|
MM_PFD *PfdBase, *PfdCurrent;
|
||||||
|
USIZE Index, PfdCount = 0;
|
||||||
|
USIZE ZoneCount = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We obtain memory map entries from the BPAL layer as it is provided
|
* We obtain memory map entries from the BPAL layer as it is provided
|
||||||
@@ -53,7 +139,15 @@ PmProbe(VOID)
|
|||||||
*/
|
*/
|
||||||
KeBpalGetHandle(&BpalHandle);
|
KeBpalGetHandle(&BpalHandle);
|
||||||
|
|
||||||
/* Iterate each memory entry */
|
/*
|
||||||
|
* Iterate each memory entry, we use two terms here:
|
||||||
|
*
|
||||||
|
* Zones: A zone is a contigious region of frames and consists
|
||||||
|
* of many page frame descriptors.
|
||||||
|
*
|
||||||
|
* PFDs: A page frame descriptor represents a single frame within
|
||||||
|
* a zone.
|
||||||
|
*/
|
||||||
for (Index = 0;; ++Index) {
|
for (Index = 0;; ++Index) {
|
||||||
Status = BpalHandle.MemEntryIdx(Index, &Entry);
|
Status = BpalHandle.MemEntryIdx(Index, &Entry);
|
||||||
|
|
||||||
@@ -70,7 +164,52 @@ PmProbe(VOID)
|
|||||||
End,
|
End,
|
||||||
PM_REGION(Entry.Type)
|
PM_REGION(Entry.Type)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Usable entries from this point only */
|
||||||
|
if (Entry.Type != MEMORY_USABLE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Append this zone */
|
||||||
|
PfdBase = (MM_PFD *)PMA_TO_VMA(Entry.Base);
|
||||||
|
for (Off = 0; Off < Entry.Length; Off += PAGESIZE) {
|
||||||
|
PfdCurrent = PTR_OFFSET(PfdBase, Off);
|
||||||
|
PmPfdListAppend(&AvlList, PfdCurrent);
|
||||||
|
++PfdCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
++ZoneCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DTRACE("%d pfds, %d zones\n", PfdCount, ZoneCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
MM_PFN
|
||||||
|
MmRequestFrame(VOID)
|
||||||
|
{
|
||||||
|
MM_PFD *Pfd;
|
||||||
|
UPTR PhysicalBase;
|
||||||
|
|
||||||
|
Pfd = PmPfdListPop(&AvlList);
|
||||||
|
RtlMemSet(Pfd, 0, PAGESIZE);
|
||||||
|
|
||||||
|
PhysicalBase = (UPTR)Pfd;
|
||||||
|
return ADDRESS_TO_PFN(PhysicalBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
MmReclaimFrame(MM_PFN Pfn)
|
||||||
|
{
|
||||||
|
MM_PFD *Pfd;
|
||||||
|
UPTR PhysicalBase;
|
||||||
|
|
||||||
|
if (Pfn == PFN_ERROR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalBase = PFN_TO_ADDRESS(Pfn);
|
||||||
|
Pfd = (VOID *)PMA_TO_VMA(PhysicalBase);
|
||||||
|
PmPfdListAppend(&AvlList, Pfd);
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
|
|||||||
Reference in New Issue
Block a user