|
22 | 22 | */ |
23 | 23 |
|
24 | 24 | #include <sys/time.h> |
| 25 | +#include <sys/mman.h> |
25 | 26 | #include <vector> |
26 | 27 | #include <utility> |
27 | 28 | #include <mutex> |
@@ -2648,3 +2649,166 @@ TEST_F(KFDQMTest, GPUDoorbellWrite) { |
2648 | 2649 |
|
2649 | 2650 | TEST_END |
2650 | 2651 | } |
| 2652 | + |
| 2653 | +TEST_F(KFDQMTest, UserQueueBufValidation) { |
| 2654 | + TEST_START(TESTPROFILE_RUNALL) |
| 2655 | + |
| 2656 | + int defaultGPUNode = m_NodeInfo.HsaDefaultGPUNode(); |
| 2657 | + ASSERT_GE(defaultGPUNode, 0) << "failed to get default GPU Node"; |
| 2658 | + |
| 2659 | + HsaQueueResource QueueResources; |
| 2660 | + HsaMemoryBuffer *QueueBuf; |
| 2661 | + HSAKMT_STATUS status; |
| 2662 | + |
| 2663 | + memset(&QueueResources, 0, sizeof(QueueResources)); |
| 2664 | + |
| 2665 | + // System memory mapping on GPU |
| 2666 | + QueueBuf = new HsaMemoryBuffer(PAGE_SIZE, defaultGPUNode); |
| 2667 | + |
| 2668 | + EXPECT_SUCCESS(hsaKmtCreateQueue(defaultGPUNode, |
| 2669 | + HSA_QUEUE_COMPUTE, |
| 2670 | + 100, |
| 2671 | + HSA_QUEUE_PRIORITY_NORMAL, |
| 2672 | + QueueBuf->As<unsigned int*>(), |
| 2673 | + PAGE_SIZE, |
| 2674 | + NULL, |
| 2675 | + &QueueResources)); |
| 2676 | + EXPECT_SUCCESS(hsaKmtDestroyQueue(QueueResources.QueueId)); |
| 2677 | + |
| 2678 | + // CP Queue creation should fail using wrong ring buffer size |
| 2679 | + EXPECT_SUCCESS(!hsaKmtCreateQueue(defaultGPUNode, |
| 2680 | + HSA_QUEUE_COMPUTE, |
| 2681 | + 100, |
| 2682 | + HSA_QUEUE_PRIORITY_NORMAL, |
| 2683 | + QueueBuf->As<unsigned int*>(), |
| 2684 | + PAGE_SIZE * 2, |
| 2685 | + NULL, |
| 2686 | + &QueueResources)); |
| 2687 | + |
| 2688 | + // SDMA queue create should fail using wrong ring buffer size |
| 2689 | + EXPECT_SUCCESS(!hsaKmtCreateQueue(defaultGPUNode, |
| 2690 | + HSA_QUEUE_SDMA, |
| 2691 | + 100, |
| 2692 | + HSA_QUEUE_PRIORITY_NORMAL, |
| 2693 | + QueueBuf->As<unsigned int*>(), |
| 2694 | + PAGE_SIZE * 2, |
| 2695 | + NULL, |
| 2696 | + &QueueResources)); |
| 2697 | + |
| 2698 | + // CP queue create should fail using NULL ring buffer |
| 2699 | + EXPECT_SUCCESS(!hsaKmtCreateQueue(defaultGPUNode, |
| 2700 | + HSA_QUEUE_COMPUTE, |
| 2701 | + 100, |
| 2702 | + HSA_QUEUE_PRIORITY_NORMAL, |
| 2703 | + NULL, |
| 2704 | + PAGE_SIZE, |
| 2705 | + NULL, |
| 2706 | + &QueueResources)); |
| 2707 | + |
| 2708 | + // SDMA queue create should fail using NULL ring buffer |
| 2709 | + EXPECT_SUCCESS(!hsaKmtCreateQueue(defaultGPUNode, |
| 2710 | + HSA_QUEUE_SDMA, |
| 2711 | + 100, |
| 2712 | + HSA_QUEUE_PRIORITY_NORMAL, |
| 2713 | + NULL, |
| 2714 | + PAGE_SIZE, |
| 2715 | + NULL, |
| 2716 | + &QueueResources)); |
| 2717 | + |
| 2718 | + EXPECT_SUCCESS(hsaKmtUnmapMemoryToGPU(QueueBuf->As<unsigned int*>())); |
| 2719 | + EXPECT_SUCCESS(hsaKmtFreeMemory(QueueBuf->As<unsigned int*>(), PAGE_SIZE)); |
| 2720 | + |
| 2721 | + // |
| 2722 | + // This following negative test will evict user queues, must execute in child process, |
| 2723 | + // because parent process is allowed to create queue to run the remaining tests. |
| 2724 | + // |
| 2725 | + pid_t childPid = fork(); |
| 2726 | + |
| 2727 | + if (childPid == 0) { /* Child process */ |
| 2728 | + void *cwsr_addr; |
| 2729 | + int exit_code = 1; |
| 2730 | + |
| 2731 | + TearDown(); |
| 2732 | + SetUp(); |
| 2733 | + |
| 2734 | + // System memory mapping on GPU |
| 2735 | + QueueBuf = new HsaMemoryBuffer(PAGE_SIZE, defaultGPUNode); |
| 2736 | + memset(&QueueResources, 0, sizeof(QueueResources)); |
| 2737 | + |
| 2738 | + status = hsaKmtCreateQueue(defaultGPUNode, |
| 2739 | + HSA_QUEUE_COMPUTE, |
| 2740 | + 100, |
| 2741 | + HSA_QUEUE_PRIORITY_NORMAL, |
| 2742 | + QueueBuf->As<unsigned int*>(), |
| 2743 | + PAGE_SIZE, |
| 2744 | + NULL, |
| 2745 | + &QueueResources); |
| 2746 | + if (status != HSAKMT_STATUS_SUCCESS) { |
| 2747 | + LOG() << "create queue failed." << std::endl; |
| 2748 | + goto free_exit; |
| 2749 | + } |
| 2750 | + |
| 2751 | + // Update queue percentage 0 to set queue inactive in order to get queue info CWSR area |
| 2752 | + status = hsaKmtUpdateQueue(QueueResources.QueueId, 0, HSA_QUEUE_PRIORITY_NORMAL, |
| 2753 | + QueueBuf->As<unsigned int*>(), PAGE_SIZE, NULL); |
| 2754 | + if (status != HSAKMT_STATUS_SUCCESS) { |
| 2755 | + LOG() << "update queue failed." << std::endl; |
| 2756 | + goto err_exit; |
| 2757 | + } |
| 2758 | + |
| 2759 | + HsaQueueInfo QueueInfo; |
| 2760 | + status = hsaKmtGetQueueInfo(QueueResources.QueueId, &QueueInfo); |
| 2761 | + if (status != HSAKMT_STATUS_SUCCESS) { |
| 2762 | + LOG() << "get queue info failed." << std::endl; |
| 2763 | + goto err_exit; |
| 2764 | + } |
| 2765 | + |
| 2766 | + // unmap CWSR buffer will evict queue before queue is destroyed |
| 2767 | + cwsr_addr = QueueInfo.UserContextSaveArea; |
| 2768 | + munmap(cwsr_addr, PAGE_SIZE); |
| 2769 | + |
| 2770 | + // unmap and free queue ring buffer should fail before the queue is destroyed |
| 2771 | + status = hsaKmtFreeMemory(QueueBuf->As<unsigned int*>(), PAGE_SIZE); |
| 2772 | + if (status == HSAKMT_STATUS_SUCCESS) { |
| 2773 | + LOG() << "free queue buf should fail." << std::endl; |
| 2774 | + goto err_exit; |
| 2775 | + } |
| 2776 | + |
| 2777 | + status = hsaKmtUnmapMemoryToGPU(QueueBuf->As<unsigned int*>()); |
| 2778 | + if (status == HSAKMT_STATUS_SUCCESS) { |
| 2779 | + LOG() << "unmap queue buf should fail." << std::endl; |
| 2780 | + goto err_exit; |
| 2781 | + } |
| 2782 | + |
| 2783 | + exit_code = 0; |
| 2784 | + |
| 2785 | +err_exit: |
| 2786 | + status = hsaKmtDestroyQueue(QueueResources.QueueId); |
| 2787 | + if (status != HSAKMT_STATUS_SUCCESS) { |
| 2788 | + LOG() << "destroy queue failed." << std::endl; |
| 2789 | + exit_code = 1; |
| 2790 | + } |
| 2791 | +free_exit: |
| 2792 | + status = hsaKmtUnmapMemoryToGPU(QueueBuf->As<unsigned int*>()); |
| 2793 | + if (status != HSAKMT_STATUS_SUCCESS) { |
| 2794 | + LOG() << "unmap queue buf failed." << std::endl; |
| 2795 | + exit_code = 1; |
| 2796 | + } |
| 2797 | + |
| 2798 | + status = hsaKmtFreeMemory(QueueBuf->As<unsigned int*>(), PAGE_SIZE); |
| 2799 | + if (status != HSAKMT_STATUS_SUCCESS) { |
| 2800 | + LOG() << "free queue buf failed." << std::endl; |
| 2801 | + exit_code = 1; |
| 2802 | + } |
| 2803 | + |
| 2804 | + exit(exit_code); |
| 2805 | + } else { |
| 2806 | + int childStatus; |
| 2807 | + |
| 2808 | + waitpid(childPid, &childStatus, 0); |
| 2809 | + EXPECT_EQ(true, WIFEXITED(childStatus)); |
| 2810 | + EXPECT_EQ(0, WEXITSTATUS(childStatus)); |
| 2811 | + } |
| 2812 | + |
| 2813 | + TEST_END |
| 2814 | +} |
0 commit comments