Geoff Chappell - Software Analyst
The HV_VENDOR_AND_MAX_FUNCTION structure (formally _HV_VENDOR_AND_MAX_FUNCTION) collects the information that a hypervisor’s cpuid leaf 0x40000000 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 0x40000080.
The HV_VENDOR_AND_MAX_FUNCTION 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 HvVendorAndMaxFunction member of the HV_CPUID_RESULT union.
The kernel provides two ways to get the whole output from cpuid leaf 0x40000000 into a caller-supplied HV_VENDOR_AND_MAX_FUNCTION:
Both are available only in version 10.0 or higher.
The HV_VENDOR_AND_MAX_FUNCTION 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_VENDOR_AND_MAX_FUNCTION 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! Offsets 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_VENDOR_AND_MAX_FUNCTION 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 (32-bit) statically linked library CLFSMGMT.LIB from the Software Development Kit (SDK) for Windows Vista.
UINT8 VendorName ;
The kernel’s primary interest is in MaxFunction. This tells which cpuid leaf is the last in the series that begins at 0x40000000. Even after cpuid leaf 0x40000001 establishes that the hypervisor is Microsoft-compatible, which guarantees the existence of leaves 0x40000002 to 0x40000005, the kernel never queries for cpuid leaf 0x40000006 or higher without checking against what cpuid leaf 0x40000000 produces in eax as MaxFunction.
Microsoft documents that Microsoft’s hypervisors have “Microsoft Hv” as the VendorName, but this is largely irrelevant to the kernel. For the practical matter of determining whether the hypervisor is Microsoft-compatible, the kernel instead relies on cpuid leaf 0x40000001. Note that this is consistent with the TLFS, which advises that “The vendor ID signature should be used only for reporting and diagnostic purposes” and recommends “that software only base compatibility decisions on the interface signature reported through leaf 0x40000001.”
That said, largely irrelevant is not completely irrelevant. Aside from retrieving the whole of the cpuid output on behalf of external callers, as noted above as Access, the kernel interprets the VendorName for callers of HviIsHypervisorVendorMicrosoft.
Beyond reporting, there is one case of the kernel itself giving significance to “Microsoft Hv” as the VendorName. Without it, the exported function HviGetDeviceDebugOptions gets no options. With it, the hypervisor is understood to have a Model-Specific Register (MSR) numbered 0x400000FF. Microsoft does not document the function. The MSR is somehow omitted from what might be thought an extensive list of them in the TLFS.
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) expects that a hypervisor with “Microsoft Hv” as the VendorName from cpuid leaf 0x40000000 has a cpuid leaf 0x40000080 whose output also fits the HV_VENDOR_AND_MAX_FUNCTION. The VendorName “Microsoft VS” signifies that 0x40000080 begins a second series of hypervisor leaves, certainly such that cpuid has a leaf 0x40000081.