From 4391ad21bb3988d6be6d85018c74cbc195c58e16 Mon Sep 17 00:00:00 2001 From: Jaime Arteaga Date: Thu, 10 Nov 2022 02:57:51 +0000 Subject: [PATCH] Fail when handle cannot be obtain for an allocation If a handle cannot be obtained, like PRIME_HANDLE_TO_FD, then properly check for the error and propagate it upwards. Signed-off-by: Jaime Arteaga --- .../core/source/context/context_imp.cpp | 59 +- level_zero/core/source/context/context_imp.h | 4 + .../core/source/driver/driver_handle_imp.cpp | 14 +- level_zero/core/source/helpers/CMakeLists.txt | 2 - .../source/helpers/allocation_extensions.cpp | 47 -- .../source/helpers/allocation_extensions.h | 18 - .../unit_tests/sources/memory/CMakeLists.txt | 1 + .../sources/memory/linux/CMakeLists.txt | 12 + .../memory/linux/test_memory_linux.cpp | 706 ++++++++++++++++++ .../unit_tests/sources/memory/test_memory.cpp | 48 ++ opencl/source/mem_obj/mem_obj.cpp | 2 +- .../os_interface/windows/wddm20_tests.cpp | 9 +- ..._manager_allocate_in_device_pool_tests.cpp | 8 +- .../memory_manager/graphics_allocation.h | 6 +- .../os_interface/linux/drm_allocation.cpp | 26 +- .../os_interface/linux/drm_allocation.h | 12 +- .../os_interface/linux/drm_memory_manager.cpp | 11 +- .../os_interface/windows/wddm_allocation.h | 5 +- .../windows/wddm_memory_manager.cpp | 6 +- .../mocks/linux/mock_drm_memory_manager.h | 9 + .../graphics_allocation_tests.cpp | 4 +- ...m_memory_manager_localmem_prelim_tests.cpp | 40 + .../linux/drm_memory_manager_tests.cpp | 73 +- 23 files changed, 1007 insertions(+), 115 deletions(-) delete mode 100644 level_zero/core/source/helpers/allocation_extensions.cpp delete mode 100644 level_zero/core/source/helpers/allocation_extensions.h create mode 100644 level_zero/core/test/unit_tests/sources/memory/linux/CMakeLists.txt create mode 100644 level_zero/core/test/unit_tests/sources/memory/linux/test_memory_linux.cpp diff --git a/level_zero/core/source/context/context_imp.cpp b/level_zero/core/source/context/context_imp.cpp index dc772848eb..775ef485fb 100644 --- a/level_zero/core/source/context/context_imp.cpp +++ b/level_zero/core/source/context/context_imp.cpp @@ -16,7 +16,6 @@ #include "level_zero/core/source/device/device_imp.h" #include "level_zero/core/source/driver/driver_handle_imp.h" #include "level_zero/core/source/event/event.h" -#include "level_zero/core/source/helpers/allocation_extensions.h" #include "level_zero/core/source/helpers/properties_parser.h" #include "level_zero/core/source/hw_helpers/l0_hw_helper.h" #include "level_zero/core/source/image/image.h" @@ -438,7 +437,11 @@ ze_result_t ContextImp::getIpcMemHandle(const void *ptr, ze_ipc_mem_handle_t *pIpcHandle) { NEO::SvmAllocationData *allocData = this->driverHandle->svmAllocsManager->getSVMAlloc(ptr); if (allocData) { - uint64_t handle = allocData->gpuAllocations.getDefaultGraphicsAllocation()->peekInternalHandle(this->driverHandle->getMemoryManager()); + uint64_t handle = 0; + int ret = allocData->gpuAllocations.getDefaultGraphicsAllocation()->peekInternalHandle(this->driverHandle->getMemoryManager(), handle); + if (ret < 0) { + return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } memcpy_s(reinterpret_cast(pIpcHandle->data), sizeof(ze_ipc_mem_handle_t), &handle, @@ -467,11 +470,15 @@ ze_result_t ContextImp::getIpcMemHandles(const void *ptr, } for (uint32_t i = 0; i < *numIpcHandles; i++) { - int handle = static_cast(allocData->gpuAllocations.getDefaultGraphicsAllocation()->peekInternalHandle(this->driverHandle->getMemoryManager(), i)); + uint64_t handle = 0; + int ret = allocData->gpuAllocations.getDefaultGraphicsAllocation()->peekInternalHandle(this->driverHandle->getMemoryManager(), i, handle); + if (ret < 0) { + return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } memcpy_s(reinterpret_cast(pIpcHandles[i].data), sizeof(ze_ipc_mem_handle_t), &handle, - sizeof(handle)); + sizeof(int)); } return ZE_RESULT_SUCCESS; @@ -540,7 +547,11 @@ ze_result_t EventPoolImp::getIpcHandle(ze_ipc_event_pool_handle_t *pIpcHandle) { return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } - uint64_t handle = this->eventPoolAllocations->getDefaultGraphicsAllocation()->peekInternalHandle(this->context->getDriverHandle()->getMemoryManager()); + uint64_t handle = 0; + int ret = this->eventPoolAllocations->getDefaultGraphicsAllocation()->peekInternalHandle(this->context->getDriverHandle()->getMemoryManager(), handle); + if (ret < 0) { + return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } memcpy_s(pIpcHandle->data, sizeof(int), &handle, sizeof(int)); @@ -630,6 +641,44 @@ ze_result_t ContextImp::openEventPoolIpcHandle(const ze_ipc_event_pool_handle_t return ZE_RESULT_SUCCESS; } +ze_result_t ContextImp::handleAllocationExtensions(NEO::GraphicsAllocation *alloc, ze_memory_type_t type, void *pNext, struct DriverHandleImp *driverHandle) { + if (pNext != nullptr) { + ze_base_properties_t *extendedProperties = + reinterpret_cast(pNext); + if (extendedProperties->stype == ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_FD) { + ze_external_memory_export_fd_t *extendedMemoryExportProperties = + reinterpret_cast(extendedProperties); + if (extendedMemoryExportProperties->flags & ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_FD) { + return ZE_RESULT_ERROR_UNSUPPORTED_ENUMERATION; + } + if (type != ZE_MEMORY_TYPE_DEVICE) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + uint64_t handle = 0; + int ret = alloc->peekInternalHandle(driverHandle->getMemoryManager(), handle); + if (ret < 0) { + return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + extendedMemoryExportProperties->fd = static_cast(handle); + } else if (extendedProperties->stype == ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_WIN32) { + ze_external_memory_export_win32_handle_t *exportStructure = reinterpret_cast(extendedProperties); + if (exportStructure->flags != ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32) { + return ZE_RESULT_ERROR_UNSUPPORTED_ENUMERATION; + } + uint64_t handle = 0; + int ret = alloc->peekInternalHandle(driverHandle->getMemoryManager(), handle); + if (ret < 0) { + return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + exportStructure->handle = reinterpret_cast(handle); + } else { + return ZE_RESULT_ERROR_INVALID_ENUMERATION; + } + } + + return ZE_RESULT_SUCCESS; +} + ze_result_t ContextImp::getMemAllocProperties(const void *ptr, ze_memory_allocation_properties_t *pMemAllocProperties, ze_device_handle_t *phDevice) { diff --git a/level_zero/core/source/context/context_imp.h b/level_zero/core/source/context/context_imp.h index 63a9a6548e..4f4c0da00d 100644 --- a/level_zero/core/source/context/context_imp.h +++ b/level_zero/core/source/context/context_imp.h @@ -8,6 +8,7 @@ #pragma once #include "shared/source/helpers/common_types.h" +#include "shared/source/memory_manager/memory_manager.h" #include "shared/source/utilities/stackvec.h" #include "level_zero/core/source/context/context.h" @@ -142,6 +143,9 @@ struct ContextImp : Context { void freePeerAllocations(const void *ptr, bool blocking, Device *device); + ze_result_t handleAllocationExtensions(NEO::GraphicsAllocation *alloc, ze_memory_type_t type, + void *pNext, struct DriverHandleImp *driverHandle); + RootDeviceIndicesContainer rootDeviceIndices; std::map deviceBitfields; diff --git a/level_zero/core/source/driver/driver_handle_imp.cpp b/level_zero/core/source/driver/driver_handle_imp.cpp index 99daa7df70..75e6620efe 100644 --- a/level_zero/core/source/driver/driver_handle_imp.cpp +++ b/level_zero/core/source/driver/driver_handle_imp.cpp @@ -567,13 +567,21 @@ NEO::GraphicsAllocation *DriverHandleImp::getPeerAllocation(Device *device, UNRECOVERABLE_IF(numHandles == 0); std::vector handles; for (uint32_t i = 0; i < numHandles; i++) { - int handle = static_cast(alloc->peekInternalHandle(this->getMemoryManager(), i)); - handles.push_back(handle); + uint64_t handle = 0; + int ret = alloc->peekInternalHandle(this->getMemoryManager(), i, handle); + if (ret < 0) { + return nullptr; + } + handles.push_back(static_cast(handle)); } auto neoDevice = device->getNEODevice()->getRootDevice(); peerPtr = this->importFdHandles(neoDevice, flags, handles, &alloc); } else { - uint64_t handle = alloc->peekInternalHandle(this->getMemoryManager()); + uint64_t handle = 0; + int ret = alloc->peekInternalHandle(this->getMemoryManager(), handle); + if (ret < 0) { + return nullptr; + } peerPtr = this->importFdHandle(device->getNEODevice(), flags, handle, &alloc); } diff --git a/level_zero/core/source/helpers/CMakeLists.txt b/level_zero/core/source/helpers/CMakeLists.txt index df1f09d17c..464977ca0f 100644 --- a/level_zero/core/source/helpers/CMakeLists.txt +++ b/level_zero/core/source/helpers/CMakeLists.txt @@ -7,8 +7,6 @@ target_sources(${L0_STATIC_LIB_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt - ${CMAKE_CURRENT_SOURCE_DIR}/allocation_extensions.h - ${CMAKE_CURRENT_SOURCE_DIR}/allocation_extensions.cpp ${CMAKE_CURRENT_SOURCE_DIR}/api_specific_config_l0.cpp ${CMAKE_CURRENT_SOURCE_DIR}/error_code_helper_l0.cpp ${CMAKE_CURRENT_SOURCE_DIR}/error_code_helper_l0.h diff --git a/level_zero/core/source/helpers/allocation_extensions.cpp b/level_zero/core/source/helpers/allocation_extensions.cpp deleted file mode 100644 index fdc177f3c3..0000000000 --- a/level_zero/core/source/helpers/allocation_extensions.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2022 Intel Corporation - * - * SPDX-License-Identifier: MIT - * - */ - -#include "level_zero/core/source/helpers/allocation_extensions.h" - -#include "shared/source/helpers/memory_properties_helpers.h" -#include "shared/source/memory_manager/memory_manager.h" -#include "shared/source/memory_manager/unified_memory_manager.h" - -#include "level_zero/core/source/driver/driver_handle_imp.h" - -namespace L0 { - -ze_result_t handleAllocationExtensions(NEO::GraphicsAllocation *alloc, ze_memory_type_t type, void *pNext, struct DriverHandleImp *driverHandle) { - if (pNext != nullptr) { - ze_base_properties_t *extendedProperties = - reinterpret_cast(pNext); - if (extendedProperties->stype == ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_FD) { - ze_external_memory_export_fd_t *extendedMemoryExportProperties = - reinterpret_cast(extendedProperties); - if (extendedMemoryExportProperties->flags & ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_FD) { - return ZE_RESULT_ERROR_UNSUPPORTED_ENUMERATION; - } - if (type != ZE_MEMORY_TYPE_DEVICE) { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; - } - uint64_t handle = alloc->peekInternalHandle(driverHandle->getMemoryManager()); - extendedMemoryExportProperties->fd = static_cast(handle); - } else if (extendedProperties->stype == ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_WIN32) { - ze_external_memory_export_win32_handle_t *exportStructure = reinterpret_cast(extendedProperties); - if (exportStructure->flags != ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32) { - return ZE_RESULT_ERROR_UNSUPPORTED_ENUMERATION; - } - uint64_t handle = alloc->peekInternalHandle(driverHandle->getMemoryManager()); - exportStructure->handle = reinterpret_cast(handle); - } else { - return ZE_RESULT_ERROR_INVALID_ENUMERATION; - } - } - - return ZE_RESULT_SUCCESS; -} -} // namespace L0 diff --git a/level_zero/core/source/helpers/allocation_extensions.h b/level_zero/core/source/helpers/allocation_extensions.h deleted file mode 100644 index 77220b0f2a..0000000000 --- a/level_zero/core/source/helpers/allocation_extensions.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2022 Intel Corporation - * - * SPDX-License-Identifier: MIT - * - */ - -#pragma once - -#include "shared/source/memory_manager/memory_manager.h" - -#include "level_zero/core/source/driver/driver_handle_imp.h" - -namespace L0 { - -ze_result_t handleAllocationExtensions(NEO::GraphicsAllocation *alloc, ze_memory_type_t type, - void *pNext, struct DriverHandleImp *driverHandle); -} // namespace L0 diff --git a/level_zero/core/test/unit_tests/sources/memory/CMakeLists.txt b/level_zero/core/test/unit_tests/sources/memory/CMakeLists.txt index e134ea0ec6..2e8f2db999 100644 --- a/level_zero/core/test/unit_tests/sources/memory/CMakeLists.txt +++ b/level_zero/core/test/unit_tests/sources/memory/CMakeLists.txt @@ -9,3 +9,4 @@ target_sources(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/test_memory.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test_memory_${DRIVER_MODEL}.cpp ) +add_subdirectories() diff --git a/level_zero/core/test/unit_tests/sources/memory/linux/CMakeLists.txt b/level_zero/core/test/unit_tests/sources/memory/linux/CMakeLists.txt new file mode 100644 index 0000000000..e8c6682df1 --- /dev/null +++ b/level_zero/core/test/unit_tests/sources/memory/linux/CMakeLists.txt @@ -0,0 +1,12 @@ +# +# Copyright (C) 2022 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +if(UNIX) + target_sources(${TARGET_NAME} PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/test_memory_linux.cpp + ) +endif() \ No newline at end of file diff --git a/level_zero/core/test/unit_tests/sources/memory/linux/test_memory_linux.cpp b/level_zero/core/test/unit_tests/sources/memory/linux/test_memory_linux.cpp new file mode 100644 index 0000000000..7abe4396cf --- /dev/null +++ b/level_zero/core/test/unit_tests/sources/memory/linux/test_memory_linux.cpp @@ -0,0 +1,706 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/os_interface/linux/drm_allocation.h" +#include "shared/source/os_interface/linux/drm_buffer_object.h" +#include "shared/source/os_interface/linux/drm_gem_close_worker.h" +#include "shared/source/os_interface/linux/drm_memory_manager.h" +#include "shared/test/common/libult/linux/drm_mock.h" +#include "shared/test/common/mocks/linux/mock_drm_allocation.h" +#include "shared/test/common/mocks/mock_driver_model.h" + +#include "level_zero/core/source/context/context_imp.h" +#include "level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.h" + +namespace L0 { +namespace ult { + +class IpcImplicitScalingObtainFdMockGraphicsAllocation : public NEO::DrmAllocation { + public: + using NEO::DrmAllocation::bufferObjects; + + IpcImplicitScalingObtainFdMockGraphicsAllocation(uint32_t rootDeviceIndex, + AllocationType allocationType, + BufferObject *bo, + void *ptrIn, + size_t sizeIn, + NEO::osHandle sharedHandle, + MemoryPool pool, + uint64_t canonizedGpuAddress) : NEO::DrmAllocation(rootDeviceIndex, + allocationType, + bo, + ptrIn, + sizeIn, + sharedHandle, + pool, + canonizedGpuAddress) { + bufferObjects.resize(2u); + } + + uint32_t getNumHandles() override { + return 2u; + } + + bool isResident(uint32_t contextId) const override { + return false; + } +}; + +class MemoryManagerIpcImplicitScalingObtainFdMock : public NEO::DrmMemoryManager { + public: + MemoryManagerIpcImplicitScalingObtainFdMock(NEO::ExecutionEnvironment &executionEnvironment) : NEO::DrmMemoryManager(gemCloseWorkerMode::gemCloseWorkerInactive, false, false, executionEnvironment) {} + + NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; } + void addAllocationToHostPtrManager(NEO::GraphicsAllocation *memory) override{}; + void removeAllocationFromHostPtrManager(NEO::GraphicsAllocation *memory) override{}; + NEO::GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override { return nullptr; }; + AllocationStatus populateOsHandles(NEO::OsHandleStorage &handleStorage, uint32_t rootDeviceIndex) override { return AllocationStatus::Success; }; + void cleanOsHandles(NEO::OsHandleStorage &handleStorage, uint32_t rootDeviceIndex) override{}; + void freeGraphicsMemoryImpl(NEO::GraphicsAllocation *gfxAllocation) override{}; + void freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation, bool isImportedAllocation) override{}; + uint64_t getSystemSharedMemory(uint32_t rootDeviceIndex) override { return 0; }; + uint64_t getLocalMemorySize(uint32_t rootDeviceIndex, uint32_t deviceBitfield) override { return 0; }; + double getPercentOfGlobalMemoryAvailable(uint32_t rootDeviceIndex) override { return 0; } + AddressRange reserveGpuAddress(size_t size, uint32_t rootDeviceIndex) override { + return {}; + } + void freeGpuAddress(AddressRange addressRange, uint32_t rootDeviceIndex) override{}; + NEO::GraphicsAllocation *createGraphicsAllocation(OsHandleStorage &handleStorage, const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemoryForNonSvmHostPtr(const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemoryWithAlignment(const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocateUSMHostGraphicsMemory(const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemory64kb(const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocate32BitGraphicsMemoryImpl(const NEO::AllocationData &allocationData, bool useLocalMemory) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemoryInDevicePool(const NEO::AllocationData &allocationData, AllocationStatus &status) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemoryWithGpuVa(const NEO::AllocationData &allocationData) override { return nullptr; }; + + NEO::GraphicsAllocation *allocateGraphicsMemoryForImageImpl(const NEO::AllocationData &allocationData, std::unique_ptr gmm) override { return nullptr; }; + NEO::GraphicsAllocation *allocateMemoryByKMD(const NEO::AllocationData &allocationData) override { return nullptr; }; + void *lockResourceImpl(NEO::GraphicsAllocation &graphicsAllocation) override { return nullptr; }; + void unlockResourceImpl(NEO::GraphicsAllocation &graphicsAllocation) override{}; + + NEO::GraphicsAllocation *allocateGraphicsMemoryInPreferredPool(const AllocationProperties &properties, const void *hostPtr) override { + auto ptr = reinterpret_cast(sharedHandleAddress++); + auto gmmHelper = getGmmHelper(0); + auto canonizedGpuAddress = gmmHelper->canonize(castToUint64(ptr)); + size_t size = 0x1000; + auto alloc = new IpcImplicitScalingObtainFdMockGraphicsAllocation(0u, + NEO::AllocationType::BUFFER, + nullptr, + ptr, + size, + 0u, + MemoryPool::System4KBPages, + canonizedGpuAddress); + auto &drm = this->getDrm(0u); + MockBufferObject bo0(&drm); + MockBufferObject bo1(&drm); + alloc->bufferObjects[0] = &bo0; + alloc->bufferObjects[1] = &bo1; + alloc->setGpuBaseAddress(0xabcd); + return alloc; + } + + NEO::GraphicsAllocation *allocateGraphicsMemoryWithProperties(const AllocationProperties &properties) override { + auto ptr = reinterpret_cast(sharedHandleAddress++); + auto gmmHelper = getGmmHelper(0); + auto canonizedGpuAddress = gmmHelper->canonize(castToUint64(ptr)); + size_t size = 0x1000; + auto alloc = new IpcImplicitScalingObtainFdMockGraphicsAllocation(0u, + NEO::AllocationType::BUFFER, + nullptr, + ptr, + size, + 0u, + MemoryPool::System4KBPages, + canonizedGpuAddress); + auto &drm = this->getDrm(0u); + MockBufferObject bo0(&drm); + MockBufferObject bo1(&drm); + alloc->bufferObjects[0] = &bo0; + alloc->bufferObjects[1] = &bo1; + alloc->setGpuBaseAddress(0xabcd); + return alloc; + } + + NEO::GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(const std::vector &handles, + AllocationProperties &properties, + bool requireSpecificBitness, + bool isHostIpcAllocation) override { + if (failOnCreateGraphicsAllocationFromSharedHandle) { + return nullptr; + } + auto ptr = reinterpret_cast(sharedHandleAddress++); + auto gmmHelper = getGmmHelper(0); + auto canonizedGpuAddress = gmmHelper->canonize(castToUint64(ptr)); + size_t size = 0x1000; + auto alloc = new IpcImplicitScalingObtainFdMockGraphicsAllocation(0u, + NEO::AllocationType::BUFFER, + nullptr, + ptr, + size, + 0u, + MemoryPool::System4KBPages, + canonizedGpuAddress); + auto &drm = this->getDrm(0u); + MockBufferObject bo0(&drm); + MockBufferObject bo1(&drm); + alloc->bufferObjects[0] = &bo0; + alloc->bufferObjects[1] = &bo1; + alloc->setGpuBaseAddress(0xabcd); + return alloc; + } + + void freeGraphicsMemory(NEO::GraphicsAllocation *alloc, bool isImportedAllocation) override { + delete alloc; + } + + int obtainFdFromHandle(int boHandle, uint32_t rootDeviceIndex) override { + if (failOnObtainFdFromHandle) { + return -1; + } + return NEO::DrmMemoryManager::obtainFdFromHandle(boHandle, rootDeviceIndex); + } + bool failOnObtainFdFromHandle = false; + + uint64_t sharedHandleAddress = 0x1234; + + bool failOnCreateGraphicsAllocationFromSharedHandle = false; +}; + +struct MemoryExportImportObtainFdTest : public ::testing::Test { + void SetUp() override { + DebugManagerStateRestore restorer; + DebugManager.flags.EnableImplicitScaling.set(1); + + executionEnvironment = new NEO::ExecutionEnvironment(); + executionEnvironment->prepareRootDeviceEnvironments(numRootDevices); + NEO::HardwareInfo hwInfo = *NEO::defaultHwInfo.get(); + for (auto i = 0u; i < executionEnvironment->rootDeviceEnvironments.size(); i++) { + executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(&hwInfo); + } + deviceFactory = std::make_unique(numRootDevices, numSubDevices, *executionEnvironment); + for (auto i = 0u; i < executionEnvironment->rootDeviceEnvironments.size(); i++) { + devices.push_back(std::unique_ptr(deviceFactory->rootDevices[i])); + executionEnvironment->rootDeviceEnvironments[i]->osInterface.reset(new NEO::OSInterface()); + auto drmMock = new DrmMockResources(*executionEnvironment->rootDeviceEnvironments[i]); + executionEnvironment->rootDeviceEnvironments[i]->osInterface->setDriverModel(std::unique_ptr(drmMock)); + } + + driverHandle = std::make_unique(); + driverHandle->initialize(std::move(devices)); + + prevMemoryManager = driverHandle->getMemoryManager(); + currMemoryManager = new MemoryManagerIpcImplicitScalingObtainFdMock(*executionEnvironment); + driverHandle->setMemoryManager(currMemoryManager); + + prevSvmAllocsManager = driverHandle->svmAllocsManager; + currSvmAllocsManager = new NEO::SVMAllocsManager(currMemoryManager, false); + driverHandle->svmAllocsManager = currSvmAllocsManager; + + context = std::make_unique(driverHandle.get()); + EXPECT_NE(context, nullptr); + for (auto i = 0u; i < numRootDevices; i++) { + auto dev = driverHandle->devices[i]; + context->getDevices().insert(std::make_pair(dev->getRootDeviceIndex(), dev->toHandle())); + } + device = driverHandle->devices[0]; + auto neoDevice = device->getNEODevice(); + context->rootDeviceIndices.push_back(neoDevice->getRootDeviceIndex()); + context->deviceBitfields.insert({neoDevice->getRootDeviceIndex(), neoDevice->getDeviceBitfield()}); + } + + void TearDown() override { + driverHandle->svmAllocsManager = prevSvmAllocsManager; + delete currSvmAllocsManager; + driverHandle->setMemoryManager(prevMemoryManager); + delete currMemoryManager; + } + + static constexpr uint32_t numRootDevices = 2u; + static constexpr uint32_t numSubDevices = 2u; + + std::vector> devices; + std::unique_ptr deviceFactory; + + SVMAllocsManager *prevSvmAllocsManager; + NEO::SVMAllocsManager *currSvmAllocsManager; + + NEO::ExecutionEnvironment *executionEnvironment = nullptr; + NEO::MemoryManager *prevMemoryManager = nullptr; + MemoryManagerIpcImplicitScalingObtainFdMock *currMemoryManager = nullptr; + std::unique_ptr driverHandle; + NEO::MockDevice *neoDevice = nullptr; + L0::Device *device = nullptr; + std::unique_ptr context; +}; + +TEST_F(MemoryExportImportObtainFdTest, + givenCallToGetIpcHandlesWithFailureToGetFdHandleThenOutOfHostMemoryIsReturned) { + size_t size = 10; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + uint32_t numIpcHandles = 0; + result = context->getIpcMemHandles(ptr, &numIpcHandles, nullptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(numIpcHandles, 2u); + + currMemoryManager->failOnObtainFdFromHandle = true; + + std::vector ipcHandles(numIpcHandles); + result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data()); + EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryExportImportObtainFdTest, + givenCallToGetIpcHandlesWithFdHandleThenSuccessIsReturned) { + size_t size = 10; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + uint32_t numIpcHandles = 0; + result = context->getIpcMemHandles(ptr, &numIpcHandles, nullptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_EQ(numIpcHandles, 2u); + + currMemoryManager->failOnObtainFdFromHandle = false; + + std::vector ipcHandles(numIpcHandles); + result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data()); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryExportImportObtainFdTest, + givenCallToGetIpcHandleWithFailureToGetFdHandleThenOutOfHostMemoryIsReturned) { + size_t size = 10; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + currMemoryManager->failOnObtainFdFromHandle = true; + ze_ipc_mem_handle_t ipcHandle{}; + result = context->getIpcMemHandle(ptr, &ipcHandle); + EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryExportImportObtainFdTest, + givenCallToGetIpcHandleWithFdHandleThenSuccessIsReturned) { + size_t size = 10; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + currMemoryManager->failOnObtainFdFromHandle = false; + ze_ipc_mem_handle_t ipcHandle{}; + result = context->getIpcMemHandle(ptr, &ipcHandle); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryExportImportObtainFdTest, + givenCallToEventPoolGetIpcHandleWithFailureToGetFdHandleThenOutOfHostMemoryIsReturned) { + + uint32_t numEvents = 4; + ze_event_pool_desc_t eventPoolDesc = { + ZE_STRUCTURE_TYPE_EVENT_POOL_DESC, + nullptr, + ZE_EVENT_POOL_FLAG_HOST_VISIBLE | ZE_EVENT_POOL_FLAG_IPC, + numEvents}; + + auto deviceHandle = device->toHandle(); + ze_result_t result = ZE_RESULT_SUCCESS; + auto eventPool = static_cast(EventPool::create(driverHandle.get(), + context.get(), + 1, + &deviceHandle, + &eventPoolDesc, + result)); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, eventPool); + eventPool->isShareableEventMemory = true; + + currMemoryManager->failOnObtainFdFromHandle = true; + ze_ipc_event_pool_handle_t ipcHandle = {}; + result = eventPool->getIpcHandle(&ipcHandle); + EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, result); + + result = eventPool->destroy(); + EXPECT_EQ(result, ZE_RESULT_SUCCESS); +} + +TEST_F(MemoryExportImportObtainFdTest, + givenCallToEventPoolGetIpcHandleWithFdHandleThenSuccessIsReturned) { + uint32_t numEvents = 4; + ze_event_pool_desc_t eventPoolDesc = { + ZE_STRUCTURE_TYPE_EVENT_POOL_DESC, + nullptr, + ZE_EVENT_POOL_FLAG_HOST_VISIBLE | ZE_EVENT_POOL_FLAG_IPC, + numEvents}; + + auto deviceHandle = device->toHandle(); + ze_result_t result = ZE_RESULT_SUCCESS; + auto eventPool = static_cast(EventPool::create(driverHandle.get(), + context.get(), + 1, + &deviceHandle, + &eventPoolDesc, + result)); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, eventPool); + eventPool->isShareableEventMemory = true; + + currMemoryManager->failOnObtainFdFromHandle = false; + ze_ipc_event_pool_handle_t ipcHandle = {}; + result = eventPool->getIpcHandle(&ipcHandle); + EXPECT_EQ(result, ZE_RESULT_SUCCESS); + + result = eventPool->destroy(); + EXPECT_EQ(result, ZE_RESULT_SUCCESS); +} + +TEST_F(MemoryExportImportObtainFdTest, + whenPeerAllocationForDeviceAllocationIsRequestedThenPeerAllocationIsReturned) { + L0::Device *device0 = driverHandle->devices[0]; + L0::Device *device1 = driverHandle->devices[1]; + + size_t size = 1024; + size_t alignment = 1u; + void *ptr = nullptr; + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device0->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + uintptr_t peerGpuAddress = 0u; + auto allocData = context->getDriverHandle()->getSvmAllocsManager()->getSVMAlloc(ptr); + EXPECT_NE(allocData, nullptr); + currMemoryManager->failOnObtainFdFromHandle = false; + auto peerAlloc = driverHandle->getPeerAllocation(device1, allocData, ptr, &peerGpuAddress); + EXPECT_NE(peerAlloc, nullptr); + + result = context->freeMem(ptr); + ASSERT_EQ(result, ZE_RESULT_SUCCESS); +} + +TEST_F(MemoryExportImportObtainFdTest, + whenPeerAllocationForDeviceAllocationIsRequestedThenNullptrIsReturned) { + L0::Device *device0 = driverHandle->devices[0]; + L0::Device *device1 = driverHandle->devices[1]; + + size_t size = 1024; + size_t alignment = 1u; + void *ptr = nullptr; + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device0->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + uintptr_t peerGpuAddress = 0u; + auto allocData = context->getDriverHandle()->getSvmAllocsManager()->getSVMAlloc(ptr); + EXPECT_NE(allocData, nullptr); + currMemoryManager->failOnObtainFdFromHandle = true; + auto peerAlloc = driverHandle->getPeerAllocation(device1, allocData, ptr, &peerGpuAddress); + EXPECT_EQ(peerAlloc, nullptr); + + result = context->freeMem(ptr); + ASSERT_EQ(result, ZE_RESULT_SUCCESS); +} + +class IpcObtainFdMockGraphicsAllocation : public NEO::DrmAllocation { + public: + using NEO::DrmAllocation::bufferObjects; + + IpcObtainFdMockGraphicsAllocation(uint32_t rootDeviceIndex, + AllocationType allocationType, + BufferObject *bo, + void *ptrIn, + size_t sizeIn, + NEO::osHandle sharedHandle, + MemoryPool pool, + uint64_t canonizedGpuAddress) : NEO::DrmAllocation(rootDeviceIndex, + allocationType, + bo, + ptrIn, + sizeIn, + sharedHandle, + pool, + canonizedGpuAddress) { + bufferObjects.resize(1u); + } + + uint32_t getNumHandles() override { + return 1u; + } + + bool isResident(uint32_t contextId) const override { + return false; + } +}; + +class MemoryManagerIpcObtainFdMock : public NEO::DrmMemoryManager { + public: + MemoryManagerIpcObtainFdMock(NEO::ExecutionEnvironment &executionEnvironment) : NEO::DrmMemoryManager(gemCloseWorkerMode::gemCloseWorkerInactive, false, false, executionEnvironment) {} + + NEO::GraphicsAllocation *createGraphicsAllocationFromSharedHandle(osHandle handle, const AllocationProperties &properties, bool requireSpecificBitness, bool isHostIpcAllocation) override { return nullptr; } + void addAllocationToHostPtrManager(NEO::GraphicsAllocation *memory) override{}; + void removeAllocationFromHostPtrManager(NEO::GraphicsAllocation *memory) override{}; + NEO::GraphicsAllocation *createGraphicsAllocationFromNTHandle(void *handle, uint32_t rootDeviceIndex, AllocationType allocType) override { return nullptr; }; + AllocationStatus populateOsHandles(NEO::OsHandleStorage &handleStorage, uint32_t rootDeviceIndex) override { return AllocationStatus::Success; }; + void cleanOsHandles(NEO::OsHandleStorage &handleStorage, uint32_t rootDeviceIndex) override{}; + void freeGraphicsMemoryImpl(NEO::GraphicsAllocation *gfxAllocation) override{}; + void freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation, bool isImportedAllocation) override{}; + uint64_t getSystemSharedMemory(uint32_t rootDeviceIndex) override { return 0; }; + uint64_t getLocalMemorySize(uint32_t rootDeviceIndex, uint32_t deviceBitfield) override { return 0; }; + double getPercentOfGlobalMemoryAvailable(uint32_t rootDeviceIndex) override { return 0; } + AddressRange reserveGpuAddress(size_t size, uint32_t rootDeviceIndex) override { + return {}; + } + void freeGpuAddress(AddressRange addressRange, uint32_t rootDeviceIndex) override{}; + NEO::GraphicsAllocation *createGraphicsAllocation(OsHandleStorage &handleStorage, const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemoryForNonSvmHostPtr(const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemoryWithAlignment(const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocateUSMHostGraphicsMemory(const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemory64kb(const NEO::AllocationData &allocationData) override { return nullptr; }; + NEO::GraphicsAllocation *allocate32BitGraphicsMemoryImpl(const NEO::AllocationData &allocationData, bool useLocalMemory) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemoryInDevicePool(const NEO::AllocationData &allocationData, AllocationStatus &status) override { return nullptr; }; + NEO::GraphicsAllocation *allocateGraphicsMemoryWithGpuVa(const NEO::AllocationData &allocationData) override { return nullptr; }; + + NEO::GraphicsAllocation *allocateGraphicsMemoryForImageImpl(const NEO::AllocationData &allocationData, std::unique_ptr gmm) override { return nullptr; }; + NEO::GraphicsAllocation *allocateMemoryByKMD(const NEO::AllocationData &allocationData) override { return nullptr; }; + void *lockResourceImpl(NEO::GraphicsAllocation &graphicsAllocation) override { return nullptr; }; + void unlockResourceImpl(NEO::GraphicsAllocation &graphicsAllocation) override{}; + + NEO::GraphicsAllocation *allocateGraphicsMemoryInPreferredPool(const AllocationProperties &properties, const void *hostPtr) override { + auto ptr = reinterpret_cast(sharedHandleAddress++); + auto gmmHelper = getGmmHelper(0); + auto canonizedGpuAddress = gmmHelper->canonize(castToUint64(ptr)); + size_t size = 0x1000; + auto alloc = new IpcObtainFdMockGraphicsAllocation(0u, + NEO::AllocationType::BUFFER, + nullptr, + ptr, + size, + 0u, + MemoryPool::System4KBPages, + canonizedGpuAddress); + auto &drm = this->getDrm(0u); + MockBufferObject bo0(&drm); + alloc->bufferObjects[0] = &bo0; + alloc->setGpuBaseAddress(0xabcd); + return alloc; + } + + NEO::GraphicsAllocation *allocateGraphicsMemoryWithProperties(const AllocationProperties &properties) override { + auto ptr = reinterpret_cast(sharedHandleAddress++); + auto gmmHelper = getGmmHelper(0); + auto canonizedGpuAddress = gmmHelper->canonize(castToUint64(ptr)); + size_t size = 0x1000; + auto alloc = new IpcObtainFdMockGraphicsAllocation(0u, + NEO::AllocationType::BUFFER, + nullptr, + ptr, + size, + 0u, + MemoryPool::System4KBPages, + canonizedGpuAddress); + auto &drm = this->getDrm(0u); + MockBufferObject bo0(&drm); + alloc->bufferObjects[0] = &bo0; + alloc->setGpuBaseAddress(0xabcd); + return alloc; + } + + NEO::GraphicsAllocation *createGraphicsAllocationFromMultipleSharedHandles(const std::vector &handles, + AllocationProperties &properties, + bool requireSpecificBitness, + bool isHostIpcAllocation) override { + if (failOnCreateGraphicsAllocationFromSharedHandle) { + return nullptr; + } + auto ptr = reinterpret_cast(sharedHandleAddress++); + auto gmmHelper = getGmmHelper(0); + auto canonizedGpuAddress = gmmHelper->canonize(castToUint64(ptr)); + size_t size = 0x1000; + auto alloc = new IpcObtainFdMockGraphicsAllocation(0u, + NEO::AllocationType::BUFFER, + nullptr, + ptr, + size, + 0u, + MemoryPool::System4KBPages, + canonizedGpuAddress); + auto &drm = this->getDrm(0u); + MockBufferObject bo0(&drm); + alloc->bufferObjects[0] = &bo0; + alloc->setGpuBaseAddress(0xabcd); + return alloc; + } + + void freeGraphicsMemory(NEO::GraphicsAllocation *alloc, bool isImportedAllocation) override { + delete alloc; + } + + int obtainFdFromHandle(int boHandle, uint32_t rootDeviceIndex) override { + if (failOnObtainFdFromHandle) { + return -1; + } + return NEO::DrmMemoryManager::obtainFdFromHandle(boHandle, rootDeviceIndex); + } + bool failOnObtainFdFromHandle = false; + + uint64_t sharedHandleAddress = 0x1234; + + bool failOnCreateGraphicsAllocationFromSharedHandle = false; +}; + +struct DriverHandleObtaindFdMock : public L0::DriverHandleImp { + void *importFdHandle(NEO::Device *neoDevice, ze_ipc_memory_flags_t flags, uint64_t handle, NEO::GraphicsAllocation **pAloc) override { + DeviceBitfield deviceBitfield{0x0}; + AllocationProperties properties(0, MemoryConstants::pageSize, + AllocationType::BUFFER, + deviceBitfield); + auto alloc = getMemoryManager()->allocateGraphicsMemoryWithProperties(properties); + return reinterpret_cast(alloc->getGpuAddress()); + } +}; + +struct MemoryObtainFdTest : public ::testing::Test { + void SetUp() override { + DebugManagerStateRestore restorer; + + executionEnvironment = new NEO::ExecutionEnvironment(); + executionEnvironment->prepareRootDeviceEnvironments(numRootDevices); + NEO::HardwareInfo hwInfo = *NEO::defaultHwInfo.get(); + for (auto i = 0u; i < executionEnvironment->rootDeviceEnvironments.size(); i++) { + executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(&hwInfo); + } + deviceFactory = std::make_unique(numRootDevices, numSubDevices, *executionEnvironment); + for (auto i = 0u; i < executionEnvironment->rootDeviceEnvironments.size(); i++) { + devices.push_back(std::unique_ptr(deviceFactory->rootDevices[i])); + executionEnvironment->rootDeviceEnvironments[i]->osInterface.reset(new NEO::OSInterface()); + auto drmMock = new DrmMockResources(*executionEnvironment->rootDeviceEnvironments[i]); + executionEnvironment->rootDeviceEnvironments[i]->osInterface->setDriverModel(std::unique_ptr(drmMock)); + } + + driverHandle = std::make_unique(); + driverHandle->initialize(std::move(devices)); + + prevMemoryManager = driverHandle->getMemoryManager(); + currMemoryManager = new MemoryManagerIpcObtainFdMock(*executionEnvironment); + driverHandle->setMemoryManager(currMemoryManager); + + prevSvmAllocsManager = driverHandle->svmAllocsManager; + currSvmAllocsManager = new NEO::SVMAllocsManager(currMemoryManager, false); + driverHandle->svmAllocsManager = currSvmAllocsManager; + + context = std::make_unique(driverHandle.get()); + EXPECT_NE(context, nullptr); + for (auto i = 0u; i < numRootDevices; i++) { + auto dev = driverHandle->devices[i]; + context->getDevices().insert(std::make_pair(dev->getRootDeviceIndex(), dev->toHandle())); + } + device = driverHandle->devices[0]; + auto neoDevice = device->getNEODevice(); + context->rootDeviceIndices.push_back(neoDevice->getRootDeviceIndex()); + context->deviceBitfields.insert({neoDevice->getRootDeviceIndex(), neoDevice->getDeviceBitfield()}); + } + + void TearDown() override { + driverHandle->svmAllocsManager = prevSvmAllocsManager; + delete currSvmAllocsManager; + driverHandle->setMemoryManager(prevMemoryManager); + delete currMemoryManager; + } + + static constexpr uint32_t numRootDevices = 2u; + static constexpr uint32_t numSubDevices = 2u; + + std::vector> devices; + std::unique_ptr deviceFactory; + + SVMAllocsManager *prevSvmAllocsManager; + NEO::SVMAllocsManager *currSvmAllocsManager; + + NEO::ExecutionEnvironment *executionEnvironment = nullptr; + NEO::MemoryManager *prevMemoryManager = nullptr; + MemoryManagerIpcObtainFdMock *currMemoryManager = nullptr; + std::unique_ptr driverHandle; + NEO::MockDevice *neoDevice = nullptr; + L0::Device *device = nullptr; + std::unique_ptr context; +}; + +TEST_F(MemoryObtainFdTest, + whenPeerAllocationForDeviceAllocationIsRequestedThenNullptrIsReturned) { + L0::Device *device0 = driverHandle->devices[0]; + L0::Device *device1 = driverHandle->devices[1]; + + size_t size = 1024; + size_t alignment = 1u; + void *ptr = nullptr; + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = context->allocDeviceMem(device0->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + uintptr_t peerGpuAddress = 0u; + auto allocData = context->getDriverHandle()->getSvmAllocsManager()->getSVMAlloc(ptr); + EXPECT_NE(allocData, nullptr); + currMemoryManager->failOnObtainFdFromHandle = true; + auto peerAlloc = driverHandle->getPeerAllocation(device1, allocData, ptr, &peerGpuAddress); + EXPECT_EQ(peerAlloc, nullptr); + + result = context->freeMem(ptr); + ASSERT_EQ(result, ZE_RESULT_SUCCESS); +} + +} // namespace ult +} // namespace L0 diff --git a/level_zero/core/test/unit_tests/sources/memory/test_memory.cpp b/level_zero/core/test/unit_tests/sources/memory/test_memory.cpp index 675f9ba5bb..ae744bb509 100644 --- a/level_zero/core/test/unit_tests/sources/memory/test_memory.cpp +++ b/level_zero/core/test/unit_tests/sources/memory/test_memory.cpp @@ -7,6 +7,7 @@ #include "shared/source/helpers/file_io.h" #include "shared/source/helpers/string.h" +#include "shared/source/memory_manager/graphics_allocation.h" #include "shared/source/memory_manager/memory_operations_status.h" #include "shared/source/os_interface/device_factory.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" @@ -1801,6 +1802,53 @@ TEST_F(MemoryExportImportTest, EXPECT_EQ(ZE_RESULT_SUCCESS, result); } +TEST_F(MemoryExportImportTest, + givenCallToMemAllocPropertiesWithExtendedExportPropertiesAndNoFdHandleThenErrorIsReturned) { + class ExportImportMockGraphicsAllocation : public NEO::MemoryAllocation { + public: + ExportImportMockGraphicsAllocation() : NEO::MemoryAllocation(0, AllocationType::BUFFER, nullptr, 0u, 0, MemoryPool::MemoryNull, MemoryManager::maxOsContextCount, 0llu) {} + + int peekInternalHandle(NEO::MemoryManager *memoryManager, uint64_t &handle) override { + return -1; + } + }; + + ze_memory_allocation_properties_t memoryProperties = {}; + ze_external_memory_export_fd_t extendedProperties = {}; + extendedProperties.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_FD; + extendedProperties.fd = std::numeric_limits::max(); + memoryProperties.pNext = &extendedProperties; + + ze_memory_type_t type = ZE_MEMORY_TYPE_DEVICE; + ExportImportMockGraphicsAllocation alloc; + ze_result_t result = context->handleAllocationExtensions(&alloc, type, &extendedProperties, driverHandle.get()); + EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, result); +} + +TEST_F(MemoryExportImportTest, + givenCallToMemAllocPropertiesWithExtendedExportPropertiesAndNoFdHandleForWin32FormatThenErrorIsReturned) { + class ExportImportMockGraphicsAllocation : public NEO::MemoryAllocation { + public: + ExportImportMockGraphicsAllocation() : NEO::MemoryAllocation(0, AllocationType::BUFFER, nullptr, 0u, 0, MemoryPool::MemoryNull, MemoryManager::maxOsContextCount, 0llu) {} + + int peekInternalHandle(NEO::MemoryManager *memoryManager, uint64_t &handle) override { + return -1; + } + }; + + ze_memory_allocation_properties_t memoryProperties = {}; + ze_external_memory_export_fd_t extendedProperties = {}; + extendedProperties.stype = ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_WIN32; + extendedProperties.flags = ZE_EXTERNAL_MEMORY_TYPE_FLAG_OPAQUE_WIN32; + extendedProperties.fd = std::numeric_limits::max(); + memoryProperties.pNext = &extendedProperties; + + ze_memory_type_t type = ZE_MEMORY_TYPE_DEVICE; + ExportImportMockGraphicsAllocation alloc; + ze_result_t result = context->handleAllocationExtensions(&alloc, type, &extendedProperties, driverHandle.get()); + EXPECT_EQ(ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY, result); +} + TEST_F(MemoryExportImportTest, givenCallToMemAllocPropertiesWithExtendedExportPropertiesForNonDeviceAllocationThenUnsupportedFeatureIsReturned) { size_t size = 10; diff --git a/opencl/source/mem_obj/mem_obj.cpp b/opencl/source/mem_obj/mem_obj.cpp index 0665cbf0d1..7cbe37d665 100644 --- a/opencl/source/mem_obj/mem_obj.cpp +++ b/opencl/source/mem_obj/mem_obj.cpp @@ -193,7 +193,7 @@ cl_int MemObj::getMemObjectInfo(cl_mem_info paramName, break; case CL_MEM_ALLOCATION_HANDLE_INTEL: - internalHandle = multiGraphicsAllocation.getDefaultGraphicsAllocation()->peekInternalHandle(this->memoryManager); + multiGraphicsAllocation.getDefaultGraphicsAllocation()->peekInternalHandle(this->memoryManager, internalHandle); srcParamSize = sizeof(internalHandle); srcParam = &internalHandle; break; diff --git a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp index 010a8298b2..e306db9f40 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp @@ -481,7 +481,9 @@ TEST_F(WddmTestWithMockGdiDll, givenShareableAllocationWhenCreateThenSharedHandl allocation.setDefaultGmm(gmm.get()); auto status = memoryManager.createGpuAllocationsWithRetry(&allocation); EXPECT_TRUE(status); - EXPECT_NE(0u, allocation.peekInternalHandle(&memoryManager)); + uint64_t handle = 0; + allocation.peekInternalHandle(&memoryManager, handle); + EXPECT_NE(0u, handle); } TEST(WddmAllocationTest, whenAllocationIsShareableThenSharedHandleToModifyIsSharedHandleOfAllocation) { @@ -489,7 +491,10 @@ TEST(WddmAllocationTest, whenAllocationIsShareableThenSharedHandleToModifyIsShar auto sharedHandleToModify = allocation.getSharedHandleToModify(); EXPECT_NE(nullptr, sharedHandleToModify); *sharedHandleToModify = 1234u; - EXPECT_EQ(*sharedHandleToModify, allocation.peekInternalHandle(nullptr)); + uint64_t handle = 0; + int ret = allocation.peekInternalHandle(nullptr, handle); + EXPECT_EQ(ret, 0); + EXPECT_EQ(*sharedHandleToModify, handle); } TEST(WddmAllocationTest, whenAllocationIsNotShareableThenItDoesntReturnSharedHandleToModify) { diff --git a/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_allocate_in_device_pool_tests.cpp b/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_allocate_in_device_pool_tests.cpp index 8c0bb2c7ed..7766a47c7f 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_allocate_in_device_pool_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm_memory_manager_allocate_in_device_pool_tests.cpp @@ -75,7 +75,9 @@ TEST_F(WddmMemoryManagerSimpleTest, givenShareableAllocationWhenAllocateInDevice EXPECT_EQ(MemoryManager::AllocationStatus::Success, status); EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool()); EXPECT_EQ(0u, allocation->getDefaultGmm()->resourceParams.Flags.Info.NonLocalOnly); - EXPECT_NE(allocation->peekInternalHandle(memoryManager.get()), 0u); + uint64_t handle = 0; + allocation->peekInternalHandle(memoryManager.get(), handle); + EXPECT_NE(handle, 0u); EXPECT_EQ(1u, allocation->getDefaultGmm()->resourceParams.Flags.Info.LocalOnly); EXPECT_EQ(1u, allocation->getDefaultGmm()->resourceParams.Flags.Info.NotLockable); @@ -102,7 +104,9 @@ TEST_F(WddmMemoryManagerSimpleTest, givenShareableAllocationWhenAllocateGraphics EXPECT_NE(nullptr, allocation); EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool()); EXPECT_EQ(0u, allocation->getDefaultGmm()->resourceParams.Flags.Info.NonLocalOnly); - EXPECT_NE(allocation->peekInternalHandle(memoryManager.get()), 0u); + uint64_t handle = 0; + allocation->peekInternalHandle(memoryManager.get(), handle); + EXPECT_NE(handle, 0u); EXPECT_EQ(1u, allocation->getDefaultGmm()->resourceParams.Flags.Info.LocalOnly); EXPECT_EQ(1u, allocation->getDefaultGmm()->resourceParams.Flags.Info.NotLockable); diff --git a/shared/source/memory_manager/graphics_allocation.h b/shared/source/memory_manager/graphics_allocation.h index 0eb242f989..28a713bf90 100644 --- a/shared/source/memory_manager/graphics_allocation.h +++ b/shared/source/memory_manager/graphics_allocation.h @@ -169,10 +169,10 @@ class GraphicsAllocation : public IDNode { bool isResidencyTaskCountBelow(uint32_t taskCount, uint32_t contextId) const { return !isResident(contextId) || getResidencyTaskCount(contextId) < taskCount; } virtual std::string getAllocationInfoString() const; - virtual uint64_t peekInternalHandle(MemoryManager *memoryManager) { return 0llu; } + virtual int peekInternalHandle(MemoryManager *memoryManager, uint64_t &handle) { return 0; } - virtual uint64_t peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId) { - return 0u; + virtual int peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId, uint64_t &handle) { + return 0; } virtual uint32_t getNumHandles() { diff --git a/shared/source/os_interface/linux/drm_allocation.cpp b/shared/source/os_interface/linux/drm_allocation.cpp index 8088b91595..39a2910b12 100644 --- a/shared/source/os_interface/linux/drm_allocation.cpp +++ b/shared/source/os_interface/linux/drm_allocation.cpp @@ -37,20 +37,24 @@ std::string DrmAllocation::getAllocationInfoString() const { return ss.str(); } -uint64_t DrmAllocation::peekInternalHandle(MemoryManager *memoryManager) { - if (handles[0] != std::numeric_limits::max()) { - return handles[0]; - } - handles[0] = static_cast((static_cast(memoryManager))->obtainFdFromHandle(getBO()->peekHandle(), this->rootDeviceIndex)); - return handles[0]; +int DrmAllocation::peekInternalHandle(MemoryManager *memoryManager, uint64_t &handle) { + return peekInternalHandle(memoryManager, 0u, handle); } -uint64_t DrmAllocation::peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId) { - if (handles[handleId] != std::numeric_limits::max()) { - return handles[handleId]; +int DrmAllocation::peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId, uint64_t &handle) { + if (handles[handleId] != std::numeric_limits::max()) { + handle = handles[handleId]; + return 0; } - handles[handleId] = static_cast((static_cast(memoryManager))->obtainFdFromHandle(getBufferObjectToModify(handleId)->peekHandle(), this->rootDeviceIndex)); - return handles[handleId]; + + int64_t ret = static_cast((static_cast(memoryManager))->obtainFdFromHandle(getBufferObjectToModify(handleId)->peekHandle(), this->rootDeviceIndex)); + if (ret < 0) { + return -1; + } + + handle = handles[handleId] = ret; + + return 0; } void DrmAllocation::setCachePolicy(CachePolicy memType) { diff --git a/shared/source/os_interface/linux/drm_allocation.h b/shared/source/os_interface/linux/drm_allocation.h index 92a690ad29..6de1c84af2 100644 --- a/shared/source/os_interface/linux/drm_allocation.h +++ b/shared/source/os_interface/linux/drm_allocation.h @@ -40,7 +40,7 @@ class DrmAllocation : public GraphicsAllocation { DrmAllocation(uint32_t rootDeviceIndex, size_t numGmms, AllocationType allocationType, BufferObject *bo, void *ptrIn, size_t sizeIn, osHandle sharedHandle, MemoryPool pool, uint64_t canonizedGpuAddress) : GraphicsAllocation(rootDeviceIndex, numGmms, allocationType, ptrIn, sizeIn, sharedHandle, pool, MemoryManager::maxOsContextCount, canonizedGpuAddress), bufferObjects(EngineLimits::maxHandleCount) { bufferObjects[0] = bo; - handles.resize(EngineLimits::maxHandleCount, std::numeric_limits::max()); + handles.resize(EngineLimits::maxHandleCount, std::numeric_limits::max()); } DrmAllocation(uint32_t rootDeviceIndex, AllocationType allocationType, BufferObject *bo, void *ptrIn, uint64_t canonizedGpuAddress, size_t sizeIn, MemoryPool pool) @@ -49,7 +49,7 @@ class DrmAllocation : public GraphicsAllocation { DrmAllocation(uint32_t rootDeviceIndex, size_t numGmms, AllocationType allocationType, BufferObject *bo, void *ptrIn, uint64_t canonizedGpuAddress, size_t sizeIn, MemoryPool pool) : GraphicsAllocation(rootDeviceIndex, numGmms, allocationType, ptrIn, canonizedGpuAddress, 0, sizeIn, pool, MemoryManager::maxOsContextCount), bufferObjects(EngineLimits::maxHandleCount) { bufferObjects[0] = bo; - handles.resize(EngineLimits::maxHandleCount, std::numeric_limits::max()); + handles.resize(EngineLimits::maxHandleCount, std::numeric_limits::max()); } DrmAllocation(uint32_t rootDeviceIndex, AllocationType allocationType, BufferObjects &bos, void *ptrIn, uint64_t canonizedGpuAddress, size_t sizeIn, MemoryPool pool) @@ -58,7 +58,7 @@ class DrmAllocation : public GraphicsAllocation { DrmAllocation(uint32_t rootDeviceIndex, size_t numGmms, AllocationType allocationType, BufferObjects &bos, void *ptrIn, uint64_t canonizedGpuAddress, size_t sizeIn, MemoryPool pool) : GraphicsAllocation(rootDeviceIndex, numGmms, allocationType, ptrIn, canonizedGpuAddress, 0, sizeIn, pool, MemoryManager::maxOsContextCount), bufferObjects(bos) { - handles.resize(EngineLimits::maxHandleCount, std::numeric_limits::max()); + handles.resize(EngineLimits::maxHandleCount, std::numeric_limits::max()); } ~DrmAllocation() override; @@ -74,7 +74,7 @@ class DrmAllocation : public GraphicsAllocation { const BufferObjects &getBOs() const { return this->bufferObjects; } - BufferObject *&getBufferObjectToModify(uint32_t handleIndex) { + MOCKABLE_VIRTUAL BufferObject *&getBufferObjectToModify(uint32_t handleIndex) { return bufferObjects[handleIndex]; } @@ -90,9 +90,9 @@ class DrmAllocation : public GraphicsAllocation { this->numHandles = numHandles; } - uint64_t peekInternalHandle(MemoryManager *memoryManager) override; + int peekInternalHandle(MemoryManager *memoryManager, uint64_t &handle) override; - uint64_t peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId) override; + int peekInternalHandle(MemoryManager *memoryManager, uint32_t handleId, uint64_t &handle) override; bool setCacheRegion(Drm *drm, CacheRegion regionIndex); bool setCacheAdvice(Drm *drm, size_t regionSize, CacheRegion regionIndex); diff --git a/shared/source/os_interface/linux/drm_memory_manager.cpp b/shared/source/os_interface/linux/drm_memory_manager.cpp index 97dd52cbe7..40820d1680 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager.cpp @@ -978,7 +978,11 @@ GraphicsAllocation *DrmMemoryManager::createGraphicsAllocationFromExistingStorag properties.size = defaultAlloc->getUnderlyingBufferSize(); properties.gpuAddress = castToUint64(ptr); - auto internalHandle = defaultAlloc->peekInternalHandle(this); + uint64_t internalHandle = 0; + int ret = defaultAlloc->peekInternalHandle(this, internalHandle); + if (ret < 0) { + return nullptr; + } return createUSMHostAllocationFromSharedHandle(static_cast(internalHandle), properties, true); } else { return allocateGraphicsMemoryWithProperties(properties, ptr); @@ -1114,7 +1118,10 @@ int DrmMemoryManager::obtainFdFromHandle(int boHandle, uint32_t rootDeviceIndex) openFd.flags = ioctlHelper->getFlagsForPrimeHandleToFd(); openFd.handle = boHandle; - ioctlHelper->ioctl(DrmIoctl::PrimeHandleToFd, &openFd); + int ret = ioctlHelper->ioctl(DrmIoctl::PrimeHandleToFd, &openFd); + if (ret < 0) { + return -1; + } return openFd.fileDescriptor; } diff --git a/shared/source/os_interface/windows/wddm_allocation.h b/shared/source/os_interface/windows/wddm_allocation.h index b0522055ba..a57054e866 100644 --- a/shared/source/os_interface/windows/wddm_allocation.h +++ b/shared/source/os_interface/windows/wddm_allocation.h @@ -72,8 +72,9 @@ class WddmAllocation : public GraphicsAllocation { handles[handleIndex] = handle; } - uint64_t peekInternalHandle(MemoryManager *memoryManager) override { - return ntSecureHandle; + int peekInternalHandle(MemoryManager *memoryManager, uint64_t &handle) override { + handle = ntSecureHandle; + return 0; } uint64_t *getSharedHandleToModify() { diff --git a/shared/source/os_interface/windows/wddm_memory_manager.cpp b/shared/source/os_interface/windows/wddm_memory_manager.cpp index af69de99bd..f33fadfdd7 100644 --- a/shared/source/os_interface/windows/wddm_memory_manager.cpp +++ b/shared/source/os_interface/windows/wddm_memory_manager.cpp @@ -557,8 +557,10 @@ void WddmMemoryManager::freeGraphicsMemoryImpl(GraphicsAllocation *gfxAllocation for (auto handleId = 0u; handleId < gfxAllocation->getNumGmms(); handleId++) { delete gfxAllocation->getGmm(handleId); } - if (input->peekInternalHandle(nullptr) != 0u) { - [[maybe_unused]] auto status = SysCalls::closeHandle(reinterpret_cast(reinterpret_cast(input->peekInternalHandle(nullptr)))); + uint64_t handle = 0; + int ret = input->peekInternalHandle(nullptr, handle); + if (ret == 0) { + [[maybe_unused]] auto status = SysCalls::closeHandle(reinterpret_cast(reinterpret_cast(handle))); DEBUG_BREAK_IF(!status); } diff --git a/shared/test/common/mocks/linux/mock_drm_memory_manager.h b/shared/test/common/mocks/linux/mock_drm_memory_manager.h index a5417a961d..ff52b40ece 100644 --- a/shared/test/common/mocks/linux/mock_drm_memory_manager.h +++ b/shared/test/common/mocks/linux/mock_drm_memory_manager.h @@ -160,6 +160,15 @@ class TestedDrmMemoryManager : public MemoryManagerCreate { bool failOnfindAndReferenceSharedBufferObject = false; + bool failOnObtainFdFromHandle = false; + + int obtainFdFromHandle(int boHandle, uint32_t rootDeviceIndex) override { + if (failOnObtainFdFromHandle) { + return -1; + } + return DrmMemoryManager::obtainFdFromHandle(boHandle, rootDeviceIndex); + } + ExecutionEnvironment *executionEnvironment = nullptr; protected: diff --git a/shared/test/unit_test/memory_manager/graphics_allocation_tests.cpp b/shared/test/unit_test/memory_manager/graphics_allocation_tests.cpp index 297f52c284..c2dbc8deb6 100644 --- a/shared/test/unit_test/memory_manager/graphics_allocation_tests.cpp +++ b/shared/test/unit_test/memory_manager/graphics_allocation_tests.cpp @@ -227,7 +227,9 @@ TEST(GraphicsAllocationTest, givenAlwaysResidentAllocationWhenUpdateTaskCountThe TEST(GraphicsAllocationTest, givenDefaultGraphicsAllocationWhenInternalHandleIsBeingObtainedThenZeroIsReturned) { MockGraphicsAllocation graphicsAllocation; - EXPECT_EQ(0llu, graphicsAllocation.peekInternalHandle(nullptr)); + uint64_t handle = 0; + graphicsAllocation.peekInternalHandle(nullptr, handle); + EXPECT_EQ(0ull, handle); } TEST(GraphicsAllocationTest, givenDefaultGraphicsAllocationWhenGettingNumHandlesThenZeroIsReturned) { diff --git a/shared/test/unit_test/os_interface/linux/drm_memory_manager_localmem_prelim_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_memory_manager_localmem_prelim_tests.cpp index 88b212ee7a..026b292609 100644 --- a/shared/test/unit_test/os_interface/linux/drm_memory_manager_localmem_prelim_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_memory_manager_localmem_prelim_tests.cpp @@ -131,6 +131,46 @@ TEST_F(DrmMemoryManagerLocalMemoryPrelimTest, givenMultiRootDeviceEnvironmentAnd executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface); } +TEST_F(DrmMemoryManagerLocalMemoryPrelimTest, givenMultiRootDeviceEnvironmentAndMemoryInfoWhenCreateMultiGraphicsAllocationAndObtainFdFromHandleFailsThenNullptrIsReturned) { + uint32_t rootDevicesNumber = 3u; + MultiGraphicsAllocation multiGraphics(rootDevicesNumber); + RootDeviceIndicesContainer rootDeviceIndices; + auto osInterface = executionEnvironment->rootDeviceEnvironments[0]->osInterface.release(); + + executionEnvironment->prepareRootDeviceEnvironments(rootDevicesNumber); + for (uint32_t i = 0; i < rootDevicesNumber; i++) { + executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(defaultHwInfo.get()); + executionEnvironment->rootDeviceEnvironments[i]->initGmm(); + auto mock = new DrmQueryMock(*executionEnvironment->rootDeviceEnvironments[i]); + + std::vector regionInfo(2); + regionInfo[0].region = {drm_i915_gem_memory_class::I915_MEMORY_CLASS_SYSTEM, 0}; + regionInfo[1].region = {drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE, DrmMockHelper::getEngineOrMemoryInstanceValue(0, 0)}; + + mock->memoryInfo.reset(new MemoryInfo(regionInfo, *mock)); + mock->queryEngineInfo(); + mock->ioctlCallsCount = 0; + executionEnvironment->rootDeviceEnvironments[i]->osInterface = std::make_unique(); + executionEnvironment->rootDeviceEnvironments[i]->osInterface->setDriverModel(std::unique_ptr(mock)); + executionEnvironment->rootDeviceEnvironments[i]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock, 0u); + executionEnvironment->rootDeviceEnvironments[i]->initGmm(); + + rootDeviceIndices.push_back(i); + } + + memoryManager = new TestedDrmMemoryManager(true, false, false, *executionEnvironment); + executionEnvironment->memoryManager.reset(memoryManager); + + size_t size = 4096u; + AllocationProperties properties(rootDeviceIndex, true, size, AllocationType::BUFFER_HOST_MEMORY, false, {}); + + memoryManager->failOnObtainFdFromHandle = true; + auto ptr = memoryManager->createMultiGraphicsAllocationInSystemMemoryPool(rootDeviceIndices, properties, multiGraphics); + EXPECT_EQ(ptr, nullptr); + + executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface); +} + TEST_F(DrmMemoryManagerLocalMemoryPrelimTest, givenMultiRootDeviceEnvironmentAndMemoryInfoWhenCreateMultiGraphicsAllocationAndImportFailsThenNullptrIsReturned) { uint32_t rootDevicesNumber = 3u; MultiGraphicsAllocation multiGraphics(rootDevicesNumber); 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 01feef9a38..2bb700ecac 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 @@ -452,7 +452,25 @@ TEST_F(DrmMemoryManagerTest, whenPeekInternalHandleIsCalledThenBoIsReturned) { mock->outputFd = 1337; auto allocation = static_cast(this->memoryManager->allocateGraphicsMemoryWithProperties(createAllocationProperties(rootDeviceIndex, 10 * MemoryConstants::pageSize, true))); ASSERT_NE(allocation->getBO(), nullptr); - ASSERT_EQ(allocation->peekInternalHandle(this->memoryManager), static_cast(1337)); + uint64_t handle = 0; + int ret = allocation->peekInternalHandle(this->memoryManager, handle); + ASSERT_EQ(ret, 0); + ASSERT_EQ(handle, static_cast(1337)); + + memoryManager->freeGraphicsMemory(allocation); +} + +TEST_F(DrmMemoryManagerTest, whenPeekInternalHandleIsCalledAndObtainFdFromHandleFailsThenErrorIsReturned) { + mock->ioctl_expected.gemUserptr = 1; + mock->ioctl_expected.gemWait = 1; + mock->ioctl_expected.gemClose = 1; + mock->outputFd = 1337; + auto allocation = static_cast(this->memoryManager->allocateGraphicsMemoryWithProperties(createAllocationProperties(rootDeviceIndex, 10 * MemoryConstants::pageSize, true))); + ASSERT_NE(allocation->getBO(), nullptr); + memoryManager->failOnObtainFdFromHandle = true; + uint64_t handle = 0; + int ret = allocation->peekInternalHandle(this->memoryManager, handle); + ASSERT_EQ(ret, -1); memoryManager->freeGraphicsMemory(allocation); } @@ -469,11 +487,18 @@ TEST_F(DrmMemoryManagerTest, whenCallingPeekInternalHandleSeveralTimesThenSameHa ASSERT_NE(allocation->getBO(), nullptr); EXPECT_EQ(mock->outputFd, static_cast(expectedFd)); - uint64_t handle0 = allocation->peekInternalHandle(this->memoryManager); + uint64_t handle0 = 0; + int ret = allocation->peekInternalHandle(this->memoryManager, handle0); + ASSERT_EQ(ret, 0); EXPECT_NE(mock->outputFd, static_cast(expectedFd)); - uint64_t handle1 = allocation->peekInternalHandle(this->memoryManager); - uint64_t handle2 = allocation->peekInternalHandle(this->memoryManager); + uint64_t handle1 = 0; + uint64_t handle2 = 0; + + ret = allocation->peekInternalHandle(this->memoryManager, handle1); + ASSERT_EQ(ret, 0); + ret = allocation->peekInternalHandle(this->memoryManager, handle2); + ASSERT_EQ(ret, 0); ASSERT_EQ(handle0, expectedFd); ASSERT_EQ(handle1, expectedFd); @@ -491,8 +516,11 @@ TEST_F(DrmMemoryManagerTest, whenPeekInternalHandleWithHandleIdIsCalledThenBoIsR auto allocation = static_cast(this->memoryManager->allocateGraphicsMemoryWithProperties(createAllocationProperties(rootDeviceIndex, 10 * MemoryConstants::pageSize, true))); ASSERT_NE(allocation->getBO(), nullptr); + uint64_t handle = 0; uint32_t handleId = 0; - ASSERT_EQ(allocation->peekInternalHandle(this->memoryManager, handleId), static_cast(1337)); + int ret = allocation->peekInternalHandle(this->memoryManager, handleId, handle); + ASSERT_EQ(ret, 0); + ASSERT_EQ(handle, static_cast(1337)); memoryManager->freeGraphicsMemory(allocation); } @@ -510,11 +538,17 @@ TEST_F(DrmMemoryManagerTest, whenCallingPeekInternalHandleWithIdSeveralTimesThen EXPECT_EQ(mock->outputFd, static_cast(expectedFd)); uint32_t handleId = 0; - uint64_t handle0 = allocation->peekInternalHandle(this->memoryManager, handleId); + uint64_t handle0 = 0; + int ret = allocation->peekInternalHandle(this->memoryManager, handleId, handle0); + ASSERT_EQ(ret, 0); EXPECT_NE(mock->outputFd, static_cast(expectedFd)); - uint64_t handle1 = allocation->peekInternalHandle(this->memoryManager, handleId); - uint64_t handle2 = allocation->peekInternalHandle(this->memoryManager, handleId); + uint64_t handle1 = 0; + uint64_t handle2 = 0; + ret = allocation->peekInternalHandle(this->memoryManager, handleId, handle1); + ASSERT_EQ(ret, 0); + ret = allocation->peekInternalHandle(this->memoryManager, handleId, handle2); + ASSERT_EQ(ret, 0); ASSERT_EQ(handle0, expectedFd); ASSERT_EQ(handle1, expectedFd); @@ -3163,6 +3197,29 @@ TEST(DrmMemoryManagerWithExplicitExpectationsTest2, whenObtainFdFromHandleIsCall } } +TEST(DrmMemoryManagerWithExplicitExpectationsTest2, whenFailingToObtainFdFromHandleThenErrorIsReturned) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(4u); + for (auto i = 0u; i < 4u; i++) { + executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(defaultHwInfo.get()); + auto mock = new DrmMockCustom(*executionEnvironment->rootDeviceEnvironments[0]); + executionEnvironment->rootDeviceEnvironments[i]->osInterface = std::make_unique(); + executionEnvironment->rootDeviceEnvironments[i]->osInterface->setDriverModel(std::unique_ptr(mock)); + executionEnvironment->rootDeviceEnvironments[i]->initGmm(); + } + auto memoryManager = std::make_unique(false, false, false, *executionEnvironment); + for (auto i = 0u; i < 4u; i++) { + auto mock = executionEnvironment->rootDeviceEnvironments[i]->osInterface->getDriverModel()->as(); + + int boHandle = 3; + mock->outputFd = -1; + mock->ioctl_res = -1; + mock->ioctl_expected.handleToPrimeFd = 1; + auto fdHandle = memoryManager->obtainFdFromHandle(boHandle, i); + EXPECT_EQ(-1, fdHandle); + } +} + TEST_F(DrmMemoryManagerTest, givenSvmCpuAllocationWhenSizeAndAlignmentProvidedThenAllocateMemoryAndReserveGpuVa) { mock->ioctl_expected.gemUserptr = 1; mock->ioctl_expected.gemWait = 1;