HviGetHypervisorVendorAndMaxFunction

The HviGetHypervisorVendorAndMaxFunction function obtains the output of a hypervisor’s cpuid leaf 0x40000000.

Declaration

VOID HviGetHypervisorVendorAndMaxFunction (HV_VENDOR_AND_MAX_FUNCTION *);

Parameters

The one argument provides the address of a structure that is to receive the cpuid output.

Availability

The HviGetHypervisorVendorAndMaxFunction function is exported by name from the kernel in version 10.0 and higher.

History

The version 6.3 kernel has an inline routine that is coded very similarly to the version 10.0 HviGetHypervisorVendorAndMaxFunction. Public symbol files for the version 6.3 kernel confirm that this earlier kernel has an inline routine that was already named HviGetHypervisorVendorAndMaxFunction and had as its one argument a pointer to an HV_VENDOR_AND_MAX_FUNCTION. That the inline routine in the binary is the same as named in the symbol files which is in turn the origin of the exported function must be all but certain.

Documentation Status

The HviGetHypervisorVendorAndMaxFunction function is not documented.

Behaviour

If a hypervisor is present—see HviIsAnyHypervisorPresent—then the function copies to the given address whatever cpuid leaf 0x40000000 produces in the eax, ebx, ecx and edx registers.

Otherwise, the structure at the given address is zeroed. This, in effect, is the function’s indication of failure.

Simplification

The kernel is largely unconcerned with the Vendor. This is consistent with the Hypervisor Top-Level Functional Specification (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.” The MaxFunction, by contrast, is important to the kernel and surely also to external callers, for assurance that output from a given cpuid leaf is meaningful. The kernel never executes any cpuid leaf beyond 0x40000005 without checking that the leaf is no greater than MaxFunction.

In practice, then, the primary purpose of HviGetHypervisorVendorAndMaxFunction is to get the MaxFunction. Public symbol files for the version 6.3 kernel confirm that Microsoft’s programmers had an inline routine that extracts just the MaxFunction:

UINT32 HvipGetMaxFunction (VOID);

This looks like it exists solely as a convenience. The only coding that looks plausible for it in the binary is that it calls the inline routine HviGetHypervisorVendorAndMaxFunction, returns the MaxFunction and discards the Vendor. This then would be a use (if not the use) that gets HviGetHypervisorVendorAndMaxFunction into the public symbol files. That HvipGetMaxFunction is also in the public symbol files would follow from its use by the inline routine HviGetHardwareFeatures. This coding all continues to Windows 10. That it doesn’t show in the public symbol files for any Windows 10 kernel pretty much proves that even though HviGetHypervisorVendorAndMaxFunction does still get inlined, it is no longer defined in a header, e.g., hvgdk_mini.h, that gets included by the source file (ntsym.c) that’s used for merging type information into the public symbols.