Geoff Chappell - Software Analyst
The HV_X64_PLATFORM_CAPABILITIES structure (formally _HV_X64_PLATFORM_CAPABILITIES and actually a union) collects the flags that a Microsoft-compatible hypervisor produces in the eax, ebx, ecx and edx registers as output for some unknown leaf of the cpuid instruction.
Or so it seems reasonable to infer. The HV_CPUID_RESULT union that Microsoft defined in the Windows Driver Kit (WDK) for Windows 7 was at least intended at the time to cover all the cpuid leaves that matter to the hypervisor. For Windows 10, according to symbol files (see below), this union got three new members. The older members are in increasing order of cpuid leaf, and had got as far as 0x40000006. The first of the new members has the mystery type HV_X64_PLATFORM_CAPABILITIES. It is followed by members whose types, HV_X64_HYPERVISOR_CPU_MANAGEMENT_FEATURES and HV_HYPERVISOR_SVM_FEATURES, are clearly for cpuid leaves 0x40000007 and 0x40000008. Among cpuid leaves in the hypervisor series that starts 0x40000000, none that the Windows kernel is presently known to execute produces flags that match the HV_X64_PLATFORM_CAPABILITIES definition.
The best guess I have—and beware that I say guess because what I base it on is too thin to call evidence—is that the HV_X64_PLATFORM_CAPABILITIES structure models the output of cpuid leaf 0x40000082. This cpuid leaf can be executed by the kernel in versions 6.1 to 6.3 inclusive and by various boot applications, notably the EFI boot manager and boot loader, starting with 64-bit Windows 8 and 32-bit Windows 8.1, and continuing at least to the 2004 release of Windows 10. Indeed, the latter use has been broadening, such that it is also seen in KDNET.DLL. The kernel and the others each test one of the lowest two bits that cpuid leaf 0x40000082 produces in eax, the kernel for licensing, the others for whether to allow debugging (of themselves and of the kernel). Squint a little and the use of these two bits look a little like matching the AllowRedSignedCode and AllowKernelDebugging that the structure has for its two first bits (see below). In the absence of any other explanation for what HV_X64_PLATFORM_CAPABILITIES can be meant for in the HV_CPUID_RESULT, I latch onto cpuid leaf 0x40000082.
The HV_X64_PLATFORM_CAPABILITIES is not documented. The hypervisor’s cpuid implementation is documented in the Hypervisor Top-Level Functional Specification (TLFS), which Microsoft provides under the Microsoft Open Specification Promise. No known version of this specification, from 2.0 dated May 2012 to 6.0b dated February 2020, mentions cpuid leaf 0x40000082 or any other whose output looks even a little like the HV_X64_PLATFORM_CAPABILITIES.
TLFS versions up to and including 5.0c, dated July 2018, do however have an appendix titled Architectural CPUID which documents the range 0x40000080 to 0x400000FF as “Reserved for use of intercept handlers in the parent partition”. I cannot discount that an earlier TLFS or precursor documented cpuid leaf 0x40000082 and perhaps even that hypervisors with Microsoft as vendor implement 0x40000080 as beginning a second series of hypervisor leaves that closely follow the pattern of the first. A quick search of the Internet turns up headers whose authors define at least something for cpuid leaf 0x400000082 and cite the TLFS (but not which version) at least for reference if not as their actual source. My thinking is that they mean their citation of the TLFS only as an inspiration for their own programmatic definitions, not that their definitions are reproduced from whatever Microsoft presented. After all, among these headers are two different names that suggest very different purposes. That I even bother to point out such apparently unreliable non-Microsoft secondary or tertiary sources is to make the point that cpuid leaf 0x40000082 is about as obscure as things get.
Independently of which cpuid leaf might be modelled by the HV_X64_PLATFORM_CAPABILITIES structure, there is anyway that the structure is about as obscure as things get for undocumented structures. In the downloadable packages of public symbols for 32-bit and 64-bit Windows 10, only the symbol files for URLMON.DLL have type information for HV_X64_PLATFORM_CAPABILITIES. URLMON 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_PLATFORM_CAPABILITIES 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_PLATFORM_CAPABILITIES 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_PLATFORM_CAPABILITIES 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_PLATFORM_CAPABILITIES for all versions of Windows 10 at least to the 2004 release.
The HV_X64_PLATFORM_CAPABILITIES is 0x10 bytes in both 32-bit and 64-bit Windows. Offsets, masks and definitions below are from type information in symbol files for URLMON.DLL before Version 1803 and then in KDHV.DLL.
Formally, the HV_X64_PLATFORM_CAPABILITIES is a 16-byte union of a structure of bit fields for the various flags and of two 64-bit integers for accessing of all flags together:
union { UINT64 AsUINT64 [2]; struct { /* mostly bit fields, see below */ }; };
The structure is essentially four dwords, each for one register as loaded by executing the unknown cpuid leaf:
Offset | Definition |
---|---|
0x00 |
/* bit fields for EAX, see below */ |
0x04 |
/* bit fields for EBX, see below */ |
0x08 |
UINT ReservedEcx; |
0x0C |
/* bit fields for EDX, see below */ |
What counts, of course, are the flags as bit fields.
Except for one bit that is named as if reserved but perhaps had earlier use, the dword for output in eax is fully assigned even for the original Windows 10:
Mask | Definition | Versions |
---|---|---|
0x00000001 |
UINT AllowRedSignedCode : 1; |
6.1 and higher |
0x00000002 |
UINT AllowKernelModeDebugging : 1; |
6.2 and higher |
0x00000004 |
UINT AllowUserModeDebugging : 1; |
10.0 and higher |
0x00000008 |
UINT AllowTelnetServer : 1; |
10.0 and higher |
0x00000010 |
UINT AllowIOPorts : 1; |
10.0 and higher |
0x00000020 |
UINT AllowFullMsrSpace : 1; |
10.0 and higher |
0x00000040 |
UINT AllowPerfCounters : 1; |
10.0 and higher |
0x00000080 |
UINT AllowHost512MB : 1; |
10.0 and higher |
UINT ReservedEax1 : 1; |
10.0 and higher | |
0x00000200 |
UINT AllowRemoteRecovery : 1; |
10.0 and higher |
0x00000400 |
UINT AllowStreaming : 1; |
10.0 and higher |
0x00000800 |
UINT AllowPushDeployment : 1; |
10.0 and higher |
0x00001000 |
UINT AllowPullDeployment : 1; |
10.0 and higher |
0x00002000 |
UINT AllowProfiling : 1; |
10.0 and higher |
0x00004000 |
UINT AllowJsProfiling : 1; |
10.0 and higher |
0x00008000 |
UINT AllowCrashDump : 1; |
10.0 and higher |
0x00010000 |
UINT AllowVsCrashDump : 1; |
10.0 and higher |
0x00020000 |
UINT AllowToolFileIO : 1; |
10.0 and higher |
0x00040000 |
UINT AllowConsoleMgmt : 1; |
10.0 and higher |
0x00080000 |
UINT AllowTracing : 1; |
10.0 and higher |
0x00100000 |
UINT AllowXStudio : 1; |
10.0 and higher |
0x00200000 |
UINT AllowGestureBuilder : 1; |
10.0 and higher |
0x00400000 |
UINT AllowSpeechLab : 1; |
10.0 and higher |
0x00800000 |
UINT AllowSmartglassStudio : 1; |
10.0 and higher |
0x01000000 |
UINT AllowNetworkTools : 1; |
10.0 and higher |
0x02000000 |
UINT AllowTcrTool : 1; |
10.0 and higher |
0x04000000 |
UINT AllowHostNetworkStack : 1; |
10.0 and higher |
0x08000000 |
UINT AllowSystemUpdateTest : 1; |
10.0 and higher |
0x10000000 |
UINT AllowOffChipPerfCtrStreaming : 1; |
10.0 and higher |
0x20000000 |
UINT AllowToolingMemory : 1; |
10.0 and higher |
0x40000000 |
UINT AllowSystemDowngrade : 1; |
10.0 and higher |
0x80000000 |
UINT AllowGreenDiskLicenses : 1; |
10.0 and higher |
That the first two flags are given above for versions before 10.0 is to be understood in the context of guessing that the HV_X64_PLATFORM_CAPABILITIES is the output of cpuid leaf 0x40000082.
The kernel in versions 6.1 to 6.3, both for 32-bit and 64-bit Windows, executes cpuid leaf 0x40000082 solely to check for the 0x00000001 bit. Its sole purpose is to configure the later behaviour of NtQueryLicenceValue, which is of course the implementation of the exported ZwQueryLicenseValue. The specific query that is affected is for Kernel-VMDetection-Private. How this might match the structure’s AllowRedSignedCode is a topic for research. Meanwhile, I observe only that the bit’s name (for signing) isn’t obviously incompatible with the kernel’s use (for licensing).
Interestingly, the kernel’s expectation for availability of cpuid leaf 0x40000082 is only that ecx from cpuid leaf 1 reports that a hypervisor is present and cpuid leaf 0x40000000 identifies the vendor as “Microsoft Hv”. Public symbols name relevant internal routines as ExpIsViridian and ExpIsViridianGuest, apparently called to answer ExpIsVirtualMachinePrivate.
Other software, none yet known to predate version 6.2, executes cpuid leaf 0x40000082 solely to check for the 0x00000002 bit. All this known use is for setting up kernel-mode debugging but not in its whole generality, only for whether to use something named synthetic debugging. Again, more research is required.
What cpuid produces in ebx was still in active development if only briefly after the original Windows 10 but no changes are known beyond Version 1511:
Mask | Definition | Versions |
---|---|---|
0x00000001 |
UINT IsLiveConnected : 1; |
10.0 and higher |
0x00000002 |
UINT IsMteBoosted : 1; |
10.0 and higher |
0x00000004 |
UINT IsQaSlt : 1; |
10.0 and higher |
0x00000008 |
UINT IsStockImage : 1; |
10.0 and higher |
0x00000010 |
UINT IsMsTestLab : 1; |
10.0 and higher |
0x00000020 |
UINT IsRetailDebugger : 1; |
10.0 and higher |
0x00000040 |
UINT IsXvdSort : 1; |
10.0 and higher |
0x00000080 |
UINT IsGreenDebug : 1; |
10.0 and higher |
0x00000100 |
UINT IsHwDevTest : 1; |
10.0 and higher |
0x00000200 |
UINT AllowDiskLicenses : 1; |
1511 and higher |
0x00000400 |
UINT AllowInstrumentation : 1; |
1511 and higher |
0x00000800 |
UINT AllowWifiTester : 1; |
1511 and higher |
0x00001000 |
UINT AllowWifiTesterDFS : 1; |
1511 and higher |
0x00002000 |
UINT IsHwTest : 1; |
1511 and higher |
0x00004000 |
UINT AllowHostOddTest : 1; |
1511 and higher |
0x00008000 |
UINT IsLiveUnrestricted : 1; |
1511 and higher |
0x00010000 |
UINT AllowDiscLicensesWithoutMediaAuth : 1; |
1511 and higher |
UINT ReservedEbx : 23; |
10.0 only | |
UINT ReservedEbx : 15; |
1511 and higher |
Registers ecx and edx look to have been kept as reserved except for the most significant bit:
Mask | Definition | Versions |
---|---|---|
UINT ReservedEdx : 31; |
10.0 and higher | |
0x80000000 |
UINT UseAlternateXvd : 1; |
10.0 and higher |