Hardware Performance Counters

The HAL handles the processor-specific work of using hardware performance counters to support the profiling of execution. What the HAL can do about profiling the processors depends, unsurprisingly, on what types of processor are present. Perhaps less unsurprisingly, it is assessed from the boot processor only. The HAL in the original release of Windows 10 distinguishes three profile interfaces:

Names are surmised from symbol files for the HAL. The name Emon appears to come from Intel’s manuals, apparently standing for Event Monitoring.

Processor Identification

For anything more sophisticated than the Default interface, the HAL must identify the boot processor as suitable. It doesn’t even try unless a rough inspection of processor features done earlier has shown that performance monitoring is at least a possibility.

Rough Feature Bits

Much of the broad picture simply uses CPU identification that has already been made by the kernel and left in the KPRCB. Presumably as a remnant of age-old code, the HAL still checks that the cpuid instruction is available (as recorded in the CpuID). For the 64-bit HAL, this is enough. The 32-bit HAL, however, recognises the support as possible for only two vendors (as identified by the CpuVendor). If the vendor is Intel, then it is enough that the family (from the CpuType) is either 6 or 15. If the vendor is AMD, then cpuid leaf 0x80000000 must indicate support for cpuid leaf 0x80000001, which must in turn set the 0x20000000 bit in edx. (Intel’s manual would have it that this bit means “Intel® 64 Architecture available if 1.”)

Interface Selection

The first part to selecting the profile interface is to know the vendor string from cpuid leaf 0. If this is AuthenticAMD, then Amd64 profiling is tentatively indicated, save only for what a hypervisor may have to say. Processors whose vendor string is GenuineIntel are tentatively recognised as having Emon profiling if the highest cpuid leaf, as returned in eax for cpuid leaf 0, is at least 10 and the result of executing cpuid leaf 10 satisfies all the following:

Neither of these identifications, for the Amd64 or Emon profiling interface, means anything if a Microsoft-compatible hypervisor is present and execution of cpuid leaf 0x40000003 produces a clear PerformanceMonitorsAvailable bit (2) in edx. This is taken to mean that whatever the underlying features of the processor, they are masked by the hypervisor. Profiling is then defaulted just as if the processor had been unrecognised. (The test for Microsoft-compatibility is the same as the kernel has for its exported HviIsHypervisorMicrosoftCompatible function. For the hypervisor features that are the output of cpuid leaf 0x40000003, see the HV_HYPERVISOR_FEATURES structure.)

Profile Interfaces

The three profile interfaces provide independently of one another for their own initialisation and subsequent use. However, many points to this are done in very much the same way so that much can usefully be said in general.

Profile Sources

For the purpose of interaction with the kernel, and indeed all the way to user mode through such functions as NtCreateProfile and NtCreateProfileEx, whatever it is that a hardware performance counter might count is abstracted as a profile source, represented numerically by a KPROFILE_SOURCE enumeration. This is defined in NTDDK.H in the Device Driver Kit (DDK) from as far back as Windows NT 3.51, moving to WDM.H in later kits, but without ever changing. The point to reproducing such a well-known enumeration here is to show which profile sources are supported by which profile interfaces:

Value Symbol Profile Interface
0x00 ProfileTime Default
0x01 ProfileAlignmentFixup  
0x02 ProfileTotalIssues Emon
0x03 ProfilePipelineDry  
0x04 ProfileLoadInstructions  
0x05 ProfilePipelineFrozen  
0x06 ProfileBranchInstructions Emon
0x07 ProfileTotalNonissues  
0x08 ProfileDcacheMisses Amd64
0x09 ProfileIcacheMisses Amd64
0x0A ProfileCacheMisses Emon
0x0B ProfileBranchMispredictions Emon
0x0C ProfileStoreInstructions  
0x0D ProfileFpInstructions Amd64
0x0E ProfileIntegerInstructions  
0x0F Profile2Issue  
0x10 Profile3Issue  
0x11 Profile4Issue  
0x12 ProfileSpecialInstructions  
0x13 ProfileTotalCycles Emon
0x14 ProfileIcacheIssues Amd64
0x15 ProfileDcacheAccesses Amd64
0x16 ProfileMemoryBarrierCycles  
0x17 ProfileLoadLinkedIssues  
0x18 ProfileMaximum  
higher processor-specific profile sources Emon