Geoff Chappell - Software Analyst
The HV_X64_ENLIGHTENMENT_INFORMATION structure (formally _HV_X64_ENLIGHTENMENT_INFORMATION) collects the flags that a Microsoft-compatible hypervisor’s cpuid leaf 0x40000004 produces in the eax, ebx, ecx and edx registers.
The HV_X64_ENLIGHTENMENT_INFORMATION is defined for Windows 10. It supersedes the HV_ENLIGHTENMENT_INFORMATION from Windows 8.1, which in turn developed from an unnamed structure for the MsHvEnlightenmentInformation member of the HV_CPUID_RESULT union. Though the new name suggests a specialisation to the x64 processor, the structure is defined identically for both 32-bit and 64-bit Windows. 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 kernel provides two ways to get the whole output from cpuid leaf 0x40000004 into a caller-supplied HV_X64_ENLIGHTENMENT_INFORMATION:
Both are available only in version 10.0 or higher.
The HV_X64_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 does document—or represents as documented—in the Hypervisor Top-Level Functional Specification (TLFS). If the structure 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.
That said, the Specification that is offered today, 12th November 2016, as the most recent version is a PDF that is three years old (version 4.0b, dated August 2013). Flags that were added for Windows 10 were left undocumented in the Specification until version 5.0a, dated February 2017. Better late than never, perhaps, but the reality behind the superficially fine words of the Microsoft Open Specification Promise is that the Hyper-V implementation, and presumably Microsoft’s use of it to Microsoft’s advantage for Microsoft’s purposes, runs ahead of the documentation that Microsoft opens for general use.
As for the HV_X64_ENLIGHTENMENT_INFORMATION as Microsoft’s particular expression of the output from cpuid leaf 0x40000004, disclosure by Microsoft is conspicuously thin. The practical equivalent of a C-language definition is published as type information in symbol files, but in the downloadable packages of public symbols for 32-bit and 64-bit Windows 10, type information for HV_X64_ENLIGHTENMENT_INFORMATION appears only in the symbol files for URLMON.DLL. This is a user-mode DLL that originated as a component of Internet Explorer (and still follows Internet Explorer’s version numbering). Well might you wonder what this DLL has to do with the hypervisor such that its symbol files have type information for this structure but the kernel’s don’t! Symbol files for URLMON.DLL starting with Windows 8, both in packages of Windows symbols and when downloaded from Microsoft’s public symbol server, happen to be private symbols. This surely was an oversight, but however this disclosure came about, Microsoft stopped it for Version 1803. That URLMON.DLL knows of the HV_X64_ENLIGHTENMENT_INFORMATION is because some URLMON.DLL source code has a #include for a header named hvgdk_mini.h. Microsoft is known to use his header for its own programming of the Windows kernel but is not known to have ever made it available for use by programmers in general (let alone by the programmers of competing web browsers).
Type information for the HV_X64_ENLIGHTENMENT_INFORMATION turns out to have been also disclosed in the relatively plain sight of two statically linked libraries. I say relatively plain because even experts tend to overlook that libraries can hold type information. Beware anyway that type information in statically linked libraries does not always match the operating system that the library is supposedly intended for. One of the libraries, named CLFSMGMT.LIB, is among the many that are supplied with the Software Development Kit (SDK) for user-mode programming. Type information for the HV_X64_ENLIGHTENMENT_INFORMATION drops out of this library in Version 2004. The other is more obviously related to hypervisors. It is named KDHV.LIB. Microsoft distributes it among the programming samples in the Debugging Tools for Windows. It has type information for the HV_X64_ENLIGHTENMENT_INFORMATION for all versions of Windows 10 at least to the 2004 release.
The HV_X64_ENLIGHTENMENT_INFORMATION is 0x10 bytes in both 32-bit and 64-bit Windows. Offsets and definitions in the tabulation below are from type information in symbol files for URLMON.DLL before Version 1803 and then in KDHV.LIB.
Offset | Definition | Versions |
---|---|---|
0x00 |
/* bit fields for EAX, see below */ |
10.0 and higher |
0x04 |
UINT32 LongSpinWaitCount; |
10.0 and higher |
0x08 |
UINT32 ReservedEcx; |
10.0 to 1803 |
/* bit fields for ECX, see below */ |
1809 and higher | |
0x0C |
UINT32 ReservedEdx; |
10.0 and higher |
The LongSpinWaitCount is previously in the HV_ENLIGHTENMENT_INFORMATION and in the even earlier anonymous structure as far back as Windows Vista SP1.
What cpuid leaf 0x40000004 produces in eax was evolving as late as the 2004 release of Windows 10:
Mask | Definition | Versions |
---|---|---|
0x00000001 |
UINT32 UseHypercallForAddressSpaceSwitch : 1; |
10.0 and higher |
0x00000002 |
UINT32 UseHypercallForLocalFlush : 1; |
10.0 and higher |
0x00000004 |
UINT32 UseHypercallForRemoteFlush : 1; |
10.0 to 1709 |
UINT32 UseHypercallForRemoteFlushAndLocalFlushEntire : 1; |
1803 and higher | |
0x00000008 |
UINT32 UseApicMsrs : 1; |
10.0 and higher |
0x00000010 |
UINT32 UseHvRegisterForReset : 1; |
10.0 and higher |
0x00000020 |
UINT32 UseRelaxedTiming : 1; |
10.0 and higher |
0x00000040 |
UINT32 UseDmaRemapping : 1; |
10.0 only |
UINT32 UseDmaRemapping_Deprecated : 1; |
1511 and higher | |
0x00000080 |
UINT32 UseInterruptRemapping : 1; |
10.0 only |
UINT32 UseInterruptRemapping_Deprecated : 1; |
1511 and higher | |
0x00000100 |
UINT32 UseX2ApicMsrs : 1; |
10.0 and higher |
0x00000200 |
UINT32 DeprecateAutoEoi : 1; |
10.0 and higher |
0x00000400 |
UINT32 UseSyntheticClusterIpi : 1; |
10.0 and higher |
0x00000800 |
UINT32 UseExProcessorMasks : 1; |
10.0 and higher |
0x00001000 |
UINT32 Nested : 1; |
1511 and higher |
0x00002000 |
UINT32 UseIntForMbecSystemCalls : 1; |
1511 and higher |
0x00004000 |
UINT32 UseVmcsEnlightenments : 1; |
1511 and higher |
0x00008000 |
UINT32 UseSyncedTimeline : 1; |
1703 and higher |
0x00010000 |
UINT32 UseReferencePageForSyncedTimeline : 1; |
1703 to 1709 |
UINT32 Available : 1; |
1803 to 1903 | |
UINT32 CoreSchedulerRequested : 1; |
2004 and higher | |
0x00020000 |
UINT32 UseDirectLocalFlushEntire : 1; |
1803 and higher |
0x00040000 |
UINT32 NoNonArchitecturalCoreSharing : 1; |
1809 and higher |
UINT32 Reserved : 20; |
10.0 only | |
UINT32 Reserved : 17; |
1511 to 1607 | |
UINT32 Reserved : 15; |
1703 to 1709 | |
UINT32 Reserved : 14; |
1803 only | |
UINT32 Reserved : 13; |
1809 and higher |
Bits from 0x00000001 to 0x00000200 have earlier definitions, some with name changes, in the HV_ENLIGHTENMENT_INFORMATION for version 6.3 and even before then in an unnamed structure nested in the HV_CPUID_RESULT. One of these old flags, UseX2ApicMsrs, is documented in the TLFS versions 4.0b through to 5.0c but becomes Reserved in version 6.0b from February 2020.
The UseSyncedTimeline flag was apparently defined too late into 2017 for coverage in the TLFS version 5.0a from February 2017. It is documented in version 5.0c from July 2018 (and was perhaps in 5.0b, no copy of which has yet been found for inspection). By then, its contemporary, UseReferencePageForSyncedTimeline, had already been discontinued. Its slot is marked explicitly as Reserved and remains so, its reuse as CoreSchedulerRequested for Version 2004 apparently coming too early in 2020 for the TLFS version 6.0b which is the latest at Microsoft’s website even in November 2022.
The kernel in the 1809 release of Windows 10 starts using bit fields in the ecx output too:
Mask | Definition | Versions |
---|---|---|
0x0000007F |
UINT32 ImplementedPhysicalAddressBits : 7; |
1809 and higher |
UINT32 ReservedEcx : 25; |
1809 and higher |