Geoff Chappell - Software Analyst
The HV_HYPERVISOR_INTERFACE_INFO structure (formally _HV_HYPERVISOR_INTERFACE_INFO) collects the information that a hypervisor’s cpuid leaf 0x40000001 produces in the eax, ebx, ecx and edx registers. It may also be intended to do the same for a Microsoft hypervisor’s implementation of cpuid leaf 0x40000081.
The HV_HYPERVISOR_INTERFACE_INFO is defined in version 6.3 and higher, having developed from what had been an unnamed structure that versions 6.0 to 6.2 define for the HvInterface member of the HV_CPUID_RESULT union.
The kernel provides two ways to get the whole output from cpuid leaf 0x40000001 into a caller-supplied HV_HYPERVISOR_INTERFACE_INFO:
Both are available only in version 10.0 or higher.
The HV_HYPERVISOR_INTERFACE_INFO structure itself is not documented. 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 (TLFS). 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_HYPERVISOR_INTERFACE_INFO is 0x10 bytes in both 32-bit and 64-bit Windows, as was the unnamed structure that it was developed from. The definition of members has never changed.
Offsets and definitions below are from type information in symbol files for the kernel in Windows 8.1 (only) and for URLMON.DLL in Windows 8.1 through to the 1709 release of Windows 10. 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! Names and definitions for later versions, presently up to and including Version 2004, are checked against type information in a statically linked library named KDHV.LIB which Microsoft distributes with programming samples in the Debugging Tools for Windows.
Also checked are earlier versions for which the HV_HYPERVISOR_INTERFACE_INFO 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.
Offset | Definition |
---|---|
0x00 |
UINT32 Interface; |
0x04 |
UINT32 Reserved1; |
0x08 |
UINT32 Reserved2; |
0x0C |
UINT32 Reserved3; |
The kernel deems the hypervisor as Microsoft-compatible if the Interface is '1#vH’, reading as “Hv#1” when looking at the structure as an array of bytes. The integer value is defined in the HVGDK.H file as the HvMicrosoftHypervisorInterface in an HV_HYPERVISOR_INTERFACE enumeration, as if there may be more even if Microsoft only cares about one.
Aside from retrieving the whole of the cpuid output on behalf of external callers, as noted above as Access, the kernel interprets the Interface for callers of HviIsHypervisorMicrosoftCompatible. Through much of the early history of hypervisors, the only interest that the kernel itself has in the Interface is that a Microsoft-compatible hypervisor is assumed to support cpuid leaves 0x40000002 to 0x40000005 inclusive such that no need exists to check these leaves against the MaxFunction from cpuid leaf 0x40000000.
Starting with the 1607 release of WIndows 10, the kernel knows of a second hypervisor interface. For this, the Interface is 'vnbX', reading from low to high as “Xbnv”. All these versions, both 32-bit and 64-bit, exempt this hypervisor interface from counting as a hypervisor. Specifically, the undocumented kernel export HviIsAnyHypervisorPresent answers in the negative if ecx from cpuid leaf 1 says that a hypervisor is present but eax from cpuid leaf 0x40000001 says the hypervisor that’s present is this one. The 64-bit kernel has an internal routine that checks for this interface once and caches the answer in an internal variable. In some versions the routine is (also) instantiated and its name passes into the public symbol files: HviIsXboxNanovisorPresent, apparently confirming that “Xbnv” stands for Xbox Nanovisor.
Starting with 64-bit Windows 8 and 32-bit WIndows 8.1, the boot manager, boot loader and a changing selection of other software (but not the kernel) know of a cpuid leaf 0x40000081 whose output also fits the HV_HYPERVISOR_INTERFACE_INFO. The expected InterfaceName is '1#SV'. It signifies the existence of a cpuid leaf 0x40000082 whose output is a set of bit flags.