kfdtest: Add test for invalid signal interrupts

AQL firmware can sometime send invalid signal interrupts with 0 context
ID. This test simulates this by submitting similar events using PM4
packets and measures the performance of signaling a normal event after
that.

Signed-off-by: Felix Kuehling <Felix.Kuehling@amd.com>
Change-Id: I69028dc6dd98a5a93f18daad4efbe1b16b6098f9


[ROCm/ROCR-Runtime commit: e738e57fc4]
Αυτή η υποβολή περιλαμβάνεται σε:
Felix Kuehling
2022-04-21 16:26:36 -04:00
γονέας 3fe8d7912c
υποβολή 94a27af7ad
@@ -295,3 +295,85 @@ TEST_F(KFDEventTest, SignalMultipleEventsWaitForAll) {
TEST_END;
}
/* Send an event interrupt with 0 context ID. Test that KFD handles it
* gracefully and with good performance. On current GPUs and firmware it
* should be handled on a fast path.
*/
TEST_F(KFDEventTest, SignalInvalidEvent) {
TEST_START(TESTPROFILE_RUNALL);
PM4Queue queue;
int defaultGPUNode = m_NodeInfo.HsaDefaultGPUNode();
ASSERT_GE(defaultGPUNode, 0) << "failed to get default GPU Node";
// Create some dummy events, to make the slow path a bit slower
static const unsigned int EVENT_NUMBER = 4094;
HsaEvent* pHsaEvent[EVENT_NUMBER];
for (int i = 0; i < EVENT_NUMBER; i++) {
pHsaEvent[i] = NULL;
ASSERT_SUCCESS(CreateQueueTypeEvent(false, false, defaultGPUNode, &pHsaEvent[i]));
}
ASSERT_SUCCESS(CreateQueueTypeEvent(false, false, defaultGPUNode, &m_pHsaEvent));
ASSERT_NE(0, m_pHsaEvent->EventData.HWData2);
ASSERT_SUCCESS(queue.Create(defaultGPUNode));
static const unsigned int REPS = 2000;
HSAuint64 duration[REPS];
HSAuint64 total = 0, min = 1000000, max = 0;
for (int i = 0; i < REPS; i++) {
// Invalid signal packet
queue.PlacePacket(PM4ReleaseMemoryPacket(m_FamilyId, false, 0, 0));
// Submit valid signal packet
queue.PlacePacket(PM4ReleaseMemoryPacket(m_FamilyId, false,
m_pHsaEvent->EventData.HWData2, m_pHsaEvent->EventId));
HSAuint64 startTime = GetSystemTickCountInMicroSec();
queue.SubmitPacket();
EXPECT_SUCCESS(hsaKmtWaitOnEvent(m_pHsaEvent, g_TestTimeOut));
duration[i] = GetSystemTickCountInMicroSec() - startTime;
total += duration[i];
if (duration[i] < min)
min = duration[i];
if (duration[i] > max)
max = duration[i];
}
double mean = (double)(total - min - max) / (REPS - 2);
double variance = 0;
bool skippedMin = false, skippedMax = false;
HSAuint64 newMin = max, newMax = min;
for (int i = 0; i < REPS; i++) {
if (!skippedMin && duration[i] == min) {
skippedMin = true;
continue;
}
if (!skippedMax && duration[i] == max) {
skippedMax = true;
continue;
}
if (duration[i] < newMin)
newMin = duration[i];
if (duration[i] > newMax)
newMax = duration[i];
double diff = mean - duration[i];
variance += diff*diff;
}
variance /= REPS - 2;
double stdDev = sqrt(variance);
LOG() << "Time for event handling (min/avg/max [std.dev] in us) " << std::dec
<< newMin << "/" << mean << "/" << newMax << " [" << stdDev << "]\n";
EXPECT_SUCCESS(queue.Destroy());
for (int i = 0; i < EVENT_NUMBER; i++)
EXPECT_SUCCESS(hsaKmtDestroyEvent(pHsaEvent[i]));
TEST_END;
}