I’ve written a driver to access the Instruction-Based Sampling (or IBS) hardware on newer AMD CPUs.
I need to select an interrupt vector, which I can link to my ISR and also tell the IBS hdwe which vector to generate its interrupt on. The hdwe doesn’t have a predefined vector, although it does have a predefined LVT entry in the local APIC.
Being a newbie to windows drivers, and not wanting to take the time to master the art completely, I came up with a method. I have a four-level loop where I try IoConnectInterrupt with various parameter values. In order, the loop tries:
* exclusive, shared access
* latched, level sensitive
* vectors 50 through FE
* IRQLs 0 through 9.
On my system, the first success is with exclusive, latched, vect 80h, IRQL 0. I’ve also tried testing shared access first, then the result is shared, with the other values the same.
Unfortunately, after enabling IBS interrupts and servicing several of them, the system completely hangs. No mouse, no keyboard, no console update for my client that is monitoring progress.
This code used to work a few years ago, when I had Windows 7 and an earlier AMD processor. Now I’ve got Windows 10 and an AMD Ryzen and I get the hangups. I figure I was just plain lucky that it used to work before.
Anyway, I’m sure there’s a RIGHT way to do this, but I don’t know what that would be. I’m asking for help from you all, at least pointers to stuff I can read.
I’ve got a few inklings…
-
I need to use the PnP manager. Even though the IBS hdwe is not an external device, I have the impression that PnP makes sure everything works in cooperation.
-
Maybe the DIRQL of 0 is wrong, and should be higher?
-
There’s something in the Hal layer that manages interrupt vectors, which I can use.
-
Reserving an interrupt vector for the IBS hdwe in the Registry somehow.
Another bit of info: AMD has a free program called CodeXL that takes IBS samples. Its kernel drivers operate without system hangups, so obviously it’s possible. I’m going through disassembly of the driver code to figure out what it’s doing to get its ISR called. So far, I’ve seen a call to HalAllocateHardwareCounters, which will prevent other (well-behaved) drivers from accessing the IBS hardware. Perhaps this is what I need to do in my own IBS driver too?
Here is the list of relevant imports for the two CodeXL drivers, if that may help you discern what their method is. Curious that IoConnectInterrupt(Ex) is not among them. Do you recognize which of these functions will bind an ISR to an interrups?
DLL Name: ntoskrnl.exe
ExFreePoolWithTag
KeInitializeEvent
KeWaitForSingleObject
DbgPrint
IoAllocateWorkItem
ExRegisterCallback
ObfDereferenceObject
ExCreateCallback
RtlInitUnicodeString
IoQueueWorkItemEx
IoFreeWorkItem
RtlIsNtDdiVersionAvailable
HalDispatchTable
ExUnregisterCallback
KeGetCurrentProcessorNumberEx
IoDeleteDevice
IoDeleteSymbolicLink
IoCreateDevice
ExAllocatePoolWithTag
IoCreateSymbolicLink
KeQueryActiveProcessorCountEx
PsGetCurrentProcessId
PsGetCurrentThreadId
MmIsAddressValid
KeAcquireSpinLockRaiseToDpc
KeRemoveQueueDpc
ExSetTimerResolution
KeSetTimerEx
KeInitializeTimer
KeReleaseSpinLock
KeCancelTimer
KeClearEvent
KeSetEvent
KeInitializeDpc
KeInsertQueueDpc
KeGetProcessorNumberFromIndex
KeSetTargetProcessorDpcEx
MmMapIoSpace
MmUnmapIoSpace
IofCompleteRequest
KeSetImportanceDpc
__C_specific_handler
DLL Name: HAL.dll
KeQueryPerformanceCounter
HalAllocateHardwareCounters
HalFreeHardwareCounters
HalGetBusDataByOffset
DLL Name: ntoskrnl.exe
ObReferenceObjectByHandle
ExAllocatePoolWithTag
KeReleaseGuardedMutex
ExFreePoolWithTag
KeAcquireGuardedMutex
ExEventObjectType
DbgPrint
KeGetCurrentProcessorNumberEx
MmUnlockPages
PsRemoveLoadImageNotifyRoutine
ZwOpenSection
ZwUnmapViewOfSection
MmProbeAndLockPages
PsSetLoadImageNotifyRoutine
IoAllocateMdl
RtlInitUnicodeString
PsRemoveCreateThreadNotifyRoutine
ZwMapViewOfSection
IoFreeMdl
MmMapLockedPagesSpecifyCache
PsSetCreateThreadNotifyRoutine
PsSetCreateProcessNotifyRoutine
ZwClose
IoDeleteDevice
IoDeleteSymbolicLink
IoCreateDevice
IofCompleteRequest
IoCreateSymbolicLink
KeQueryActiveProcessorCountEx
ZwCreateFile
ZwWriteFile
ZwQueryInformationFile
KeSetEvent
ExInterlockedInsertTailList
ExInterlockedRemoveHeadList
PsIsThreadTerminating
PsCreateSystemThread
KeClearEvent
KeWaitForSingleObject
PsTerminateSystemThread
KeSetImportanceDpc
KeInsertQueueDpc
KeInitializeDpc
RtlQueryRegistryValues
KeInitializeEvent
IoSizeofWorkItem
ZwQueryVolumeInformationFile
IoQueryFileDosDeviceName
IoInitializeWorkItem
IoQueueWorkItemEx
ObfReferenceObject
IoUninitializeWorkItem
ZwOpenFile
IoIs32bitProcess
ObfDereferenceObject
KeInitializeGuardedMutex
IoGetStackLimits
RtlVirtualUnwind
MmSystemRangeStart
RtlQueryModuleInformation
MmHighestUserAddress
ProbeForRead
ExpInterlockedFlushSList
KeInitializeApc
ExpInterlockedPopEntrySList
ExpInterlockedPushEntrySList
PsGetCurrentProcessId
KeInsertQueueApc
PsGetThreadId
PsGetThreadProcessId
InitializeSListHead
RtlImageDirectoryEntryToData
RtlIsNtDdiVersionAvailable
KeGetProcessorNumberFromIndex
KeSetTargetProcessorDpcEx
PsGetCurrentProcessWow64Process
MmIsAddressValid
__C_specific_handler
DLL Name: HAL.dll
HalRequestSoftwareInterrupt
KeQueryPerformanceCounter