Geoff Chappell - Software Analyst
The HV_ENLIGHTENMENT_INFORMATION structure collects the flags that a Microsoft-compatible hypervisor’s cpuid leaf 0x40000004 produces in the eax, ebx, ecx and edx registers.
The HV_ENLIGHTENMENT_INFORMATION is defined in version 6.3, having developed from the unnamed structure that versions 6.0 to 6.2 define for the MsHvEnlightenmentInformation member of the HV_CPUID_RESULT union. It is superseded in version 10.0 by the HV_X64_ENLIGHTENMENT_INFORMATION. Version 10.0 also defines an HV_ARM64_ENLIGHTENMENT_INFORMATION, but what this represents on the applicable processors lies (far) outside the scope of this article.
It is here thought that HV_ENLIGHTENMENT_INFORMATION is retained in version 10.0 and higher as a macro for the appropriate processor-specific structure: HV_X64_ENLIGHTENMENT_INFORMATION when building for the x86 and x64 processors; but HV_ARM64_ENLIGHTENMENT_INFORMATION for the 32-bit and 64-bit ARM processors.
The HV_ENLIGHTENMENT_INFORMATION is not documented. Some of its members, having previously been defined in the HV_CPUID_RESULT, are documented in the Windows Driver Kit (WDK) for Windows 7, which also provided a C-language definition (of the structure’s unnamed ancestor) in the HVGDK.H header file. Except that documentation continued to a separately downloadable package for merging into Visual Studio 2012, later kits have neither the documentation nor the header.
The structure anyway repackages material that Microsoft documents in the Hypervisor Top-Level Functional Specification. If it or its members’ previous definitions have become undocumented, it may be just that Microsoft regards the structure as no more than a convenience for Microsoft’s own programming in the loader and kernel, if not in the hypervisor itself.
The HV_ENLIGHTENMENT_INFORMATION is 0x10 bytes in both 32-bit and 64-bit Windows, as was the unnamed structure that it was developed from. Offsets and definitions below are from type information in symbol files for URLMON.DLL in Windows 8.1. Well might you wonder what URLMON.DLL has to do with the hypervisor such that its symbol files have type information for this structure but the kernel’s don’t!
These tables also survey the structure’s development in earlier versions when it was not yet a named structure. Offsets, names and types are from (in roughly decreasing order of forensic quality): the C-language definition of the HV_CPUID_RESULT in the WDK for Windows 7; type information in symbol files for URLMON.DLL for Windows 8; and type information in the statically linked library CLFSMGMT.LIB from the Software Development Kit (SDK) for Windows Vista. Some development within version 6.0 is inferred from inspection of binaries: late 6.0 starts with Windows Vista SP1.
Offset | Definition | Versions |
---|---|---|
0x00 |
/* bit fields for EAX, see below */ |
6.0 to 6.3 |
0x04 |
UINT32 ReservedEbx; |
early 6.0 only |
UINT32 LongSpinWaitCount; |
late 6.0 to 6.3 | |
0x08 |
UINT32 ReservedEcx; |
6.0 to 6.3 |
0x0C |
UINT32 ReservedEdx; |
6.0 to 6.3 |
Version numbers before 6.3 refer to prior appearance in the MsHvEnlightenmentInformation member of the HV_CPUID_RESULT.
Though no definition of LongSpinWaitCount is known before Windows 7, one surely did exist since the kernel’s interpretation of the output in ebx starts at Windows Vista SP1.
Mask | Definition | Versions |
---|---|---|
0x00000001 |
UINT32 UseHypercallForAddressSpaceSwitch : 1; |
6.0 to 6.3 |
0x00000002 |
UINT32 UseHypercallForLocalFlush : 1; |
6.0 to 6.3 |
0x00000004 |
UINT32 UseHypercallForRemoteFlush : 1; |
6.0 to 6.3 |
0x00000008 |
UINT32 UseMsrForApicAccess : 1; |
early 6.0 only |
UINT32 UseApicMsrs : 1; |
late 6.0 to 6.3 | |
0x00000010 |
UINT32 UseMsrForReset : 1; |
late 6.0 to 6.3 |
0x00000020 |
UINT32 UseRelaxedTiming : 1; |
late 6.0 to 6.3 |
0x00000040 |
UINT32 UseDmaRemapping : 1; |
6.2 to 6.3 |
0x00000080 |
UINT32 UseInterruptRemapping : 1; |
6.2 to 6.3 |
0x00000100 |
UINT32 UseX2ApicMsrs : 1; |
6.2 to 6.3 |
0x00000200 |
UINT32 DeprecateAutoEoi : 1; |
6.2 to 6.3 |
UINT32 Reserved : 28; |
6.0 only | |
UINT32 Reserved : 26; |
6.1 only | |
UINT32 Reserved : 22; |
6.2 to 6.3 |
When the 0x00000008 bit changed name is not known with the certainty of formal definition or even of type information, but inspection of the kernel and HAL binaries shows that interpretation of cpuid leaf 0x40000004 was extended for Windows Vista SP1 (see next paragraph) and it is here thought more likely that the name changes will have been done then rather than separately for Windows 7.
Though no definition is known for any bit beyond 0x00000008 before Windows 7, the HAL and the kernel in Windows Vista SP1 use the 0x00000010 and 0x00000020 bits, respectively, for the same purposes as do later versions.
All flags that are defined for version 6.3 continue to version 10.0 in the HV_X64_ENLIGHTENMENT_INFORMATION, but UseMsrForReset changes name to UseHvRegisterForReset.