All the pages resident in physical memory are manged by the PFN Database or Page Frame Number Database. The PFN is used to describe the page state of each page, and the number of references to this page.
The page states can be found in a enumeration called _MMLISTS:
Zeroed – The page already is free and already contains 0’s, or has been freed and being zeroed.
Free – The page is free, but may still contain data since the Dirty bit could have not been set, therefore these pages are zeroed before being marked as a user page for user-mode processes.
Standby – The page has been recently been removed from the working set of a process, and as a result is currently in Transition. The page hasn’t been written to or modified since removal and transfer to the hard disk, but the PTE (Invalid) may still refer to the physical page.
Modified – The page has been recently removed from the working set of a process, but has been written to and modified before it was written to the hard disk, thereby the contents of this page must be written to the hard disk before the physical page the PTE points to can be used.
Modified No-Write – The no write version of the Modified page state. The page will not be written to the hard disk.
Bad – The page has a parity error, or has other associated hardware issues with it. It may be used by the Kernel for look-aside caches and changing page states.
Active/Valid – The page is part of a working set (process or system), or is a non-paged pool page, and will therefore have a valid PTE.
Transition – Temporary page state used for pages which aren’t present on working set lists and other page state lists. I/O for these pages will be in progress, and collided page faults can be used here.
ROM – Read Only Memory Page
Since, we now understand the different page states, there is two methods for gathering system wide information about the page states used by the PFN database. The first method is to use the WinDbg extension called !memusage.
You will always notice a few bad pages, for the reasons explained earlier. The second method and the fastest method, would be to use the MemInfo Tool with the -s switch.
The appropriate program version is shown in the image below:
Structure of the PFN Database
The PFN Database is a array of data structures such as _MMPFN and _MMPFNENTRY. Each PFN Entry data structure is used to store information about a physical page in memory.
The flags are all represented by certain bits, and these flag meanings will be explained below:
WriteInProgress – Indicates that a write operation is in progress for this page. A event object will become signaled when this operation is complete.
Modified – Shows if the page was modified, and if so, then contents of the page must be written out to the disk before the page can be removed from memory.
ReadInProgress – Indicates that a read and in-page operation is in progress for this page. Again, a event object will be signaled when this operation is complete.
Rom – The page is currently read-only memory.
InPageError – I/O error occurred during a in-page operation with this page.
KernelStack – The page is being used to contain a Kernel Stack, the PFN Entry will contain the owner of the the stack and the next stack for the PFN for the same thread.
RemovalRequested – Indicates that page is eligible to removal.
ParityError – Physical page contains parity errors or ECC errors. There is a white paper somewhere on parity and ECC errors.
The !pfn extension can give us information about a PFN Entry. Using the !pfn with the known page frame, we can see the output seen below. Remember that we can obtain the Page Frame from the !pte extension. The !pfn gives similar information to the _MMPFN structure.
We can see the Reference Count field which refers to the number of references to this page. The reference count is incremented when added to the working set of a process, and when the page has been locked into memory for I/O. The reference count is decremented when the share count becomes 0, or when the page has been unlocked from memory.
We can also see the Share Count field which refers to the number of PTEs which refers to the page, this value can be greater than one for shared pages.
The Colour field is used to link physical pages together by colour, which refers to their location within the processor cache. This is generally used for performance purposes.
The Priority field shows us the page priority of the PFN, and thereby which standby list it will be placed upon. I’ll explain these page priorities a little later in my post.
Page Priority Levels
The page priority levels run from 0 to 7, with 0 being the lowest priority. The default priority level is 5, but the priority level can be inherited from the process’ thread which caused the allocation. The Memory Manager will always take pages from the standby list of the lowest priority first.
Using the MemInfo Tool with the -c extension, we can then view the Page Priority Standby lists, as shown here:
I’m going to explain the TLB Cache and Look Aside Lists in my next blog post instead, since this topic got a little big.