HV_PARTITION_PRIVILEGE_MASK

The HV_PARTITION_PRIVILEGE_MASK (formally _HV_PARTITION_PRIVILEGE_MASK) collects the flags that a Microsoft-compatible hypervisor’s cpuid leaf 0x40000003 produces in the eax and ebx registers.

Availability

The HV_PARTITION_PRIVILEGE_MASK is defined for version 6.0 and higher.

Being only part of the output from the corresponding cpuid leaf, the HV_PARTITION_PRIVILEGE_MASK has all along been nested in a structure that has the whole output. Specifically, it is the type of the PartitionPrivileges in:

The distinctiveness of the partition privileges in eax and ebx has long been important enough to Microsoft’s programmers that they have an inline routine that retrieves just the partition privileges rather than the whole feature set that cpuid leaf 0x40000003 produces in eax, ebx, ecx and edx. Public symbol files for the kernel, even as recently as for the 2004 edition of Windows 10, confirm that this inline routine is

VOID HviGetPartitionPrivileges (HV_PARTITION_PRIVILEGE_MASK *);

Documentation Status

The HV_PARTITION_PRIVILEGE_MASK is documented in the Windows Driver Kit (WDK) for Windows 7, which was the last to have documentation included. This kit also provides a C-language definition 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. A search through Google today, 12th November 2016, produces just five results for the name, none from Microsoft.

A C-language definition of HV_PARTITION_PRIVILEGE_MASK is presented in the text of the Hypervisor Top-Level Functional Specification (TLFS). It is adapted, not simply reproduced, from what Microsoft apparently uses in its own programming, but it is helpfully followed by a table of descriptions that are more than just an English rewording of the symbolic names.

That said, the Specification that is offered at Microsoft’s website today, 12th November 2016, as the most recent version is a PDF that is three years old (version 4.0b, dated August 2013). Flags that were added for Windows 10 were left undocumented in the Specification until version 5.0a, dated February 2017. By then, one flag that had been documented was marked instead as Reserved. The reality behind the superficially fine words of the Microsoft Open Specification Promise is that the Hyper-V implementation, and presumably Microsoft’s use of it to Microsoft’s advantage for Microsoft’s purposes, runs ahead of the documentation that Microsoft opens for general use.

Layout

The HV_PARTITION_PRIVILEGE_MASK is 8 bytes in both 32-bit and 64-bit Windows. Formally, the HV_PARTITION_PRIVILEGE_MASK is a union of an 8-byte integer and a structure of 8-byte bit fields. The integer eases the accessing of all flags together:

union {
    UINT64 AsUINT64;
    struct {
        /*  changing bit fields, see below  */
    };
};

Of most interest, of course, are the bit fields. These change as Microsoft’s hypervisor becomes ever more capable. Masks and definitions are from: type information in a statically linked library named CLFSMGMT.LIB for (32-bit) Windows Vista; the published C-language definition for Windows 7; and type information in symbol files for URLMON.DLL in Windows 8 and for the kernel in Windows 8.1 and higher.

Mask Definition Versions
0x00000000`00000001
UINT64 AccessVpRunTimeMsr : 1;
6.0 to 6.3
UINT64 AccessVpRunTimeReg : 1;
10.0 and higher
0x00000000`00000002
UINT64 AccessPartitionReferenceCounter : 1;
6.1 and higher
0x00000000`00000002 (6.0);
0x00000000`00000004
UINT64 AccessSynicMsrs : 1;
6.0 to 6.3
UINT64 AccessSynicRegs : 1;
10.0 and higher
0x00000000`00000008
UINT64 AccessSyntheticTimerMsrs : 1;
6.1 to 6.3
UINT64 AccessSyntheticTimerRegs : 1;
10.0 and higher
0x00000000`00000010
UINT64 AccessApicMsrs : 1;
6.1 to 6.3
UINT64 AccessIntrCtrlRegs : 1;
10.0 and higher
0x00000000`00000020
UINT64 AccessHypercallMsrs : 1;
6.1 and higher
0x00000000`00000040
UINT64 AccessVpIndex : 1;
6.1 and higher
0x00000000`00000080
UINT64 AccessResetMsr : 1;
6.1 to 6.3
UINT64 AccessResetReg : 1;
10.0 and higher
0x00000000`00000100
UINT64 AccessStatsMsr : 1;
6.1 to 6.3
UINT64 AccessStatsReg : 1;
10.0 and higher
0x00000000`00000200
UINT64 AccessPartitionReferenceTsc : 1;
6.1 and higher
0x00000000`00000400
UINT64 AccessGuestIdleMsr : 1;
6.1 to 6.3
UINT64 AccessGuestIdleReg : 1;
10.0 and higher
0x00000000`00000800
UINT64 AccessFrequencyMsrs : 1;
6.2 to 6.3
UINT64 AccessFrequencyRegs : 1;
10.0 and higher
0x00000000`00001000
UINT64 AccessDebugMsrs : 1;
6.2 to 6.3
UINT64 AccessDebugRegs : 1;
10.0 and higher
0x00000000`00002000
UINT64 AccessReenlightenmentControls : 1;
1607 and higher
0x00000000`00004000
UINT64 AccessRootSchedulerReg : 1;
1709 and higher
0x00000000`00008000
UINT64 AccessTscInvariantControls : 1;
2004 and higher
 
UINT64 Reserved1 : 30;
6.0 only
UINT64 Reserved1 : 21;
6.1 only
UINT64 Reserved1 : 19;
6.3 to 1511
UINT64 Reserved1 : 18;
1607 to 1703
UINT64 Reserved1 : 17;
1709 to 1903
UINT64 Reserved1 : 16;
2004 and higher
0x00000001`00000000
UINT64 CreatePartitions : 1;
6.0 and higher
0x00000002`00000000
UINT64 AccessPartitionId : 1;
6.0 and higher
0x00000004`00000000
UINT64 AccessMemoryPool : 1;
6.0 and higher
0x00000008`00000000
UINT64 AdjustMessageBuffers : 1;
6.0 and higher
0x00000010`00000000
UINT64 PostMessages : 1;
6.0 and higher
0x00000020`00000000
UINT64 SignalEvents : 1;
6.0 and higher
0x00000040`00000000
UINT64 CreatePort : 1;
6.0 and higher
0x00000080`00000000
UINT64 ConnectPort : 1;
6.0 and higher
0x00000100`00000000 (6.0)
UINT64 IteratePhysicalHardware : 1;
6.0 only
0x00000200`00000000 (6.0);
0x00000100`00000000
UINT64 AccessStats : 1;
6.0 and higher
 
UINT64 Reserved2 : 22;
6.0 only
UINT64 Reserved2 : 2;
6.1 and higher
0x00000800`00000000
UINT64 Debugging : 1;
6.1 and higher
0x00001000`00000000
UINT64 CpuManagement : 1;
6.1 and higher
0x00002000`00000000
UINT64 ConfigureProfiler : 1;
6.1 and higher
0x00004000`00000000
UINT64 EnableExpandedStackwalking : 1;
6.3 only
UINT64 AccessVpExitTracing : 1;
10.0 and higher
0x00008000`00000000
UINT64 EnableExtendedGvaRangesForFlushVirtualAddressList : 1;
10.0 and higher
0x00010000`00000000
UINT64 AccessVsm : 1;
10.0 and higher
0x00020000`00000000
UINT64 AccessVpRegisters : 1;
10.0 and higher
 
UINT64 UnusedBit : 1;
10.0 and higher
0x00080000`00000000
UINT64 FastHypercallOutput : 1;
10.0 and higher
0x00100000`00000000
UINT64 EnableExtendedHypercalls : 1;
10.0 and higher
0x00200000`00000000
UINT64 StartVirtualProcessor : 1;
10.0 and higher
0x00400000`00000000
UINT64 Isolation : 1;
1809 and higher
 
UINT64 Reserved3 : 18;
6.1 to 6.2
UINT64 Reserved3 : 17;
6.3 only
UINT64 Reserved3 : 10;
10.0 to 1803
UINT64 Reserved3 : 9;
1809 and higher

Comments in the C-language definition from Windows 7 make clear that there has all the while been a logic to which of the 8-byte bit fields are in which dword. The low dword, i.e., the output in eax, provides for “Access to virtual MSRs” but the output in ebx is for “Access to hypercalls”.

Some abbreviations are perhaps not well-known: Vp is Virtual processor; Synic is Synthetic Interrupt Controller.

A CLFSMGMT.LIB that is targeted for Windows 7 does not define AccessGuestIdleMsr or ConfigureProfiler. They may have been defined only shortly before the final build for Windows 7: the library in the Windows 7 SDK was built a month before the Windows 7 kernel (11th June 2009 versus 14th July).

Though ConfigureProfiler dates from Windows 7 and remains defined according to the symbol files, the TLFS version 4.0b dated August 2013 has it in the C-language definition but not among the plain-text descriptions, and all later TLFS versions have it merely as Reserved even in the C-language definition.

The original Windows 10 renamed most of the bits for eax, mostly on the pattern of changing Msr to Reg, but added none. For ebx, by contrast, one flag was repurposed and six were added. The EnableExpandedStackwalking flag had anyway been added only recently (for Windows 8.1). The TLFS version 4.0b had it too in the C-language definition but not among the plain-text descriptions. In Windows 10, it is instead AccessVpExitTracing and again all later TLFS versions denote it as Reserved in the C-language definition.

Of the additions for the original Windows 10, EnableExtendedGvaRangesForFlushVirtualAddressList and FastHypercallOutput similarly have their names replaced by Reserved in the C-language definition and AccessVpRegisters is allowed in the definiton but has no descriptive text even as late as the TLFS version 5.0c dated July 2018. That version is too early for Isolation, which isn’t in the symbol files until the second half-yearly release for 2018, but it is omitted entirely even from the TLFS version 6.0b dated February 2020 which is the latest I have found at Microsoft’s website today, 15th November 2022.

For eax, the AccessReenlightenmentControls flag is in the symbol files for the update from mid-2016 but gets no mention in the TLFS version 5.0a dated February 2017. It scrapes into the C-language definition in the TLFS version 5.0c dated July 2018. It got a plain-text description in time for the TLFS version 6.0b dated February 2020. Even this version says nothing of AccessRootSchedulerReg, which has been in the symbol files since late 2017. The AccessTscInvariantControls flag is new for the first half-yearly release of 2020: when might documentation be expected?