SKETCH OF HOW RESEARCH MIGHT CONTINUE AND RESULTS BE PRESENTED

MI_SYSTEM_VA_TYPE

From the beginning, Windows separates virtual address space into a low part for user mode and a high part for kernel mode. The user space varies with the process and can be accessed by both user-mode and kernel-mode code. The system space is mostly global but is accessible only to code that executes in kernel mode. This still serves as a rough understanding, despite elaborations. An important one is that the division was originally equal, with 2GB each, but was made configurable as long ago as Windows NT 4.0 SP3 so that the user space could be as large as 3GB. In 32-bit Windows, then, system address space typically starts at 0x80000000 but may start as high as 0xC0000000.

In 64-bit Windows the processor architecture itself separates the address space since the mapping to physical addresses through page tables does not support a continuous 64-bit address space but instead defines low and high 47-bit address spaces in which an address can be valid only if the high 17 bits are either all clear or all set. Still, the user and system spaces are the low and high halves: the 128TB user space runs up to and including 0x00007FFF`FFFFFFFF and the 128TB system address space starts at 0xFFFF8000`00000000.

Historically, the Windows kernel divided the system virtual address space at startup into different regions for different uses. One notable region has long been hard-coded: all known versions of 32-bit Windows prepare the top level of the page-table mapping so that 0xC0000000 is the address of an array of page table entries for the whole 4GB of linear address space. Other regions are not so much hard-coded as preset: their start addresses are computed during initialisation and are then kept in internal variables whose values never can change. In this way, for instance, versions 3.10 to 5.0 have the paged pool at 0xE1000000 and versions 3.10 to 5.2 have the system cache at 0xC1000000.

Not until Windows Vista does the 32-bit system address space get allocated to the different uses dynamically. The allocation unit is the amount of address space that is mapped through one page directory entry, thus 4MB in what was once the ordinary page-table mapping but 2MB if the kernel uses the slightly different mapping that allows for Physical Address Extension (PAE).

For each allocation unit of system address space, the type of use, if any, is represented by the MI_SYSTEM_VA_TYPE enumeration. Before version 10.0, the 32-bit kernel’s record of the types for successive allocation units from the start of the system address space upwards is kept as an internal variable named MiSystemVaType. Windows 10 reworked this as the SystemVaType member of an MI_VISIBLE_STATE structure that is in turn the Vs member of an MI_SYSTEM_INFORMATION structure that is the type of an internal variable named MiState.

Microsoft’s names for MI_SYSTEM_VA_TYPE itself and for its possible values are known from public symbol files for the kernel, starting with Windows Vista:

Value (x86) Value (x64) Name Versions Remarks
0x00 0x00 MiVaUnused 6.0 and higher  
0x01 0x01 MiVaSessionSpace 6.0 and higher  
0x02 0x02 MiVaProcessSpace 6.0 and higher  
0x03 0x03 MiVaBootLoaded 6.0 and higher  
0x04 0x04 MiVaPfnDatabase 6.0 and higher  
0x05 0x05 MiVaNonPagedPool 6.0 and higher  
0x06 0x06 MiVaPagedPool 6.0 and higher  
0x07 0x07 MiVaSpecialPool 6.0 only  
MiVaSpecialPoolPaged 6.1 and higher  
0x08 0x08 MiVaSystemCache 6.0 and higher  
0x09 0x09 MiVaSystemPtes 6.0 and higher  
0x0A 0x0A MiVaHal 6.0 and higher  
0x0B 0x0B MiVaSessionGlobalSpace 6.0 and higher  
0x0C 0x0C MiVaDriverImages late 6.0 and higher  
0x0D (6.1 to 1809) 0x0D (6.1 to 1809) MiVaSpecialPoolNonPaged 6.1 to 1809  
0x0E (6.2 to 1709)   MiVaPagedProtoPool 6.2 to 1709  
0x0F (1709);
0x0E (1803 to 1809);
0x0D
0x0E (1709 to 1809);
0x0D
MiVaSystemPtesLarge 1709 and higher previously after MiVaMaximumType
0x10 (1709);
0x0F (1803 to 1809);
0x0E
0x0F (1709 to 1809);
0x0E
MiVaKernelStacks 1709 and higher  
0x0F 0x0F MiVaSecureNonPagedPool 2004 and higher  
0x0C (early 6.0);
0x0D (late 6.0);
0x0E (6.1);
0x0F (6.2 to 1703);
0x11 (1709);
0x10 (1803 to 1809);
0x0F (1903);
0x10
0x0C (early 6.0);
0x0D (late 6.0);
0x0E (6.1 to 1703):
0x10 (1803 to 1809);
0x0F (1903);
0x10
MiVaMaximumType 6.0 and higher  
0x10 (6.3 to 1703) 0x0F (6.3 to 1703) MiVaSystemPtesLarge 6.3 to 1703 next at 0x0F and 0x0E

For most versions, MiVaMaximumType ends the enumeration and acts conventionally not as a defined type but as counting the defined types. Addition of MiVaSystemPtesLarge for Windows 8.1 disturbed this. Whether this was by intention or oversight, it persisted for years: only when the 1709 release of Windows 10 added MiVaKernelStacks was MiVaMaximumType restored to counting all the defined types.