Geoff Chappell - Software Analyst
The SYSTEM_HYPERVISOR_DETAIL_INFORMATION structure is what a successful call to ZwQuerySystemInformation or NtQuerySystemInformation produces in its output buffer when given the information class SystemHypervisorDetailInformation (0x9F). It collects the output from executing the cpuid instruction repeatedly for a set of hypervisor leaves, i.e., starting at 0x40000000.
The SYSTEM_HYPERVISOR_DETAIL_INFORMATION and the corresponding information class are new for Windows 10.
The SYSTEM_HYPERVISOR_DETAIL_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_DETAIL_INFORMATION is 0x70 bytes in both 32-bit and 64-bit Windows 10 at least to the 2004 release. Offsets, names and types are from symbol files, as noted above.
Offset | Definition | Leaf | Interpretation |
---|---|---|---|
0x00 |
HV_DETAILS HvVendorAndMaxFunction; |
0x40000000 | HV_VENDOR_AND_MAX_FUNCTION |
0x10 |
HV_DETAILS HypervisorInterface; |
0x40000001 | HV_HYPERVISOR_INTERFACE_INFO |
0x20 |
HV_DETAILS HypervisorVersion; |
0x40000002 | HV_HYPERVISOR_VERSION_INFO |
0x30 |
HV_DETAILS HvFeatures; |
0x40000003 | HV_X64_HYPERVISOR_FEATURES |
0x40 |
HV_DETAILS HwFeatures; |
0x40000006 | HV_X64_HYPERVISOR_HARDWARE_FEATURES |
0x50 |
HV_DETAILS EnlightenmentInfo; |
0x40000004 | HV_X64_ENLIGHTENMENT_INFORMATION |
0x60 |
HV_DETAILS ImplementationLimits; |
0x40000005 | HV_IMPLEMENTATION_LIMITS |
Each member is an HV_DETAILS structure. This is a generic container for the cpuid instruction’s output in the eax, ebx, ecx and edx registers, apparently only used when the input in eax selects a cpuid leaf from the hypervisor series which begins at 0x40000000. Microsoft defines more specific containers, presumably for its internal use. These and the corresponding cpuid leaves are noted above in the Leaf and Interpretation columns.
The SYSTEM_HYPERVISOR_DETAIL_INFORMATION members are not quite arranged in increasing order of the corresponding cpuid leaves. What may have happened is that leaves 0x40000004 and 0x40000005 were initially omitted because an interpretation of their output was already exposed in other structures that are the output for older information classes: SYSTEM_HYPERVISOR_QUERY_INFORMATION and SYSTEM_HYPERVISOR_PROCESSOR_COUNT_INFORMATION, respectively. Then perhaps the raw output from these cpuid leaves was tacked on. If so, the present layout was settled for the original release of Windows 10. It has not been extended to report on cpuid leaves that have become meaningful to the kernel since the original Windows 10.
A hypervisor’s presence is established by a set 0x80000000 bit in ecx from cpuid leaf 1. This is taken as implying that cpuid leaves 0x40000000 and 0x40000001 are implemented. If cpuid leaf 0x40000001 produces 0x31237648 in ebx, the hypervisor is deemed Microsoft-compatible. This in turn implies that cpuid leaves 0x40000002 to 0x40000005 are implemented. Implementation of cpuid leaf 0x40000006 is inferred only if eax from cpuid leaf 0x40000000 is at least 0x40000006. For any cpuid leaf that is in this way deemed unimplemented, the corresponding HV_DETAILS is zeroed.