kernel
Loading...
Searching...
No Matches
pfn.c
Go to the documentation of this file.
1/*++
2
3Module Name:
4
5 pfn.c
6
7Purpose:
8
9 This translation unit contains the implementation of the PFN Database (covers physical memory map init)
10
11Author:
12
13 slep (Matanel) 2025.
14
15Revision History:
16 DD/MM/YY
17
18
19 17/10/2025 - Revised Physical Memory from a simple bitmap to a PFN database.
20
21
22--*/
23
24#include "../../includes/mm.h"
25#include "../../includes/mg.h"
26#include "../../assert.h"
27#include "../../includes/me.h"
28
32
33uint64_t MmTotalMemory = 0;
35
36
37static
38uint64_t
39MiGetTotalMemory(
40 const BOOT_INFO* boot_info
41)
42
43/*++
44
45 Routine description:
46
47 Calculates the highest address of USABLE physical memory in the system.
48
49 Arguments:
50
51 [IN] Pointer to BOOT_INFO struct, obtained from UEFI.
52
53 Return Values:
54
55 Highest Usable Address in physical memory (total amount of usable RAM)
56
57 DO NOTE: The function will return the max address that is usable in the system, which might leave MMIO holes above, these will NOT be added into the PFN DB.
58
59--*/
60
61{
62 uint64_t highest_addr = 0;
63 size_t entry_count = boot_info->MapSize / boot_info->DescriptorSize;
64 PEFI_MEMORY_DESCRIPTOR desc = boot_info->MemoryMap;
65
66 for (size_t i = 0; i < entry_count; i++) {
67 if (desc->Type == EfiConventionalMemory)
68 {
69 uint64_t region_end = desc->PhysicalStart + (desc->NumberOfPages * PhysicalFrameSize);
70 if (region_end > highest_addr) highest_addr = region_end;
71 }
72
73 desc = (PEFI_MEMORY_DESCRIPTOR)((uint8_t*)desc + boot_info->DescriptorSize);
74 }
75
76 MmTotalUsableMemory = highest_addr;
77 return highest_addr;
78}
79
80static
81void
82MiReservePhysRange(
83 uint64_t phys_start,
84 uint64_t length
85)
86
87{
88 uint64_t first = phys_start / PhysicalFrameSize;
89 uint64_t pages = (length + PhysicalFrameSize - 1) / PhysicalFrameSize;
90 for (uint64_t i = 0; i < pages; ++i) {
91 uint64_t idx = first + i;
92 if (idx >= PfnDatabase.TotalPageCount) continue;
93 PPFN_ENTRY e = &PfnDatabase.PfnEntries[idx];
94 e->RefCount = 1;
98 }
99}
100
103 IN PBOOT_INFO BootInfo
104)
105
106/*++
107
108 Routine description:
109
110 Initializes the global PFN database.
111
112 Arguments:
113
114 [IN] Pointer to BOOT_INFO struct, obtained from UEFI.
115
116 Return Values:
117
118 MTSTATUS Status Code.
119
120--*/
121
122{
123 // First of all, before creating the PFN Database
124 // we would need the amount of total RAM, divide that by each physical frame size
125 // to allocate the amount of PFN_ENTRY(ies) needed.
126 uint64_t totalRam = MiGetTotalMemory(BootInfo);
127 if (!totalRam) return MT_NO_MEMORY;
128
129 uint64_t totalPfnEntries = totalRam / PhysicalFrameSize;
130
131 // The amount of PFN Entries needed times the sizeof the struct, gives us the amount in bytes.
132 uint64_t neededRam = totalPfnEntries * sizeof(PFN_ENTRY);
133 assert((neededRam) < INT32_MAX, "Needed Ram DB is insanely huge");
134
135 // Now, we need to find a suitable memory region to hold the PFN Entries in.
136 PEFI_MEMORY_DESCRIPTOR desc = BootInfo->MemoryMap;
137 size_t entryCount = BootInfo->MapSize / BootInfo->DescriptorSize;
138 uint64_t pfnEntriesPhys = 0;
139
140 // Loop over all memory.
141 for (size_t i = 0; i < entryCount; i++) {
142 if (desc->Type == EfiConventionalMemory) {
143 // This physical region size is the number of pages in it times frame size.
144 uint64_t regionSize = desc->NumberOfPages * PhysicalFrameSize;
145
146 if (regionSize >= neededRam) {
147 // This region can hold the PFN database entries.
148 pfnEntriesPhys = desc->PhysicalStart;
149 break;
150 }
151 }
152 // Advance to the next UEFI memory descriptor in the map.
153 desc = (PEFI_MEMORY_DESCRIPTOR)((uint8_t*)desc + BootInfo->DescriptorSize);
154 }
155
156 // Verify we found a suitable region.
157 if (!pfnEntriesPhys) return MT_NOT_FOUND;
158
159 // Convert the address to our virtual offsetable.
160 uint64_t pfnEntriesVirt = pfnEntriesPhys + PhysicalMemoryOffset;
161
162 // Initialize the doubly linked lists.
163 InitializeListHead(&PfnDatabase.FreePageList.ListEntry);
164 InitializeListHead(&PfnDatabase.BadPageList.ListEntry);
165 InitializeListHead(&PfnDatabase.StandbyPageList.ListEntry);
166 InitializeListHead(&PfnDatabase.ZeroedPageList.ListEntry);
167 InitializeListHead(&PfnDatabase.ModifiedPageList.ListEntry);
168
169 // Map the whole region, acquire its PTE for each 4KiB.
170 uint64_t neededPages = (neededRam + VirtualPageSize - 1) / VirtualPageSize;
171
172 for (uint64_t i = 0; i < neededPages; i++) {
173 PMMPTE pte = MiGetPtePointer(pfnEntriesVirt);
174 if (!pte) return MT_GENERAL_FAILURE;
175 MI_WRITE_PTE(pte, pfnEntriesVirt, pfnEntriesPhys, PAGE_PRESENT | PAGE_RW);
176 pfnEntriesVirt += VirtualPageSize;
177 pfnEntriesPhys += VirtualPageSize;
178 }
179
180 // Set the pointer.
181 uint64_t pfn_region_phys = pfnEntriesPhys - (neededPages * VirtualPageSize);
182 PfnDatabase.PfnEntries = (PPFN_ENTRY)(uintptr_t)(pfn_region_phys + PhysicalMemoryOffset);
183
184 // Zero the region.
185 kmemset(PfnDatabase.PfnEntries, 0, neededPages * VirtualPageSize);
186
187 // This ensures that holes (addresses not covered by UEFI map) are treated as invalid.
188 for (uint64_t i = 0; i < totalPfnEntries; i++) {
189 PfnDatabase.PfnEntries[i].State = PfnStateBad;
190 PfnDatabase.PfnEntries[i].RefCount = 0; // Optional if you want 0
191 }
192
193 // Initialize counts.
194 PfnDatabase.TotalPageCount = totalPfnEntries;
195 PfnDatabase.AvailablePages = 0;
196 PfnDatabase.TotalReserved = 0;
197
198 PfnDatabase.FreePageList.Count = 0;
199 PfnDatabase.BadPageList.Count = 0;
200 PfnDatabase.StandbyPageList.Count = 0;
201 PfnDatabase.ZeroedPageList.Count = 0;
202 PfnDatabase.ModifiedPageList.Count = 0;
203
204 // Initialize locks
205 PfnDatabase.PfnDatabaseLock.locked = 0;
206 PfnDatabase.BadPageList.PfnListLock.locked = 0;
207 PfnDatabase.StandbyPageList.PfnListLock.locked = 0;
208 PfnDatabase.ZeroedPageList.PfnListLock.locked = 0;
209 PfnDatabase.FreePageList.PfnListLock.locked = 0;
210 PfnDatabase.ModifiedPageList.PfnListLock.locked = 0;
211
212 // Reserve the PFN Array in the PFN List.
213 MiReservePhysRange(pfn_region_phys, neededPages * VirtualPageSize);
214
215 // We can interact with the entries, begin filling the PFN DB.
216 PAGE_INDEX lastPfnIdx = 0;
217 desc = BootInfo->MemoryMap; // reset desc to original pointer
218 for (size_t i = 0; i < entryCount; i++) {
219 uint64_t regionStart = desc->PhysicalStart;
220 uint64_t regionPages = desc->NumberOfPages;
221
222 // For each 4KiB page in the physical region of pages
223 for (uint64_t p = 0; p < regionPages; p++) {
224 // The physical address is calculated by taking the (regionStart (physical address of region base) plus the current increment) times the frame size.
225 uint64_t physAddr = regionStart + p * PhysicalFrameSize;
226
227 uint64_t currentPfnIndex = (physAddr / PhysicalFrameSize);
228
229 // UEFI Memory maps arent sorted in order, we could get address 0x100000 at one iteration, and address 0x2000 at the next iteration.
230 // We guard it with a simple if statement.
231 if (currentPfnIndex > lastPfnIdx) {
232 lastPfnIdx = currentPfnIndex;
233 }
234
235 if (currentPfnIndex >= PfnDatabase.TotalPageCount) {
236 // out of range physical address, we skip.
237 continue;
238 }
239
240 PPFN_ENTRY entry = &PfnDatabase.PfnEntries[currentPfnIndex];
241
242 // If this page is inside the PFN-array region we just reserved, skip adding it to db.
243 if (desc->Type == EfiConventionalMemory) {
244 if (physAddr >= pfn_region_phys && physAddr < pfn_region_phys + neededPages * VirtualPageSize) {
245 continue; // Do not touch this entry, it was set by MiReservePhysRange
246 }
247 }
248
249 // Initialize the PFN Entry.
250 entry->RefCount = 0;
251
252 switch (desc->Type) {
254 entry->State = PfnStateFree;
255 entry->Flags = PFN_FLAG_NONE;
256
257 // Add to free list.
258 InsertTailList(&PfnDatabase.FreePageList.ListEntry, &entry->Descriptor.ListEntry);
259 // Increment the free page list count.
260 InterlockedIncrementU64(&PfnDatabase.FreePageList.Count);
261 InterlockedIncrementU64(&PfnDatabase.AvailablePages);
262 break;
265 case EfiLoaderCode:
266 case EfiLoaderData:
270 case EfiACPIMemoryNVS:
271 // Mark pages used by firmware, loader, or kernel as active.
272 // these will not be returned by the page allocator.
273 entry->State = PfnStateActive;
274 entry->Flags = PFN_FLAG_NONE;
275 entry->Descriptor.Mapping.PteAddress = NULL;
276 entry->Descriptor.Mapping.Vad = NULL; // No VAD for these.
277 entry->RefCount = 1; // Set reference count to 1, so allocator will not get confused.
278 InterlockedIncrementU64(&PfnDatabase.TotalReserved);
279 break;
280 //case EfiACPIReclaimMemory TODO RECLAIMABLE.
281 default:
282 // If its not conventional memory, or one of the runtime/loader/boot/reserved, it is bad memory.
283 entry->State = PfnStateBad;
284 entry->Flags = PFN_FLAG_NONE;
285
286 // Add to free list and increment count.
287 InsertTailList(&PfnDatabase.BadPageList.ListEntry, &entry->Descriptor.ListEntry);
288 InterlockedIncrementU64(&PfnDatabase.BadPageList.Count);
289 break;
290 }
291 }
292 desc = (PEFI_MEMORY_DESCRIPTOR)((uint8_t*)desc + BootInfo->DescriptorSize);
293 }
294
295 // Set the global state as initialized.
297 MmHighestPfn = lastPfnIdx;
298 return MT_SUCCESS;
299}
300
301static
303MiReleaseAnyPage(
304 IN PDOUBLY_LINKED_LIST ListEntry
305)
306
307/*++
308
309 Routine description:
310
311 Attempts to retrieve a PFN Entry from the ListEntry given.
312
313 Arguments:
314
315 [IN] Pointer to ListEntry of PFN_LIST.
316
317 Return Values:
318
319 Pointer of PFN_ENTRY, NULL on failure.
320
321--*/
322
323{
324 PDOUBLY_LINKED_LIST pListEntry = RemoveHeadList(ListEntry);
325 if (!pListEntry) return NULL;
326
327 // Return the PFN_ENTRY of this ListEntry.
328 PPFN_ENTRY pPfnEntry = CONTAINING_RECORD(pListEntry, PFN_ENTRY, Descriptor.ListEntry);
329 return pPfnEntry;
330}
331
334 IN PFN_STATE ListType
335)
336
337/*++
338
339 Routine description:
340
341 Retrieves a physical page from the PFN Database.
342
343 Arguments:
344
345 [IN] enum _PFN_STATE Type. (e.g PfnStateZeroed is guranteed to return a zeroed physical page)
346
347 Return Values:
348
349 PFN Index of the page, otherwise PFN_ERROR on failure.
350
351 Notes:
352
353 The PFN index given, does not return an actively mapped PFN (that is mapped to a VA), other functions must set its mapping.
354
355--*/
356
357{
358 // Declarations
359 IRQL oldIrql;
360 IRQL DbIrql;
361 PPFN_ENTRY pfn = NULL;
362 PFN_STATE oldState; // To know if we need to zero
363
364 // Acquire global PFN DB lock.
365 MsAcquireSpinlock(&PfnDatabase.PfnDatabaseLock, &DbIrql);
366
367 // 1. Try ZeroedPageList
368 MsAcquireSpinlock(&PfnDatabase.ZeroedPageList.PfnListLock, &oldIrql);
369 pfn = MiReleaseAnyPage(&PfnDatabase.ZeroedPageList.ListEntry);
370 MsReleaseSpinlock(&PfnDatabase.ZeroedPageList.PfnListLock, oldIrql);
371 if (pfn) {
372 InterlockedDecrementU64(&PfnDatabase.ZeroedPageList.Count);
373 oldState = PfnStateZeroed;
374 goto found;
375 }
376
377 // 2. Try FreePageList
378 MsAcquireSpinlock(&PfnDatabase.FreePageList.PfnListLock, &oldIrql);
379 pfn = MiReleaseAnyPage(&PfnDatabase.FreePageList.ListEntry);
380 MsReleaseSpinlock(&PfnDatabase.FreePageList.PfnListLock, oldIrql);
381 if (pfn) {
382 InterlockedDecrementU64(&PfnDatabase.FreePageList.Count);
383 oldState = PfnStateFree;
384 goto found;
385 }
386
387 // 3. Try StandbyPageList
388 MsAcquireSpinlock(&PfnDatabase.StandbyPageList.PfnListLock, &oldIrql);
389 pfn = MiReleaseAnyPage(&PfnDatabase.StandbyPageList.ListEntry);
390 MsReleaseSpinlock(&PfnDatabase.StandbyPageList.PfnListLock, oldIrql);
391 if (pfn) {
392 InterlockedDecrementU64(&PfnDatabase.StandbyPageList.Count);
393 oldState = PfnStateStandby;
394 goto found;
395 }
396
397 // 4. All lists are empty
398 // TODO: Paging (flush modified list to disk, give a page from there.)
399 // If paging fails, that means a buggy storage driver, a thread starve, or other (view the NO_PAGES_AVAILABLE 0x4D bugcheck in msdn)
400
401 // Release Global Lock
402 MsReleaseSpinlock(&PfnDatabase.PfnDatabaseLock, DbIrql);
403 return PFN_ERROR;
404
405found:
406 assert((pfn->RefCount) == 0);
407
408 // Claim while locked.
409 // Set final metadata: now "owned" by the caller.
411 pfn->RefCount = 1;
412
413 // Release Global Lock
414 MsReleaseSpinlock(&PfnDatabase.PfnDatabaseLock, DbIrql);
415 // Decrement total available pages
416 InterlockedDecrementU64(&PfnDatabase.AvailablePages);
417
418 uint64_t pfnIndex = PPFN_TO_INDEX(pfn);
419
420 // If caller wants a zeroed page, but we didn't get one, zero it now.
421 if (ListType == PfnStateZeroed && oldState != PfnStateZeroed) {
422 IRQL hyperIrql;
423 uint8_t* va = MiMapPageInHyperspace(pfnIndex, &hyperIrql);
424 kmemset(va, 0, VirtualPageSize);
425 MiUnmapHyperSpaceMap(hyperIrql);
426 }
427
428 return pfnIndex;
429}
430
432extern char MiReleasePhysicalPage_end;
433
434#ifndef _MSC_VER
435asm(".global MiReleasePhysicalPage_start\n"
436 "MiReleasePhysicalPage_start:\n");
437#endif
438
440void
442 IN PAGE_INDEX PfnIndex
443)
444
445/*++
446
447 Routine description:
448
449 Releases a physical page back to the memory manager
450
451 Arguments:
452
453 [IN] PAGE_INDEX Index of the PFN given by MiRequestPhysicalPage
454
455 Return Values:
456
457 None.
458
459--*/
460
461{
462 // First, access the PFN in the database to determine its staistics.
463 PPFN_ENTRY pfn = INDEX_TO_PPFN(PfnIndex);
464
465 assert((pfn->RefCount) > 0, "Refcount is 0 while releasing. Double Free");
466
467 if (InterlockedDecrementU32(&pfn->RefCount) == 0) {
468 // This is the last reference to the page, store it back in the list.
469 if (pfn->State == PfnStateActive) {
470 // Clear mapping info.
471 pfn->Descriptor.Mapping.Vad = NULL;
472 if (pfn->Descriptor.Mapping.PteAddress != NULL &&
474 // Dirty bit is set, we throw it back to the modified page list.
475 IRQL oldIrql;
476 pfn->State = PfnStateModified;
477 MsAcquireSpinlock(&PfnDatabase.ModifiedPageList.PfnListLock, &oldIrql);
478 InsertTailList(&PfnDatabase.ModifiedPageList.ListEntry, &pfn->Descriptor.ListEntry);
479
480 // Increment the counters
481 InterlockedIncrementU64(&PfnDatabase.ModifiedPageList.Count);
482
483 // Available pages is not incremented for the modified page list, as they should not be available just yet (need to be flushed to disk)
484 //
485 //InterlockedIncrementU64(&PfnDatabase.AvailablePages);
486
487 MsReleaseSpinlock(&PfnDatabase.ModifiedPageList.PfnListLock, oldIrql);
488 }
489 else {
490 // Dirty bit is not set, we throw it to the standby list.
491 IRQL oldIrql;
492 pfn->State = PfnStateStandby;
493 MsAcquireSpinlock(&PfnDatabase.StandbyPageList.PfnListLock, &oldIrql);
494 InsertTailList(&PfnDatabase.StandbyPageList.ListEntry, &pfn->Descriptor.ListEntry);
495
496 // Increment the counters
497 InterlockedIncrementU64(&PfnDatabase.StandbyPageList.Count);
498 InterlockedIncrementU64(&PfnDatabase.AvailablePages);
499
500 // Set PTE as transition (compare-exchange)
503
504 MsReleaseSpinlock(&PfnDatabase.StandbyPageList.PfnListLock, oldIrql);
505 }
506 }
507 }
508}
509
510#ifndef _MSC_VER
511asm(".global MiReleasePhysicalPage_end\n"
512 "MiReleasePhysicalPage_end:\n");
513#endif
514
515bool
517 void* VirtualAddress
518)
519
520// Self explanatory function, this is only used for debugging.
521
522{
523 uintptr_t a = (uintptr_t)VirtualAddress;
524 uintptr_t s = (uintptr_t)&MiReleasePhysicalPage_start;
525 uintptr_t e = (uintptr_t)&MiReleasePhysicalPage_end;
526 return (a >= s) && (a < e);
527}
528
529void
531 PPFN_ENTRY pfn
532)
533
534// Unlink a specified PPFN_ENTRY from its PfnDb list.
535
536{
537 IRQL oldIrql;
538 SPINLOCK* lock = NULL;
539 volatile uint64_t* count = NULL;
540
541 /* Determine which list this PFN is on and pick the corresponding lock/count */
542 switch (pfn->State) {
543 case PfnStateFree:
544 lock = &PfnDatabase.FreePageList.PfnListLock;
545 count = &PfnDatabase.FreePageList.Count;
546 break;
547 case PfnStateZeroed:
548 lock = &PfnDatabase.ZeroedPageList.PfnListLock;
549 count = &PfnDatabase.ZeroedPageList.Count;
550 break;
551 case PfnStateStandby:
552 lock = &PfnDatabase.StandbyPageList.PfnListLock;
553 count = &PfnDatabase.StandbyPageList.Count;
554 break;
555 default:
556 /* Active/Modified/Bad pages are handled elsewhere */
557 return;
558 }
559
560 MsAcquireSpinlock(lock, &oldIrql);
561
562 /*
563 * Guard: if the entry isn't linked (both pointers NULL) then nothing to do.
564 * This avoids calling RemoveEntryList on an unlinked node.
565 */
566 if (pfn->Descriptor.ListEntry.Flink == NULL &&
567 pfn->Descriptor.ListEntry.Blink == NULL) {
568 MsReleaseSpinlock(lock, oldIrql);
569 return;
570 }
571
572 /* Remove this node from whatever list it currently sits on. */
574
575 /* Clear the entry's links to mark it as unlinked (like RemoveHeadList does). */
577
578 /* Update list and global counts while holding the lock. */
580 InterlockedDecrementU64(&PfnDatabase.AvailablePages);
581
582 MsReleaseSpinlock(lock, oldIrql);
583}
#define NOINLINE
Definition annotations.h:69
#define IN
Definition annotations.h:8
#define assert(...)
Definition assert.h:57
FORCEINLINE uint64_t InterlockedIncrementU64(volatile uint64_t *target)
Definition atomic.h:125
FORCEINLINE uint32_t InterlockedDecrementU32(volatile uint32_t *target)
Definition atomic.h:122
FORCEINLINE uint64_t InterlockedDecrementU64(volatile uint64_t *target)
Definition atomic.h:128
struct _DOUBLY_LINKED_LIST * PDOUBLY_LINKED_LIST
enum _IRQL IRQL
#define EfiRuntimeServicesData
Definition efi.h:91
struct _BOOT_INFO * PBOOT_INFO
#define EfiBootServicesCode
Definition efi.h:88
#define EfiLoaderData
Definition efi.h:87
#define EfiACPIMemoryNVS
Definition efi.h:95
#define EfiLoaderCode
Definition efi.h:86
#define EfiBootServicesData
Definition efi.h:89
struct _BOOT_INFO BOOT_INFO
struct _EFI_MEMORY_DESCRIPTOR * PEFI_MEMORY_DESCRIPTOR
#define EfiConventionalMemory
Definition efi.h:92
#define EfiRuntimeServicesCode
Definition efi.h:90
#define EfiReservedMemoryType
Definition efi.h:85
void * MiMapPageInHyperspace(IN uint64_t PfnIndex, OUT PIRQL OldIrql)
Definition hypermap.c:37
void MiUnmapHyperSpaceMap(IN IRQL OldIrql)
Definition hypermap.c:95
#define UNREFERENCED_PARAMETER(x)
Definition intrin.h:29
#define CONTAINING_RECORD(ptr, type, member)
Definition macros.h:11
PMMPTE MiGetPtePointer(IN uintptr_t va)
Definition map.c:76
bool MiAtomicSetTransitionPte(IN PMMPTE Pte, IN PAGE_INDEX Pfn)
Definition map.c:438
@ PAGE_RW
Definition mm.h:311
@ PAGE_PRESENT
Definition mm.h:307
#define PhysicalFrameSize
Definition mm.h:54
@ PfnStateTransition
Definition mm.h:281
@ PfnStateFree
Definition mm.h:279
@ PfnStateZeroed
Definition mm.h:280
@ PfnStateModified
Definition mm.h:278
@ PfnStateActive
Definition mm.h:276
@ PfnStateStandby
Definition mm.h:277
@ PfnStateBad
Definition mm.h:282
enum _PFN_STATE PFN_STATE
#define PPFN_TO_INDEX(PPFN)
Definition mm.h:135
struct _MMPTE * PMMPTE
struct _MM_PFN_DATABASE MM_PFN_DATABASE
struct _PFN_ENTRY PFN_ENTRY
uint64_t PAGE_INDEX
Definition mm.h:256
FORCEINLINE void * kmemset(void *dest, int64_t val, uint64_t len)
Definition mm.h:655
#define PhysicalMemoryOffset
Definition mm.h:56
#define PFN_ERROR
Definition mm.h:229
#define VirtualPageSize
Definition mm.h:53
#define INDEX_TO_PPFN(Index)
Definition mm.h:62
#define MI_WRITE_PTE(_PtePointer, _Va, _Pa, _Flags)
Definition mm.h:90
struct _PFN_ENTRY * PPFN_ENTRY
@ PFN_FLAG_NONE
Definition mm.h:287
FORCEINLINE PDOUBLY_LINKED_LIST RemoveHeadList(PDOUBLY_LINKED_LIST Head)
Definition ms.h:272
FORCEINLINE void InitializeListHead(PDOUBLY_LINKED_LIST Head)
Definition ms.h:223
FORCEINLINE void InsertTailList(PDOUBLY_LINKED_LIST Head, PDOUBLY_LINKED_LIST Entry)
Definition ms.h:236
struct _SPINLOCK SPINLOCK
FORCEINLINE void RemoveEntryList(PDOUBLY_LINKED_LIST Entry)
Definition ms.h:297
#define MT_NO_MEMORY
Definition mtstatus.h:42
#define MT_SUCCESS
Definition mtstatus.h:22
#define MT_GENERAL_FAILURE
Definition mtstatus.h:31
int32_t MTSTATUS
Definition mtstatus.h:12
#define MT_NOT_FOUND
Definition mtstatus.h:30
PAGE_INDEX MiRequestPhysicalPage(IN PFN_STATE ListType)
Definition pfn.c:333
NOINLINE void MiReleasePhysicalPage(IN PAGE_INDEX PfnIndex)
Definition pfn.c:441
PAGE_INDEX MmHighestPfn
Definition pfn.c:31
void MiUnlinkPageFromList(PPFN_ENTRY pfn)
Definition pfn.c:530
char MiReleasePhysicalPage_end
bool MmPfnDatabaseInitialized
Definition pfn.c:30
bool MiIsWithinBoundsOfReleasePhysicalPage(void *VirtualAddress)
Definition pfn.c:516
uint64_t MmTotalUsableMemory
Definition pfn.c:34
MM_PFN_DATABASE PfnDatabase
Definition pfn.c:29
char MiReleasePhysicalPage_start
uint64_t MmTotalMemory
Definition pfn.c:33
MTSTATUS MiInitializePfnDatabase(IN PBOOT_INFO BootInfo)
Definition pfn.c:102
void MsAcquireSpinlock(IN PSPINLOCK lock, IN PIRQL OldIrql)
Definition spinlock.c:13
void MsReleaseSpinlock(IN PSPINLOCK lock, IN IRQL OldIrql)
Definition spinlock.c:45
EFI_MEMORY_DESCRIPTOR * MemoryMap
Definition efi.h:54
size_t DescriptorSize
Definition efi.h:56
size_t MapSize
Definition efi.h:55
struct _DOUBLY_LINKED_LIST * Blink
Definition core.h:30
struct _DOUBLY_LINKED_LIST * Flink
Definition core.h:31
uint32_t Type
Definition efi.h:34
uint64_t NumberOfPages
Definition efi.h:38
uint64_t PhysicalStart
Definition efi.h:36
struct _MMPTE::@172372265215056352375070220246156106027174106113::@200357034104227323320222006243127050212100105247 Hard
uint64_t Dirty
Definition mm.h:436
union _PFN_ENTRY::@217024126340164016372152071216274230164113211246 Descriptor
volatile uint32_t RefCount
Definition mm.h:470
struct _PFN_ENTRY::@217024126340164016372152071216274230164113211246::@301110335271023021153236134322146064331241142124 Mapping
uint8_t State
Definition mm.h:471
PMMPTE PteAddress
Definition mm.h:482
struct _MMVAD * Vad
Definition mm.h:481
struct _DOUBLY_LINKED_LIST ListEntry
Definition mm.h:477
uint8_t Flags
Definition mm.h:472