Geoff Chappell - Software Analyst
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.
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.