diff --git a/level_zero/core/source/context/context_imp.cpp b/level_zero/core/source/context/context_imp.cpp index 6c9f57ca84..aa15d61f7b 100644 --- a/level_zero/core/source/context/context_imp.cpp +++ b/level_zero/core/source/context/context_imp.cpp @@ -779,6 +779,14 @@ ze_result_t ContextImp::getIpcMemHandlesImpl(const void *ptr, ipcType = InternalIpcMemoryType::hostUnifiedMemory; } + bool pidfdOrSocket = true; + for (auto &device : this->driverHandle->devices) { + auto &productHelper = device->getNEODevice()->getProductHelper(); + if (!productHelper.isPidFdOrSocketForIpcSupported()) { + pidfdOrSocket = false; + break; + } + } uint32_t loopCount = numIpcHandles ? *numIpcHandles : 1u; for (uint32_t i = 0u; i < loopCount; i++) { uint64_t handle = 0; @@ -789,11 +797,14 @@ ze_result_t ContextImp::getIpcMemHandlesImpl(const void *ptr, memoryManager->registerIpcExportedAllocation(alloc); - using IpcDataT = IpcMemoryData; - IpcDataT &ipcData = *reinterpret_cast(pIpcHandles[i].data); - setIPCHandleData(alloc, handle, ipcData, reinterpret_cast(ptr), static_cast(ipcType), usmPool); + if (pidfdOrSocket) { + IpcOpaqueMemoryData &ipcData = *reinterpret_cast(pIpcHandles[i].data); + setIPCHandleData(alloc, handle, ipcData, reinterpret_cast(ptr), static_cast(ipcType), usmPool); + } else { + IpcMemoryData &ipcData = *reinterpret_cast(pIpcHandles[i].data); + setIPCHandleData(alloc, handle, ipcData, reinterpret_cast(ptr), static_cast(ipcType), usmPool); + } } - return ZE_RESULT_SUCCESS; } diff --git a/level_zero/core/source/context/context_imp.h b/level_zero/core/source/context/context_imp.h index abeb4c1584..c7d857c8e0 100644 --- a/level_zero/core/source/context/context_imp.h +++ b/level_zero/core/source/context/context_imp.h @@ -202,8 +202,16 @@ struct ContextImp : Context, NEO::NonCopyableAndNonMovableClass { std::map::iterator ipcHandleIterator; ipcData = {}; - ipcData.handle = handle; - ipcData.type = type; + if constexpr (std::is_same_v) { + ipcData.handle = handle; + ipcData.type = type; + } else if constexpr (std::is_same_v) { + printf("opaque type used\n"); + ipcData.memoryType = type; + ipcData.processId = NEO::SysCalls::getCurrentProcessId(); + ipcData.type = IpcHandleType::fdHandle; + ipcData.handle.fd = static_cast(handle); + } if (usmPool) { ipcData.poolOffset = usmPool->getOffsetInPool(addrToPtr(ptrAddress)); @@ -220,7 +228,9 @@ struct ContextImp : Context, NEO::NonCopyableAndNonMovableClass { handleTracking->refcnt = 1; handleTracking->ptr = ptrAddress; handleTracking->handle = handle; - handleTracking->ipcData = ipcData; + if constexpr (std::is_same_v) { + handleTracking->ipcData = ipcData; + } this->driverHandle->getIPCHandleMap().insert(std::pair(handle, handleTracking)); } } diff --git a/level_zero/core/source/driver/driver_handle_imp.h b/level_zero/core/source/driver/driver_handle_imp.h index 01c2a5b2f1..06eb46d479 100644 --- a/level_zero/core/source/driver/driver_handle_imp.h +++ b/level_zero/core/source/driver/driver_handle_imp.h @@ -11,6 +11,7 @@ #include "shared/source/memory_manager/graphics_allocation.h" #include "shared/source/memory_manager/unified_memory_pooling.h" #include "shared/source/os_interface/os_library.h" +#include "shared/source/os_interface/sys_calls_common.h" #include "level_zero/api/extensions/public/ze_exp_ext.h" #include "level_zero/core/source/driver/driver_handle.h" @@ -36,6 +37,24 @@ struct IpcMemoryData { #pragma pack() static_assert(sizeof(IpcMemoryData) <= ZE_MAX_IPC_HANDLE_SIZE, "IpcMemoryData is bigger than ZE_MAX_IPC_HANDLE_SIZE"); +enum class IpcHandleType : uint8_t { + fdHandle = 0, + maxHandle +}; + +struct IpcOpaqueMemoryData { + union IpcHandle { + int fd; + uint64_t reserved; + }; + IpcHandle handle = {}; + uint64_t poolOffset = 0; + unsigned int processId = 0; + IpcHandleType type = IpcHandleType::maxHandle; + uint8_t memoryType = 0; +}; +static_assert(sizeof(IpcOpaqueMemoryData) <= ZE_MAX_IPC_HANDLE_SIZE, "IpcOpaqueMemoryData is bigger than ZE_MAX_IPC_HANDLE_SIZE"); + struct IpcHandleTracking { uint64_t refcnt = 0; NEO::GraphicsAllocation *alloc = nullptr; diff --git a/level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.cpp b/level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.cpp index 3a2a4e6c94..f4f1778fbe 100644 --- a/level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.cpp +++ b/level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.cpp @@ -553,5 +553,31 @@ void MemoryExportImportImplicitScalingTest::TearDown() { delete currMemoryManager; } +void MemoryGetIpcHandlePidfdTest::SetUp() { + neoDevice = + NEO::MockDevice::createWithNewExecutionEnvironment(NEO::defaultHwInfo.get()); + auto mockBuiltIns = new MockBuiltins(); + MockRootDeviceEnvironment::resetBuiltins(neoDevice->executionEnvironment->rootDeviceEnvironments[0].get(), mockBuiltIns); + NEO::DeviceVector devices; + devices.push_back(std::unique_ptr(neoDevice)); + driverHandle = std::make_unique(); + driverHandle->initialize(std::move(devices)); + prevMemoryManager = driverHandle->getMemoryManager(); + currMemoryManager = new MemoryManagerOpenIpcMock(*neoDevice->executionEnvironment); + driverHandle->setMemoryManager(currMemoryManager); + device = driverHandle->devices[0]; + + context = std::make_unique(driverHandle.get()); + EXPECT_NE(context, nullptr); + context->getDevices().insert(std::make_pair(device->getRootDeviceIndex(), device->toHandle())); + auto neoDevice = device->getNEODevice(); + context->rootDeviceIndices.pushUnique(neoDevice->getRootDeviceIndex()); + context->deviceBitfields.insert({neoDevice->getRootDeviceIndex(), neoDevice->getDeviceBitfield()}); +} +void MemoryGetIpcHandlePidfdTest::TearDown() { + driverHandle->setMemoryManager(prevMemoryManager); + delete currMemoryManager; +} + } // namespace ult } // namespace L0 \ No newline at end of file diff --git a/level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.h b/level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.h index ee0f009a55..9b2c11c9c4 100644 --- a/level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.h +++ b/level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.h @@ -402,5 +402,17 @@ struct MemoryExportImportImplicitScalingTest : public ::testing::Test { std::unique_ptr context; }; +struct MemoryGetIpcHandlePidfdTest : public ::testing::Test { + void SetUp() override; + void TearDown() override; + + NEO::MemoryManager *prevMemoryManager = nullptr; + NEO::MemoryManager *currMemoryManager = nullptr; + std::unique_ptr driverHandle; + NEO::MockDevice *neoDevice = nullptr; + L0::Device *device = nullptr; + std::unique_ptr context; +}; + } // namespace ult } // namespace L0 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 index 8031e5393c..cc4cf81970 100644 --- 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 @@ -990,5 +990,28 @@ TEST_F(MemoryExportImportImplicitScalingTest, EXPECT_EQ(ZE_RESULT_SUCCESS, result); } +TEST_F(MemoryGetIpcHandlePidfdTest, + givenCallToGetIpcHandleWithDeviceAllocationWithPidFdSocketMethodThenIpcHandleIsReturned) { + DebugManagerStateRestore restorer; + debugManager.flags.EnablePidFdOrSocketsForIpc.set(1); + 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); + + 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); +} + } // namespace ult } // namespace L0 diff --git a/level_zero/core/test/unit_tests/sources/memory/test_memory_drm_or_wddm.cpp b/level_zero/core/test/unit_tests/sources/memory/test_memory_drm_or_wddm.cpp index fb14e9a47b..44f109ba12 100644 --- a/level_zero/core/test/unit_tests/sources/memory/test_memory_drm_or_wddm.cpp +++ b/level_zero/core/test/unit_tests/sources/memory/test_memory_drm_or_wddm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Intel Corporation + * Copyright (C) 2022-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -9,7 +9,10 @@ #include "shared/test/common/mocks/mock_device.h" #include "shared/test/common/mocks/mock_driver_model.h" #include "shared/test/common/mocks/mock_memory_manager.h" +#include "shared/test/common/os_interface/linux/drm_mock_extended.h" +#include "shared/test/common/test_macros/hw_test.h" +#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h" #include "level_zero/core/test/unit_tests/fixtures/memory_ipc_fixture.h" #include "level_zero/core/test/unit_tests/mocks/mock_built_ins.h" @@ -1031,5 +1034,47 @@ TEST_F(MemoryExportImportTest, EXPECT_EQ(ZE_RESULT_SUCCESS, result); } +class DrmIpcPidfdFixture : public DeviceFixture { + public: + void setUp() { + DeviceFixture::setUp(); + + auto &rootDeviceEnvironment{*neoDevice->executionEnvironment->rootDeviceEnvironments[0]}; + drmMock = new DrmMock(rootDeviceEnvironment); + + rootDeviceEnvironment.osInterface.reset(new NEO::OSInterface); + rootDeviceEnvironment.osInterface->setDriverModel(std::unique_ptr(drmMock)); + } + void tearDown() { + DeviceFixture::tearDown(); + } + + DrmMock *drmMock = nullptr; +}; + +using MemoryDrmIpcPidfdTests = Test; +TEST_F(MemoryDrmIpcPidfdTests, + givenCallToGetIpcHandleWithDeviceAllocationWithPidFdSocketMethodAndMockDrmThenIpcHandleIsReturned) { + DebugManagerStateRestore restorer; + debugManager.flags.EnablePidFdOrSocketsForIpc.set(1); + 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); + + 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); +} + } // namespace ult } // namespace L0