Geoff Chappell - Software Analyst
The SYSTEM_HYPERVISOR_QUERY_INFORMATION structure (formally _SYSTEM_HYPERVISOR_QUERY_INFORMATION) is what a successful call to ZwQuerySystemInformation or NtQuerySystemInformation produces in its output buffer when given the information class SystemHypervisorInformation (0x5B).
The SYSTEM_HYPERVISOR_QUERY_INFORMATION and the corresponding information class were introduced for Windows Vista and remain defined at least to the 2004 release of Windows 10.
The SYSTEM_HYPERVISOR_QUERY_INFORMATION structure is not documented.
Microsoft does publish the practical equivalent of a C-language definition as type information in symbol files—not for the kernel, where the structure is prepared, nor even for low-level user-mode DLLs that interpret the structure, but for a handful of higher-level DLLs that might ordinarily be thought very distant from any involvement with the structure. Perhaps only by oversight, but starting as long ago as Windows 8, Microsoft’s downloadable packages of public symbols have included a smattering of private symbol files and these continue to be available through the public symbol server. Precisely which DLLs have the type information varies between versions. COMBASE.DLL is among the more reliable nowadays. Disclosure in symbol files for URLMON.DLL stopped for the 1803 release of Windows 10 but is specially notable because of this DLL’s origins in Internet Explorer and thence for the strong suggestion that Microsoft’s programmers of Internet Explorer had access to more details of low-level Windows programming than Microsoft publishes for wider use (including by the programmers of competing web browsers).
The SYSTEM_HYPERVISOR_QUERY_INFORMATION is 0x10 bytes in 32-bit and 64-bit Windows. Offsets, names and types are from symbol files, as noted above, starting with Windows 8. What’s known for earlier versions is something of a guess from inspection of the kernel.
Offset | Definition | Versions |
---|---|---|
0x00 |
BOOLEAN HypervisorConnected; |
6.0 and higher |
0x01 |
BOOLEAN HypervisorDebuggingEnabled; |
6.3 and higher |
0x02 |
BOOLEAN HypervisorPresent; |
10.0 and higher |
0x03 |
UCHAR HypervisorSchedulerType; |
1903 and higher |
0x01 (6.0 to 6.2); 0x02 (6.3); 0x03 (10.0 to 1809); 0x04 |
UCHAR Spare0 [7]; |
6.0 to 6.2 |
UCHAR Spare0 [6]; |
6.3 only | |
UCHAR Spare0 [5]; |
10.0 to 1809 | |
UCHAR Spare0 [4]; |
1903 and higher | |
0x08 |
ULONGLONG EnabledAddressSpaceEnlightenments; |
6.0 to 6.3 |
ULONGLONG EnabledEnlightenments; |
10.0 and higher |
Microsoft’s assembly-language names for a few of the EnabledEnlightenments are known from headers named KS386.INC and KSAMD64.INC in either or both of Windows Driver Kit (WDK) and the Software Development Kit (SDK) for various Windows versions:
Mask | Name | Versions |
---|---|---|
0x00000001 | HV_MMU_USE_HYPERCALL_FOR_ADDRESS_SWITCH | 6.0 and higher |
0x00000002 | HV_MMU_USE_HYPERCALL_FOR_LOCAL_FLUSH | 6.0 and higher |
0x00000004 | HV_MMU_USE_HYPERCALL_FOR_REMOTE_FLUSH | 6.0 and higher |
0x00000010 | HV_APIC_ENLIGHTENED | 6.2 and higher |
0x00000040 | HV_KE_USE_HYPERCALL_FOR_LONG_SPIN_WAIT | 6.1 and higher |
0x00002000 (6.2 to 10.0); 0x00001000 |
HV_DEPRECATE_AUTO_EOI | 6.2 and higher |
Independently of what names might be learnt from Microsoft, the following quick survey of individual bits is obtained by looking at how the kernel initialises the variable that EnabledEnlightenments is copied from. The kernel determines most from one or another bit in the output from one or another cpuid leaf. These bits are described below by their names in the HV_X64_HYPERVISOR_FEATURES, HV_X64_ENLIGHTENMENT_INFORMATION or HV_X64_HYPERVISOR_CPU_MANAGEMENT_FEATURES structures that are Microsoft’s programmatic representation of the output from cpuid leaves 0x40000003, 0x40000004 and 0x40000007, respectively. For some, there are additional conditions or other subtleties. The aim below is only to sketch what looks most likely as the essential character for Microsoft’s choice of its unknown names for the EnabledEnlightenments. It is all anyway a work in (occasional) progress. In particular, I’m yet to study the additions for Version 1703 and higher, let alone to devise their presentation.
Mask | Leaf | Bit | Versions |
---|---|---|---|
0x00000001 | 0x40000004 | UseHypercallForAddressSpaceSwitch | 6.0 and higher |
0x00000002 | 0x40000004 | UseHypercallForLocalFlush |
6.0 and higher |
0x00000004 | 0x40000004 | UseHypercallForRemoteFlush | 6.0 and higher |
0x00000008 | always set | 6.0 only | |
0x40000003 | CpuManagement | 6.1 to 6.3 | |
0x40000007 | ReservedIdentityBit | 10.0 and higher | |
0x00000010 | 0x40000004 | UseApicMsrs |
6.0 and higher |
0x00000020 | 0x40000004 | UseRelaxedTiming | 6.1 and higher |
0x00000040 | 0x40000004 | positive LongSpinWaitCount | 6.1 and higher |
0x00000080 | 0x40000003 | XmmRegistersForFastHypercallAvailable | 6.1 and higher (x64) |
0x00000100 | 0x40000003 | both AccessPartitionReferenceCounter and AccessPartitionReferenceTsc |
6.1 and higher |
0x00000200 | 0x40000003 | GuestIdleAvailable | 6.1 and higher |
0x00000400 | 0x40000003 | CpuManagement | 6.2 to 6.3 |
0x40000007 | ProcessorPowerManagement | 10.0 and higher | |
0x00000800 | 0x40000003 | either CpuManagement or NumaDistanceQueryAvailable |
6.2 to 6.3 |
0x40000003 | NumaDistanceQueryAvailable | 10.0 and higher | |
0x00001000 | 0x40000004 | UseInterruptRemapping | 6.2 to 10.0 |
0x00002000 (6.2 to 10.0); 0x00001000 |
0x40000004 | DeprecateAutoEoi | 6.2 and higher |
0x00004000 (6.2 to 10.0); 0x00002000 |
0x40000003 | GuestCrashRegsAvailable | 6.2 and higher |
0x00008000 (6.2 to 10.0); 0x00004000 |
0x40000004 | UseSyntheticClusterIpi | 10.0 and higher |
0x00010000 (6.2 to 10.0); 0x00008000 |
0x40000003 | StartVirtualProcessor | 10.0 and higher |
0x00020000 (6.2 to 10.0); 0x00010000 |
0x40000007 | ReservedIdentityBit | 10.0 and higher |
0x00040000 (6.2 to 10.0); 0x00020000 |
0x40000007 | MwaitIdleStates | 10.0 and higher |
0x00080000 (6.2 to 10.0); 0x00040000 |
0x40000007 | LogicalProcessorIdling | 10.0 and higher |
0x00080000 | 0x40000004 | UseIntForMbecSystemCalls | 1511 and higher (x64) |
0x00100000 | 0x40000003 | HypercallMsrLockAvailable | 1511 and higher |
0x00200000 | extended capability |
0x00000002 bit | 1703 and higher |
0x00400000 | extended capability |
0x00000004 bit | 1709 and higher |
0x00800000 | 1803 and higher | ||
0x01000000 | |||
0x02000000 | |||
0x04000000 | 0x40000003 | CrossVtlFlushAvailable | 1903 and higher |
0x08000000 | extended capability |
0x00000080 bit | 2004 and higher |
The LongSpinWaitCount is known to be declared as an unsigned integer, but for the purpose of determining enlightenments it is reinterpreted as signed. A wait count of 0x80000000 or higher, not that anyone would want it, would be ignored for being negative.
The 0x04000000 enlightenment is shown above as corresponding to the CrossVtlFlushAvailable feature, but this is for brevity. The enlightenment is reported for 32-bit Windows, but the feature relates to the secure kernel and is meaningful only for 64-bit Windows. The cross-VTL flush is done only as a fast hypercall, and so although the 0x04000000 englightenment requires this feature, it also requires XmmRegistersForFastHypercallAvailable.