From bd86fb1e633612b447c17ad96f931c76fa2a2fc5 Mon Sep 17 00:00:00 2001 From: Philip Yang Date: Wed, 5 Mar 2025 18:00:08 -0500 Subject: [PATCH] kfdtest: Add KFDQMTest UserQueueBufValidation Create CP queue and SDMA queue should fail with invalid queue ring buffer or ring buffer size. Test unmap or free queue buffers should fail before queue is destroyed. Use child process to test unmap CWSR buffer will evict queue. Signed-off-by: Philip Yang Change-Id: I5dcd51d6b43445d19a986f8b0b82063e20348a5f --- libhsakmt/tests/kfdtest/src/KFDQMTest.cpp | 164 ++++++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/libhsakmt/tests/kfdtest/src/KFDQMTest.cpp b/libhsakmt/tests/kfdtest/src/KFDQMTest.cpp index 7ef4e30b92..467e9fef15 100644 --- a/libhsakmt/tests/kfdtest/src/KFDQMTest.cpp +++ b/libhsakmt/tests/kfdtest/src/KFDQMTest.cpp @@ -22,6 +22,7 @@ */ #include +#include #include #include #include @@ -2648,3 +2649,166 @@ TEST_F(KFDQMTest, GPUDoorbellWrite) { TEST_END } + +TEST_F(KFDQMTest, UserQueueBufValidation) { + TEST_START(TESTPROFILE_RUNALL) + + int defaultGPUNode = m_NodeInfo.HsaDefaultGPUNode(); + ASSERT_GE(defaultGPUNode, 0) << "failed to get default GPU Node"; + + HsaQueueResource QueueResources; + HsaMemoryBuffer *QueueBuf; + HSAKMT_STATUS status; + + memset(&QueueResources, 0, sizeof(QueueResources)); + + // System memory mapping on GPU + QueueBuf = new HsaMemoryBuffer(PAGE_SIZE, defaultGPUNode); + + EXPECT_SUCCESS(hsaKmtCreateQueue(defaultGPUNode, + HSA_QUEUE_COMPUTE, + 100, + HSA_QUEUE_PRIORITY_NORMAL, + QueueBuf->As(), + PAGE_SIZE, + NULL, + &QueueResources)); + EXPECT_SUCCESS(hsaKmtDestroyQueue(QueueResources.QueueId)); + + // CP Queue creation should fail using wrong ring buffer size + EXPECT_SUCCESS(!hsaKmtCreateQueue(defaultGPUNode, + HSA_QUEUE_COMPUTE, + 100, + HSA_QUEUE_PRIORITY_NORMAL, + QueueBuf->As(), + PAGE_SIZE * 2, + NULL, + &QueueResources)); + + // SDMA queue create should fail using wrong ring buffer size + EXPECT_SUCCESS(!hsaKmtCreateQueue(defaultGPUNode, + HSA_QUEUE_SDMA, + 100, + HSA_QUEUE_PRIORITY_NORMAL, + QueueBuf->As(), + PAGE_SIZE * 2, + NULL, + &QueueResources)); + + // CP queue create should fail using NULL ring buffer + EXPECT_SUCCESS(!hsaKmtCreateQueue(defaultGPUNode, + HSA_QUEUE_COMPUTE, + 100, + HSA_QUEUE_PRIORITY_NORMAL, + NULL, + PAGE_SIZE, + NULL, + &QueueResources)); + + // SDMA queue create should fail using NULL ring buffer + EXPECT_SUCCESS(!hsaKmtCreateQueue(defaultGPUNode, + HSA_QUEUE_SDMA, + 100, + HSA_QUEUE_PRIORITY_NORMAL, + NULL, + PAGE_SIZE, + NULL, + &QueueResources)); + + EXPECT_SUCCESS(hsaKmtUnmapMemoryToGPU(QueueBuf->As())); + EXPECT_SUCCESS(hsaKmtFreeMemory(QueueBuf->As(), PAGE_SIZE)); + + // + // This following negative test will evict user queues, must execute in child process, + // because parent process is allowed to create queue to run the remaining tests. + // + pid_t childPid = fork(); + + if (childPid == 0) { /* Child process */ + void *cwsr_addr; + int exit_code = 1; + + TearDown(); + SetUp(); + + // System memory mapping on GPU + QueueBuf = new HsaMemoryBuffer(PAGE_SIZE, defaultGPUNode); + memset(&QueueResources, 0, sizeof(QueueResources)); + + status = hsaKmtCreateQueue(defaultGPUNode, + HSA_QUEUE_COMPUTE, + 100, + HSA_QUEUE_PRIORITY_NORMAL, + QueueBuf->As(), + PAGE_SIZE, + NULL, + &QueueResources); + if (status != HSAKMT_STATUS_SUCCESS) { + LOG() << "create queue failed." << std::endl; + goto free_exit; + } + + // Update queue percentage 0 to set queue inactive in order to get queue info CWSR area + status = hsaKmtUpdateQueue(QueueResources.QueueId, 0, HSA_QUEUE_PRIORITY_NORMAL, + QueueBuf->As(), PAGE_SIZE, NULL); + if (status != HSAKMT_STATUS_SUCCESS) { + LOG() << "update queue failed." << std::endl; + goto err_exit; + } + + HsaQueueInfo QueueInfo; + status = hsaKmtGetQueueInfo(QueueResources.QueueId, &QueueInfo); + if (status != HSAKMT_STATUS_SUCCESS) { + LOG() << "get queue info failed." << std::endl; + goto err_exit; + } + + // unmap CWSR buffer will evict queue before queue is destroyed + cwsr_addr = QueueInfo.UserContextSaveArea; + munmap(cwsr_addr, PAGE_SIZE); + + // unmap and free queue ring buffer should fail before the queue is destroyed + status = hsaKmtFreeMemory(QueueBuf->As(), PAGE_SIZE); + if (status == HSAKMT_STATUS_SUCCESS) { + LOG() << "free queue buf should fail." << std::endl; + goto err_exit; + } + + status = hsaKmtUnmapMemoryToGPU(QueueBuf->As()); + if (status == HSAKMT_STATUS_SUCCESS) { + LOG() << "unmap queue buf should fail." << std::endl; + goto err_exit; + } + + exit_code = 0; + +err_exit: + status = hsaKmtDestroyQueue(QueueResources.QueueId); + if (status != HSAKMT_STATUS_SUCCESS) { + LOG() << "destroy queue failed." << std::endl; + exit_code = 1; + } +free_exit: + status = hsaKmtUnmapMemoryToGPU(QueueBuf->As()); + if (status != HSAKMT_STATUS_SUCCESS) { + LOG() << "unmap queue buf failed." << std::endl; + exit_code = 1; + } + + status = hsaKmtFreeMemory(QueueBuf->As(), PAGE_SIZE); + if (status != HSAKMT_STATUS_SUCCESS) { + LOG() << "free queue buf failed." << std::endl; + exit_code = 1; + } + + exit(exit_code); + } else { + int childStatus; + + waitpid(childPid, &childStatus, 0); + EXPECT_EQ(true, WIFEXITED(childStatus)); + EXPECT_EQ(0, WEXITSTATUS(childStatus)); + } + + TEST_END +}