Geoff Chappell - Software Analyst
For each physical page that’s in general use, the kernel keeps one MMPFN structure. For each physical page that’s not in active use (or at least in transition to or from active use), the MMPFN goes into one or another list. The MMPFNLIST structure (formally _MMPFNLIST) is the list head.
Before Windows 10, the list heads are internal variables in the kernel’s data. In Windows 10 and higher, with physical memory in separate partitions, the list heads are the PageLists and Vp members of an MI_PARTITION structure.
The MMPFNLIST structure is 0x14 or 0x28 bytes in 32-bit and 64-bit Windows 10, respectively, since its one change for Windows 7. In earlier versions it is 0x10 or 0x20 bytes.
Offset (x86) | Offset (x64) | Definition | Versions |
---|---|---|---|
0x00 | 0x00 |
ULONG_PTR Total; |
all |
0x04 | 0x08 |
MMLISTS ListName; |
all |
0x08 | 0x10 |
PFN_NUMBER Flink; |
all |
0x0C | 0x18 |
PFN_NUMBER Blink; |
all |
0x10 | 0x20 |
ULONG_PTR Lock; |
6.1 and higher |
The Total is of pages in the list. The ListName has long been only a rough classification of the list’s purpose. In early versions, the kernel has six lists among its internal variables, each with a unique ListName. Only in version 3.10 does each list have its own ListName. Version 5.0 added a second list that shares StandbyPageList for its ListName. Ever since, the ListName is arguably more a list type.
The kernel keeps all MMPFN structures in an array that is indexed by the Page Frame Number (PFN) of the corresponding pages of physical memory. For each page that’s in a list, the MMPFN has its Flink and Blink members set to the PFN of the next and previous page, respectively, or to a terminating value if the page is at the tail or head. The terminator varies with the version:
x86 | x64 | Version |
---|---|---|
0xFFFFFFFF | 0xFFFFFFFF`FFFFFFFF | 3.10 to 6.1 |
0x01FFFFFF | 0x0000000F`FFFFFFFF | 6.2 only |
0x00FFFFFF | 0x0000000F`FFFFFFFF | 6.3 and higher |
This interpretation applies also to the Flink and Blink in the MMPFNLIST. They are respectively the PFN of the first and last pages in the list, else they hold the terminating value.