The Amd64 Profile Interface

If the HAL’s initialisation of Hardware Performance Counters establishes that the boot processor is from AMD, has 64-bit architecture, and that its support for performance monitoring counters is not masked from Windows by a Microsoft-compatible hypervisor, the HAL chooses the Amd64 profile interface.

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, these performance events are abstracted as profile sources, represented numerically by a KPROFILE_SOURCE enumeration. Microsoft’s public definition of this enumeration goes only to 0x18 as ProfileMaximum, presumably having covered sources that are anticipated for arbitrary processor architectures. The Amd64 profile interface in the HAL from the original release of Windows 10 continues with many more:

Value Symbol Select
0x00 ProfileTime 0x00030076
0x02 ProfileTotalIssues 0x000300C0
0x06 ProfileBranchInstructions 0x000300C2
0x08 ProfileDcacheMisses 0x00030041
0x09 ProfileIcacheMisses 0x00030081
0x0B ProfileBranchMispredictions 0x000300C3
0x0D ProfileFpInstructions 0x00030FCB
0x14 ProfileIcacheIssues 0x00030080
0x15 ProfileDcacheAccesses 0x00030040
0x19 ProfileFPDispatchedFPUOps 0x00033F00
0x1A ProfileFPDispatchedFPUOpsAddExcludeJunk 0x00030100
0x1B ProfileFPDispatchedFPUOpsMulExcludeJunk 0x00030200
0x1C ProfileFPDispatchedFPUOpsStoreExcludeJunk 0x00030400
0x1D ProfileFPDispatchedFPUOpsAddJunk 0x00030800
0x1E ProfileFPDispatchedFPUOpsMulJunk 0x00031000
0x1F ProfileFPDispatchedFPUOpsStoreJunk 0x00032000
0x20 ProfileFPCyclesNoFPUOpsRetired 0x00030001
0x21 ProfileFPDispatchedFPUOpsWithFastFlag 0x00030002
0x22 ProfileLSSegmentRegisterLoad 0x00037F20
0x23 ProfileLSSegmentRegisterLoadES 0x00030120
0x24 ProfileLSSegmentRegisterLoadCS 0x00030220
0x25 ProfileLSSegmentRegisterLoadSS 0x00030420
0x26 ProfileLSSegmentRegisterLoadDS 0x00030820
0x27 ProfileLSSegmentRegisterLoadFS 0x00031020
0x28 ProfileLSSegmentRegisterLoadGS 0x00032020
0x29 ProfileLSSegmentRegisterLoadHS 0x00034020
0x2A ProfileLSResyncBySelfModifyingCode 0x00030021
0x2B ProfileLSResyncBySnoop 0x00030022
0x2C ProfileLSBuffer2Full 0x00030023
0x2D ProfileLSLockedOperation 0x00030024
0x2E ProfileLSLateCancelOperation 0x00030025
0x2F ProfileLSRetiredCFLUSH 0x00030026
0x30 ProfileLSRetiredCPUID 0x00030027
0x31 ProfileDCAccess 0x00030040
0x32 ProfileDCMiss 0x00030041
0x33 ProfileDCRefillFromL2 0x00031F42
0x34 ProfileDCRefillFromL2Invalid 0x00030142
0x35 ProfileDCRefillFromL2Shared 0x00030242
0x36 ProfileDCRefillFromL2Exclusive 0x00030442
0x37 ProfileDCRefillFromL2Owner 0x00030842
0x38 ProfileDCRefillFromL2Modified 0x00031042
0x39 ProfileDCRefillFromSystem 0x00031F43
0x3A ProfileDCRefillFromSystemInvalid 0x00030143
0x3B ProfileDCRefillFromSystemShared 0x00030243
0x3C ProfileDCRefillFromSystemExclusive 0x00030443
0x3D ProfileDCRefillFromSystemOwner 0x00030843
0x3E ProfileDCRefillFromSystemModified 0x00031043
0x3F ProfileDCRefillCopyBack 0x00031F44
0x40 ProfileDCRefillCopyBackInvalid 0x00030144
0x41 ProfileDCRefillCopyBackShared 0x00030244
0x42 ProfileDCRefillCopyBackExclusive 0x00030444
0x43 ProfileDCRefillCopyBackOwner 0x00030844
0x44 ProfileDCRefillCopyBackModified 0x00031044
0x45 ProfileDCL1DTLBMissL2DTLBHit 0x00030745
0x46 ProfileDCL1DTLBMissL2DTLBMiss 0x00030746
0x47 ProfileDCMisaligndDataReference 0x00030047
0x48 ProfileDCLateCancelOfAccess 0x00030048
0x49 ProfileDCEarlyCancelOfAccess 0x00030049
0x4A ProfileDCOneBitECCError 0x0003034A
0x4B ProfileDCOneBitECCErrorScrubberError 0x0003014A
0x4C ProfileDCOneBitECCErrorPiggybackScrubberError 0x0003024A
0x4D ProfileDCDispatchedPrefetchInstructions 0x0003074B
0x4E ProfileDCDispatchedPrefetchInstructionsLoad 0x0003014B
0x4F ProfileDCDispatchedPrefetchInstructionsStore 0x0003024B
0x50 ProfileDCDispatchedPrefetchInstructionsNTA 0x0003044B
0x51 ProfileBUInternalL2Request 0x00031F7D
0x52 ProfileBUInternalL2RequestICFill 0x0003017D
0x53 ProfileBUInternalL2RequestDCFill 0x0003027D
0x54 ProfileBUInternalL2RequestTLBReload 0x0003047D
0x55 ProfileBUInternalL2RequestTagSnoopRequest 0x0003087D
0x56 ProfileBUInternalL2RequestCancelledRequest 0x0003107D
0x57 ProfileBUFillRequestMissedInL2 0x0003077E
0x58 ProfileBUFillRequestMissedInL2ICFill 0x0003017E
0x59 ProfileBUFillRequestMissedInL2DCFill 0x0003027E
0x5A ProfileBUFillRequestMissedInL2TLBLoad 0x0003047E
0x5B ProfileBUFillIntoL2 0x0003037F
0x5C ProfileBUFillIntoL2DirtyL2Victim 0x0003017F
0x5D ProfileBUFillIntoL2VictimFromL1 0x0003027F
0x5E ProfileICFetch 0x00030080
0x5F ProfileICMiss 0x00030081
0x60 ProfileICRefillFromL2 0x00030082
0x61 ProfileICRefillFromSystem 0x00030083
0x62 ProfileICL1TLBMissL2TLBHit 0x00030084
0x63 ProfileICL1TLBMissL2TLBMiss 0x00030385
0x64 ProfileICResyncBySnoop 0x00030086
0x65 ProfileICInstructionFetchStall 0x00030087
0x66 ProfileICReturnStackHit 0x00030088
0x67 ProfileICReturnStackOverflow 0x00030089
0x68 ProfileFRRetiredx86Instructions 0x000300C0
0x69 ProfileFRRetireduops 0x000300C1
0x6A ProfileFRRetiredBranches 0x000300C2
0x6B ProfileFRRetiredBranchesMispredicted 0x000300C3
0x6C ProfileFRRetiredTakenBranches 0x000300C4
0x6D ProfileFRRetiredTakenBranchesMispredicted 0x000300C5
0x6E ProfileFRRetiredFarControlTransfers 0x000300C6
0x6F ProfileFRRetiredResyncsNonControlTransferBranches 0x000300C7
0x70 ProfileFRRetiredNearReturns 0x000300C8
0x71 ProfileFRRetiredNearReturnsMispredicted 0x000300C9
0x72 ProfileFRRetiredTakenBranchMispredictedByAddressMiscompare 0x000300CA
0x73 ProfileFRRetiredFPUInstructions 0x00030FCB
0x74 ProfileFRRetiredFPUInstructionsx87 0x000301CB
0x75 ProfileFRRetiredFPUInstructionsMMXAnd3DNow 0x000302CB
0x76 ProfileFRRetiredFPUInstructionsPackedSSEAndSSE2 0x000304CB
0x77 ProfileFRRetiredFPUInstructionsScalarSSEAndSSE2 0x000308CB
0x78 ProfileFRRetiredFastpathDoubleOpInstructions 0x000307CC
0x79 ProfileFRRetiredFastpathDoubleOpInstructionsLowOpInPosition0 0x000301CC
0x7A ProfileFRRetiredFastpathDoubleOpInstructionsLowOpInPosition1 0x000302CC
0x7B ProfileFRRetiredFastpathDoubleOpInstructionsLowOpInPosition2 0x000304CC
0x7C ProfileFRInterruptsMaskedCycles 0x000300CD
0x7D ProfileFRInterruptsMaskedWhilePendingCycles 0x000300CE
0x7E ProfileFRTakenHardwareInterrupts 0x000300CF
0x7F ProfileFRNothingToDispatch 0x000300D0
0x80 ProfileFRDispatchStalls 0x000300D1
0x81 ProfileFRDispatchStallsFromBranchAbortToRetire 0x000300D2
0x82 ProfileFRDispatchStallsForSerialization 0x000300D3
0x83 ProfileFRDispachStallsForSegmentLoad 0x000300D4
0x84 ProfileFRDispatchStallsWhenReorderBufferFull 0x000300D5
0x85 ProfileFRDispatchStallsWhenReservationStationsFull 0x000300D6
0x86 ProfileFRDispatchStallsWhenFPUFull 0x000300D7
0x87 ProfileFRDispatchStallsWhenLSFull 0x000300D8
0x88 ProfileFRDispatchStallsWhenWaitingForAllQuiet 0x000300D9
0x89 ProfileFRDispatchStallsWhenFarControlOrResyncBranchPending 0x000300DA
0x8A ProfileFRFPUExceptions 0x00030FDB
0x8B ProfileFRFPUExcpetionsx87ReclassMicroFaults 0x000301DB
0x8C ProfileFRFPUExceptionsSSERetypeMicroFaults 0x000302DB
0x8D ProfileFRFPUExceptionsSSEReclassMicroFaults 0x000304DB
0x8E ProfileFRFPUExceptionsSSEAndx87MicroTraps 0x000308DB
0x8F ProfileFRNumberOfBreakPointsForDR0 0x000300DC
0x90 ProfileFRNumberOfBreakPointsForDR1 0x000300DD
0x91 ProfileFRNumberOfBreakPointsForDR2 0x000300DE
0x92 ProfileFRNumberOfBreakPointsForDR3 0x000300DF
0x93 ProfileNBMemoryControllerPageAccessEvent 0x000307E0
0x94 ProfileNBMemoryControllerPageAccessEventPageHit 0x000301E0
0x95 ProfileNBMemoryControllerPageAccessEventPageMiss 0x000302E0
0x96 ProfileNBMemoryControllerPageAccessEventPageConflict 0x000304E0
0x97 ProfileNBMemoryControllerPageTableOverflow 0x000300E1
0x98 ProfileNBMemoryControllerDRAMCommandSlotsMissed 0x000300E2
0x99 ProfileNBMemoryControllerTurnAround 0x000307E3
0x9A ProfileNBMemoryControllerTurnAroundDIMM 0x000301E3
0x9B ProfileNBMemoryControllerTurnAroundReadToWrite 0x000302E3
0x9C ProfileNBMemoryControllerTurnAroundWriteToRead 0x000304E3
0x9D ProfileNBMemoryControllerBypassCounter 0x00030FE4
0x9E ProfileNBMemoryControllerBypassCounterHighPriority 0x000301E4
0x9F ProfileNBMemoryControllerBypassCounterLowPriority 0x000302E4
0xA0 ProfileNBMemoryControllerBypassCounterDRAMControllerInterface 0x000304E4
0xA1 ProfileNBMemoryControllerBypassCounterDRAMControllerQueue 0x000308E4
0xA2 ProfileNBSizedCommands 0x00037FEB
0xA3 ProfileNBSizedCommandsNonPostWrSzByte 0x000301EB
0xA4 ProfileNBSizedCommandsNonPostWrSzDword 0x000302EB
0xA5 ProfileNBSizedCommandsWrSzByte 0x000304EB
0xA6 ProfileNBSizedCommandsWrSzDword 0x000308EB
0xA7 ProfileNBSizedCommandsRdSzByte 0x000310EB
0xA8 ProfileNBSizedCommandsRdSzDword 0x000320EB
0xA9 ProfileNBSizedCommandsRdModWr 0x000340EB
0xAA ProfileNBProbeResult 0x00030FEC
0xAB ProfileNBProbeResultMiss 0x000301EC
0xAC ProfileNBProbeResultHit 0x000302EC
0xAD ProfileNBProbeResultHitDirtyWithoutMemoryCanceL 0x000304EC
0xAE ProfileNBProbeResultHitDirtyWithMemoryCancel 0x000308EC
0xAF ProfileNBHyperTransportBus0Bandwidth 0x00030FF6
0xB0 ProfileNBHyperTransportBus0BandwidthCommandSent 0x000301F6
0xB1 ProfileNBHyperTransportBus0BandwidthDataSent 0x000302F6
0xB2 ProfileNBHyperTransportBus0BandwidthBufferReleaseSent 0x000304F6
0xB3 ProfileNBHyperTransportBug0BandwidthNopSent 0x000308F6
0xB4 ProfileNBHyperTransportBus1Bandwidth 0x00030FF7
0xB5 ProfileNBHyperTransportBus1BandwidthCommandSent 0x000301F7
0xB6 ProfileNBHyperTransportBus1BandwidthDataSent 0x000302F7
0xB7 ProfileNBHyperTransportBus1BandwidthBufferReleaseSent 0x000304F7
0xB8 ProfileNBHyperTransportBus1BandwidthNopSent 0x000308F7
0xB9 ProfileNBHyperTransportBus2Bandwidth 0x00030FF8
0xBA ProfileNBHyperTransportBus2BandwidthCommandSent 0x000301F8
0xBB ProfileNBHyperTransportBus2BandwidthDataSent 0x000302F8
0xBC ProfileNBHyperTransportBus2BandwidthBufferReleaseSent 0x000304F8
0xBD ProfileNBHyperTransportBus2BandwidthNopSen 0x000308F8
0xBE ProfileBUCleanToDirty 0x00031063
0xBF ProfileBUSharedToDirty 0x00032063

Microsoft’s names for values below 0x19 are known from the enumeration’s C-language definition in WDM.H from the Windows Driver Kit (WDK). Presumably, the values from 0x19 and higher are omitted from that definition because they are processor-specific and the definition is meant to be general. Names for the Amd64-specific profile sources are inferred from descriptive strings in the HAL, which can be obtained even from user mode through ZwQuerySystemInformation when given the information class SystemPerformanceTraceInformation (0x1F) and the secondary information class EventTraceProfileSourceListInformation (0x0D) as the first dword in the information buffer. For the values that Microsoft names in KPROFILE_SOURCE, each name is this descriptive string but with Profile as a prefix. Extrapolation of this relationship to the extra values seems at least a reasonable guess.

To each profile source there corresponds a value that must be loaded into a Performance Event Select Register to, well, select the corresponding performance event. The four Performance Event Select Registers are the model-specific registers 0xC0010000 to 0xC0040000. The counters themselves are the model-specific registers 0xC0010004 to 0xC0010007. Initially, the Amd64 profile interface loads zero into each of the declared Performance Event Select Registers.

Except for ProfileTime, which is handled separately, the Amd64-specific profile sources are the complete set. The generally defined profile sources, numbered below 0x19, that the Amd64 profile interface can support are just those that map to the Amd64-specific profile sources. The mapping is not one-to-one: very many more profile sources are available than are generally defined.

For the sake of completeness, note that the Amd64 profile interface requires 8 bytes per counter per processor. The number of counters per processor is fixed at four, as noted above. The number of processors is not known at the time and anyway can change. The HAL allows for the maximum possible number of registered processors, the meaning of which is a small topic in itself. Failure to get the memory, which is almost unthinkable, causes the HAL_MEMORY_ALLOCATION (0xAC) bug check.