These globals are defined in ntos/mm/miglobal.c and set in ntos/mm/mminit.c and ntos/mm/i386/init386.c.
These are available in kd as follows:Converting Virtual Address to PTE's.
The page tables are based at 0xc0000000. 32 bits of address space must be represented by all PTE's. Each PTE represents 12 bits of address space (a 4K page) and itself consumes 2 bits (PTE = 4 bytes). So:
32 - 12 + 2 = 22 bitsof address space is required. Therefore the top of the page table is at 0xc0400000-1.
The relationship between VA, a virtual address, and PTE, the address of the PTE for that address, is:
VA = (( PTE - PTE_BASE )/ 4 ) * 4K PTE = ( VA/4K ) * 4 + PTE_BASEIt is useful to note:
PTE_BASE = 0xc0000000 4K = 0x1000Because 4K is so nicely represented in hex, the only hard part for by-hand calculation is the division or multiplication by 4.
For example, the PTE for the base of the PTE table is:
PTE = ( 0xc0000000 / 0x1000 ) * 4 + 0xc0000000 = 0xc0000 * 4 + 0xc0000000 = 0x300000 + 0xc0000000 = 0xc0300000By clever coincidence, the page of PTE's starting at this addess is the PDE - a page of PTE's pointing to other pages of PTE's. The PTE of this VA is:
PTE = ( 0xc0300000 / 0x1000 ) * 4 + PTE_BASE = 0xc0300c00This PTE contains the page frame number of the page holding the page directory. However, there must also be some PDE containing this page frame number. Since address translation will work even if each PTE/PDE references a different page frame, the PDE for this address must be the same as the PTE for this address.
The PTE for 0xc0300c00, since it is on the same page as the previously calculated PTE, is at 0xc0300c00. This PTE maps itself.
We check this, and that the page frame number in this PTE/PDE is loaded into CR3:
kd> !pte c0300c00 C0300000 - PDE at C0300C00 PTE at C0300C00 contains 00030067 contains 00030067 pfn 00030 --DA--UWV pfn 00030 --DA--UWV kd> r eax=00000001 ebx=00725d11 ecx=8014d25c edx=000002f8 esi=000000ae edi=c1979f90 eip=80135b18 esp=801509f4 ebp=80150a04 iopl=0 nv up ei pl nz na pe nc cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202 cr0=8001003f cr2=01020004 cr3=00030000 kd>
Remarks on the PTE map.
The previous paragraph remarked that virtual address 0xc0300c00 is mapped by the PTE at the same virtual address. This is explained as the fixed point of the PTE map. Recall that the PTE map, PTE = h(VA), is linear:
PTE = h( VA ) = ( VA / PAGE_SIZE ) * PTE_SIZE + PTE_BASESo there is a solution to x = h(x). However, this solution need not be integral, so this explanation of the fixed point is faulty.
Note, however, that this special address, PTE_f = 0xc0300c00, can be calculated, for any PTE_BASE, as the third iterate of the map h:
PTE_f = h( h( h( X ) ) ), for any virtual address X.The first iterate maps an arbitrary virtual address to a PTE-aligned virtual address in the page table; the second iterate maps this address to a PDE in the page directory; and the third iterate maps this address the map's fixed point.
This is all by virtue that h is a contracting map:
X /superset h(X) /superset h(h(X)) /superset ... /superset Yand the displayed descending chain of address subsets must stablized, since the sets are discrete. Although abstract, this paragraph is a complete proof of the fixed point and illustrates all the conditions necessary for its existence.
For instace, for h to be contracting, the page directory must land page aligned. Hence we find that PTE_BASE must be aligned on a 4M boundary, or 0x00400000. The length of the chain before stabilization is one more than the layers of page tables. The two level page tables of the i386 implies that 3 interations of h are necessary.
As an alternative but hypothetical example, consider 256 byte pages of 64 PTE's per page, PTE's still 4 bytes. This would give a four level page table where each level uses 6 bits, and the final offset is 8 bits. ( 4*6+8=32 ). The fixed point would be calculated by taking h(h(h(h(h(X))))) for any X in the address space.
WinStation space layout.
The following comment is from ntos/mm/citrix/ctxmi.h. Only MmWinstationSpaceBase is a global and can be included in the table of significant globals.
// // Address Map when MmWinstationSpaceBase == 0xA3000000. // // When the system is booted in 2GB mode, these addresses // change. // // MmWinStationSpaceBase+0 // Base structure // 64K // // MmWinStationSpaceBase+0x10000 // Driver images // 12M-64K (re)based drivers allocated from top down // WIN32K.SYS based at 0xA3010000 always // // MmWinStationSpaceBase+0xC00000 // Working Set // 4M // // MmWinStationSpaceBase+0x1000000 // Paged Pool // 16M // // MmWinStationSpaceBase+0x2000000 // Mapped Views // 16M // // Total // 48M // // MmWinStationSpaceBase+0x3000000 // KSTACK POOL // // Total 416M // //
The WinstationSpace structures are in kernel space, but the active WinstaionSpace structure is mapped to MmWinStationSpaceBase. The first DWORD of this structure is the signature 0x0ccccccc, so this value should always appear at 0a3000000.
The MM_WINSTATIONSPACE structures are double-linked into a chain rooted at some global. Inside the structures are 20 PDE's which map up to 80M of Winstation space. Japanese has more.