MMPFN Union 2

The MMPFN (Memory Manager Page Frame Number) structure is the key to pretty much everything that the Memory Manager knows about a page of physical memory that is in general use. Since an array of these structures for all physical memory needs to be kept in physical memory, the MMPFN is its own substantial overhead. Presumably to keep this down, ever more gets packed in to the MMPFN ever more intricately.

All known versions of the MMPFN have a u2 member. Members have come and gone and been reordered. The union itself has shifted within the MMPFN. As a type, the u2 member is originally an unnamed union. Windows 10 turns it into an MIPFNBLINK structure. Take away the scaffolding:

Offset (x86) Offset (x64) Definition Versions
0x08 (3.10 to 5.2);
0x04 (6.0 to 6.3);
0x10
0x10 (late 5.2);
0x08 (6.0 to 6.3);
0x18
PFN_NUMBER Blink;
3.10 to 6.1
struct {
    /*  see below: Blink Bits  */
};
6.2 and higher
0x04 (6.0 to 6.3) 0x08 (6.0 to 6.3)
MMPTE *ImageProtoPte;
6.0 to 6.3
0x08 (3.10 to 5.2);
0x04 (6.0 to 6.3);
0x10
0x10 (late 5.2);
0x08 (6.0 to 6.3);
0x18
ULONG_PTR ShareCount;
3.10 to 6.3
struct {
    /*  see below: ShareCount Bits  */
};
10.0 and higher
0x08 (5.0)  
ULONG SecondaryColorFlink;
5.0 only
0x10 0x18
ULONG_PTR EntireField;
10.0 and higher
0x10 0x18
union {
    LONG_PTR volatile Lock;
    struct {
        /*  see below: Lock Bits  */
    };
};
10.0 and higher

The Blink is meaningful when the physical page represented by the MMPFN is on any of several lists, e.g., of free pages. It is specifically the Page Frame Number (PFN) of the previous physical page on the same list.

Blink Bits

While 32-bit and 64-bit Windows need deal only with 36-bit and 48-bit physical addresses, pages of physical memory need only 24 or 36 bits of the ULONG or ULONGLONG that Microsoft defines for the PFN_NUMBER. Wherever a physical page number is kept in anything that’s similar to a Page Table Entry (PTE), there are always the low 12 bits for flags. In 64-bit Windows, and in 32-bit Windows with PAE, each PTE is eight bytes and high bits are available too. Throughout the following, the understanding is that PFN_BITS is:

Version x86 x64
6.2 25 36
6.3 and higher 24 36

Starting with 64-bit Windows 8, pages on a standby list can also be linked in a list just of pages that are on the same NUMA node. The ancient Blink coexists with what might be named NodeBlink except that it exists only as high and low parts. The high 20 bits are crammed into the one ULONGLONG with the full Blink and a new 4-bit TbFlushStamp. The low 16 bits replace the UsedPageTableEntries in the MMPFN directly.

Mask (x86) Mask (x64) Definition Versions
0x01FFFFFF (6.2);
0x00FFFFFF
0x0000000F`FFFFFFFF
ULONG_PTR Blink : PFN_BITS;
6.2 and higher
  0x00FFFFF0`00000000
ULONG_PTR NodeBlinkHigh : 20;
6.2 and higher
0x1E000000 (6.2);
0x0F000000
0x0F000000`00000000
ULONG_PTR TbFlushStamp : 4;
6.2 and higher
   
ULONG_PTR SpareBlink : 3;
6.2 to 6.3 (x86)
ULONG_PTR SpareBlink : 4;
6.2 to 6.3 (x64)
ULONG_PTR Unused : 2;
10.0 and higher
0x40000000 0x40000000`00000000
ULONG_PTR PageBlinkDeleteBit : 1;
10.0 and higher
0x80000000 0x80000000`00000000
ULONG_PTR PageBlinkLockBit : 1;
10.0 and higher

It’s not ordinarily a concern for these notes to track the masks of those bits that Microsoft labels spare, reserved or unused, but note that the narrowing of Blink by one bit for 32-bit Windows 8.1 is not accompanied by a widening of SpareBlink, which then does not account for all the spare bits. The highest two bits become meaningful in Windows 10 and are defined in all three sets of u2 bit fields, i.e., in union with Blink and ShareCount (where they apparently just mark space) and Lock (where they are meant to be used).

ShareCount Bits

The ShareCount in Windows 10 loses the highest two bits to the Lock.

Mask (x86) Mask (x64) Definition Versions
0x3FFFFFFF 0x3FFFFFFF`FFFFFFFF
ULONG ShareCount : 30;
10.0 and higher (x86)
ULONGLONG ShareCount : 62;
10.0 and higher (x64)
0x40000000 0x40000000`00000000
ULONG_PTR PageShareCountDeleteBit : 1;
10.0 and higher
0x80000000 0x80000000`00000000
ULONG_PTR PageShareCountLockBit : 1;
10.0 and higher

Lock Bits

The new Lock for Windows 10 uses only the highest two bits. Even this may be just a formality. The lock itself is much like a KSPIN_LOCK but with no instrumentation and using the high bit instead of the low.

Mask (x86) Mask (x64) Definition Versions
0x3FFFFFFF 0x3FFFFFFF`FFFFFFFF
ULONG LockNotUsed : 30;
10.0 and higher (x86)
ULONGLONG LockNotUsed : 62;
10.0 and higher (x64)
0x40000000 0x40000000`00000000
ULONG_PTR DeleteBit : 1;
10.0 and higher
0x80000000 0x80000000`00000000
ULONG_PTR LockBit : 1;
10.0 and higher