From 64af8dd9566bb44cf28c3cb56989f6d203c98017 Mon Sep 17 00:00:00 2001 From: Bartosz Dunajski Date: Mon, 3 Jun 2024 16:23:41 +0000 Subject: [PATCH] feature: allocating interrupt support Related-To: NEO-8179 Signed-off-by: Bartosz Dunajski --- .../driver_experimental/public/zex_event.cpp | 21 ++++++++++++++-- .../unit_tests/sources/event/test_event.cpp | 11 +++++++++ shared/source/memory_manager/memory_manager.h | 2 ++ .../os_interface/linux/drm_memory_manager.cpp | 8 +++++++ .../os_interface/linux/drm_memory_manager.h | 3 +++ .../source/os_interface/linux/drm_wrappers.h | 1 + .../source/os_interface/linux/ioctl_helper.h | 3 +++ .../common/mocks/linux/mock_ioctl_helper.h | 14 +++++++++++ .../linux/drm_memory_manager_tests.cpp | 24 +++++++++++++++++++ 9 files changed, 85 insertions(+), 2 deletions(-) diff --git a/level_zero/api/driver_experimental/public/zex_event.cpp b/level_zero/api/driver_experimental/public/zex_event.cpp index c355b952d0..3cca057474 100644 --- a/level_zero/api/driver_experimental/public/zex_event.cpp +++ b/level_zero/api/driver_experimental/public/zex_event.cpp @@ -11,6 +11,7 @@ #include "shared/source/memory_manager/graphics_allocation.h" #include "shared/source/memory_manager/unified_memory_manager.h" +#include "level_zero/core/source/context/context_imp.h" #include "level_zero/core/source/device/device.h" #include "level_zero/core/source/driver/driver_handle.h" #include "level_zero/core/source/event/event.h" @@ -74,11 +75,27 @@ zexCounterBasedEventCreate(ze_context_handle_t hContext, ze_device_handle_t hDev } ZE_APIEXPORT ze_result_t ZE_APICALL zexIntelAllocateNetworkInterrupt(ze_context_handle_t hContext, uint32_t &networkInterruptId) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + auto context = static_cast(L0::Context::fromHandle(hContext)); + + if (!context) { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + + if (!context->getDriverHandle()->getMemoryManager()->allocateInterrupt(networkInterruptId, context->rootDeviceIndices[0])) { + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } + + return ZE_RESULT_SUCCESS; } ZE_APIEXPORT ze_result_t ZE_APICALL zexIntelReleaseNetworkInterrupt(ze_context_handle_t hContext, uint32_t networkInterruptId) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + auto context = static_cast(L0::Context::fromHandle(hContext)); + + if (!context || !context->getDriverHandle()->getMemoryManager()->releaseInterrupt(networkInterruptId, context->rootDeviceIndices[0])) { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + + return ZE_RESULT_SUCCESS; } } // namespace L0 diff --git a/level_zero/core/test/unit_tests/sources/event/test_event.cpp b/level_zero/core/test/unit_tests/sources/event/test_event.cpp index 7e084eb9dc..cc4fb8c06c 100644 --- a/level_zero/core/test/unit_tests/sources/event/test_event.cpp +++ b/level_zero/core/test/unit_tests/sources/event/test_event.cpp @@ -3424,6 +3424,17 @@ HWTEST_F(EventTests, givenStandaloneCbEventAndTbxModeWhenSynchronizingThenHandle context->freeMem(hostAddress); } +HWTEST_F(EventTests, givenOsAgnosticContextWhenAllocatingInterruptThenReturnError) { + uint32_t interruptId = 0; + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, zexIntelAllocateNetworkInterrupt(nullptr, interruptId)); + + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, zexIntelAllocateNetworkInterrupt(context, interruptId)); + + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, zexIntelReleaseNetworkInterrupt(nullptr, interruptId)); + + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, zexIntelReleaseNetworkInterrupt(context, interruptId)); +} + HWTEST_F(EventTests, givenInOrderEventWithHostAllocWhenHostSynchronizeIsCalledThenAllocationIsDonwloadedOnlyAfterEventWasUsedOnGpu) { debugManager.flags.InOrderDuplicatedCounterStorageEnabled.set(1); diff --git a/shared/source/memory_manager/memory_manager.h b/shared/source/memory_manager/memory_manager.h index 79b60c0d7f..2b465b63df 100644 --- a/shared/source/memory_manager/memory_manager.h +++ b/shared/source/memory_manager/memory_manager.h @@ -292,6 +292,8 @@ class MemoryManager { virtual void unMapPhysicalToVirtualMemory(GraphicsAllocation *physicalAllocation, uint64_t gpuRange, size_t bufferSize, OsContext *osContext, uint32_t rootDeviceIndex) = 0; bool allocateBindlessSlot(GraphicsAllocation *allocation); static uint64_t adjustToggleBitFlagForGpuVa(AllocationType inputAllocationType, uint64_t gpuAddress); + virtual bool allocateInterrupt(uint32_t &outHandle, uint32_t rootDeviceIndex) { return false; } + virtual bool releaseInterrupt(uint32_t outHandle, uint32_t rootDeviceIndex) { return false; } protected: bool getAllocationData(AllocationData &allocationData, const AllocationProperties &properties, const void *hostPtr, const StorageInfo &storageInfo); diff --git a/shared/source/os_interface/linux/drm_memory_manager.cpp b/shared/source/os_interface/linux/drm_memory_manager.cpp index ad39b63504..42acff12b2 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager.cpp @@ -2696,4 +2696,12 @@ bool DrmMemoryManager::allowIndirectAllocationsAsPack(uint32_t rootDeviceIndex) return this->getDrm(rootDeviceIndex).isVmBindAvailable(); } +bool DrmMemoryManager::allocateInterrupt(uint32_t &outHandle, uint32_t rootDeviceIndex) { + return getDrm(rootDeviceIndex).getIoctlHelper()->allocateInterrupt(outHandle); +} + +bool DrmMemoryManager::releaseInterrupt(uint32_t outHandle, uint32_t rootDeviceIndex) { + return getDrm(rootDeviceIndex).getIoctlHelper()->releaseInterrupt(outHandle); +} + } // namespace NEO diff --git a/shared/source/os_interface/linux/drm_memory_manager.h b/shared/source/os_interface/linux/drm_memory_manager.h index 86622fd824..fd3d7cc695 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.h +++ b/shared/source/os_interface/linux/drm_memory_manager.h @@ -100,6 +100,9 @@ class DrmMemoryManager : public MemoryManager { MOCKABLE_VIRTUAL void checkUnexpectedGpuPageFault(); + bool allocateInterrupt(uint32_t &outHandle, uint32_t rootDeviceIndex) override; + bool releaseInterrupt(uint32_t outHandle, uint32_t rootDeviceIndex) override; + protected: void registerSharedBoHandleAllocation(DrmAllocation *drmAllocation); BufferObjectHandleWrapper tryToGetBoHandleWrapperWithSharedOwnership(int boHandle); diff --git a/shared/source/os_interface/linux/drm_wrappers.h b/shared/source/os_interface/linux/drm_wrappers.h index 269bf99cb7..6e17252079 100644 --- a/shared/source/os_interface/linux/drm_wrappers.h +++ b/shared/source/os_interface/linux/drm_wrappers.h @@ -229,6 +229,7 @@ struct DrmDebuggerOpen { }; enum class DrmIoctl { + allocateInterrupt, gemExecbuffer2, gemWait, gemUserptr, diff --git a/shared/source/os_interface/linux/ioctl_helper.h b/shared/source/os_interface/linux/ioctl_helper.h index c8f7a433ec..2022172681 100644 --- a/shared/source/os_interface/linux/ioctl_helper.h +++ b/shared/source/os_interface/linux/ioctl_helper.h @@ -201,6 +201,9 @@ class IoctlHelper { virtual void insertEngineToContextParams(ContextParamEngines<> &contextParamEngines, uint32_t engineId, const EngineClassInstance *engineClassInstance, uint32_t tileId, bool hasVirtualEngines) = 0; virtual bool isPreemptionSupported() = 0; + virtual bool allocateInterrupt(uint32_t &outHandle) { return false; } + virtual bool releaseInterrupt(uint32_t handle) { return false; } + protected: Drm &drm; }; diff --git a/shared/test/common/mocks/linux/mock_ioctl_helper.h b/shared/test/common/mocks/linux/mock_ioctl_helper.h index b76d711be6..ab71999313 100644 --- a/shared/test/common/mocks/linux/mock_ioctl_helper.h +++ b/shared/test/common/mocks/linux/mock_ioctl_helper.h @@ -56,6 +56,17 @@ class MockIoctlHelper : public IoctlHelperPrelim20 { return IoctlHelperPrelim20::isWaitBeforeBindRequired(bind); } + bool allocateInterrupt(uint32_t &handle) override { + allocateInterruptCalled++; + return IoctlHelperPrelim20::allocateInterrupt(handle); + } + + bool releaseInterrupt(uint32_t handle) override { + releaseInterruptCalled++; + latestReleaseInterruptHandle = handle; + return IoctlHelperPrelim20::releaseInterrupt(handle); + } + std::unique_ptr createMemoryInfo() override { std::vector regionInfo(3); @@ -77,5 +88,8 @@ class MockIoctlHelper : public IoctlHelperPrelim20 { int drmParamValue = 1234; std::optional failBind{}; std::optional waitBeforeBindRequired{}; + uint32_t allocateInterruptCalled = 0; + uint32_t releaseInterruptCalled = 0; + uint32_t latestReleaseInterruptHandle = InterruptId::notUsed; }; } // namespace NEO diff --git a/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp index 317f145028..bd93644354 100644 --- a/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp @@ -1700,6 +1700,30 @@ TEST_F(DrmMemoryManagerTest, givenRequiresStandard2MBHeapThenStandard2MBHeapIsAc EXPECT_GT(gmmHelper->canonize(memoryManager->getGfxPartition(rootDeviceIndex)->getHeapLimit(HeapIndex::heapStandard2MB)), range); } +TEST_F(DrmMemoryManagerTest, whenCallingAllocateAndReleaseInterruptThenCallIoctlHelper) { + auto mockIoctlHelper = new MockIoctlHelper(*mock); + + auto &drm = static_cast(memoryManager->getDrm(rootDeviceIndex)); + drm.ioctlHelper.reset(mockIoctlHelper); + + uint32_t handle = 0; + + EXPECT_EQ(0u, mockIoctlHelper->allocateInterruptCalled); + EXPECT_EQ(0u, mockIoctlHelper->releaseInterruptCalled); + + memoryManager->allocateInterrupt(handle, rootDeviceIndex); + EXPECT_EQ(1u, mockIoctlHelper->allocateInterruptCalled); + EXPECT_EQ(0u, mockIoctlHelper->releaseInterruptCalled); + + handle = 123; + EXPECT_EQ(InterruptId::notUsed, mockIoctlHelper->latestReleaseInterruptHandle); + + memoryManager->releaseInterrupt(handle, rootDeviceIndex); + EXPECT_EQ(1u, mockIoctlHelper->allocateInterruptCalled); + EXPECT_EQ(1u, mockIoctlHelper->releaseInterruptCalled); + EXPECT_EQ(123u, mockIoctlHelper->latestReleaseInterruptHandle); +} + TEST_F(DrmMemoryManagerTest, GivenShareableEnabledWhenAskedToCreateGraphicsAllocationThenValidAllocationIsReturnedAndStandard64KBHeapIsUsed) { mock->ioctlHelper.reset(new MockIoctlHelper(*mock)); mock->queryMemoryInfo();