diff --git a/level_zero/core/source/context/context_imp_drm/context_imp_drm.cpp b/level_zero/core/source/context/context_imp_drm/context_imp_drm.cpp index 6737bf78d1..bde67c146b 100644 --- a/level_zero/core/source/context/context_imp_drm/context_imp_drm.cpp +++ b/level_zero/core/source/context/context_imp_drm/context_imp_drm.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 Intel Corporation + * Copyright (C) 2022-2025 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -7,6 +7,7 @@ #include "shared/source/device/device.h" #include "shared/source/memory_manager/unified_memory_manager.h" +#include "shared/source/os_interface/linux/sys_calls.h" #include "level_zero/core/source/context/context_imp.h" #include "level_zero/core/source/device/device.h" @@ -23,6 +24,26 @@ bool ContextImp::isShareableMemory(const void *exportDesc, bool exportableMemory void *ContextImp::getMemHandlePtr(ze_device_handle_t hDevice, uint64_t handle, NEO::AllocationType allocationType, ze_ipc_memory_flags_t flags) { auto neoDevice = Device::fromHandle(hDevice)->getNEODevice(); + bool pidfdOrSocket = false; + if (NEO::debugManager.flags.EnablePidFdOrSocketsForIpc.get() != -1) { + pidfdOrSocket = !!(NEO::debugManager.flags.EnablePidFdOrSocketsForIpc.get()); + } + if (pidfdOrSocket) { + // With pidfd approach extract parent pid and target fd before importing handle + pid_t exporterPid = 0; + unsigned int flags = 0u; + int pidfd = NEO::SysCalls::pidfdopen(exporterPid, flags); + if (pidfd == -1) { + PRINT_DEBUG_STRING(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "pidfd_open Syscall failed, using fallback mechanism for IPC handle exchange\n"); + } else { + unsigned int flags = 0u; + int newfd = NEO::SysCalls::pidfdgetfd(pidfd, 0, flags); + if (newfd < 0) { + PRINT_DEBUG_STRING(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "pidfd_getfd Syscall failed, using fallback mechanism for IPC handle exchange\n"); + } + } + } + NEO::SvmAllocationData allocDataInternal(neoDevice->getRootDeviceIndex()); return this->driverHandle->importFdHandle(neoDevice, flags, handle, allocationType, nullptr, nullptr, allocDataInternal); } diff --git a/level_zero/core/test/unit_tests/sources/context/test_context_drm.cpp b/level_zero/core/test/unit_tests/sources/context/test_context_drm.cpp index 1e9111030f..5d8321222e 100644 --- a/level_zero/core/test/unit_tests/sources/context/test_context_drm.cpp +++ b/level_zero/core/test/unit_tests/sources/context/test_context_drm.cpp @@ -1,11 +1,12 @@ /* - * Copyright (C) 2020-2023 Intel Corporation + * Copyright (C) 2020-2025 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/built_ins/sip.h" +#include "shared/source/os_interface/linux/sys_calls.h" #include "shared/test/common/mocks/mock_command_stream_receiver.h" #include "shared/test/common/mocks/mock_compilers.h" #include "shared/test/common/mocks/mock_cpu_page_fault_manager.h" @@ -13,6 +14,7 @@ #include "shared/test/common/mocks/mock_graphics_allocation.h" #include "shared/test/common/mocks/mock_memory_manager.h" #include "shared/test/common/mocks/mock_svm_manager.h" +#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" #include "shared/test/common/test_macros/test.h" #include "level_zero/core/source/context/context_imp.h" @@ -69,5 +71,52 @@ TEST_F(GetMemHandlePtrTest, whenCallingGetMemHandlePtrWithInvalidHandleThenNullp EXPECT_EQ(nullptr, context->getMemHandlePtr(device, handle, NEO::AllocationType::buffer, 0)); } +TEST_F(GetMemHandlePtrTest, whenCallingGetMemHandlePtrWithPidfdMethodAndSyscallsReturnSuccessThenValidHandleIsReturned) { + DebugManagerStateRestore restorer; + debugManager.flags.EnablePidFdOrSocketsForIpc.set(1); + VariableBackup pidfdOpenCalledBackup(&NEO::SysCalls::pidfdopenCalled, 0u); + VariableBackup pidfdGetFdCalledBackup(&NEO::SysCalls::pidfdgetfdCalled, 0u); + + uint64_t handle = 57; + + // Test Successfully returning fd Handle + EXPECT_NE(nullptr, context->getMemHandlePtr(device, handle, NEO::AllocationType::buffer, 0)); + EXPECT_EQ(1, NEO::SysCalls::pidfdopenCalled); + EXPECT_EQ(1, NEO::SysCalls::pidfdgetfdCalled); +} + +TEST_F(GetMemHandlePtrTest, whenCallingGetMemHandlePtrWithPidfdMethodAndPidfdOpenSyscallReturnFailThenPidfdGetNotCalled) { + DebugManagerStateRestore restorer; + debugManager.flags.EnablePidFdOrSocketsForIpc.set(1); + + VariableBackup pidfdOpenCalledBackup(&NEO::SysCalls::pidfdopenCalled, 0u); + VariableBackup pidfdGetFdCalledBackup(&NEO::SysCalls::pidfdgetfdCalled, 0u); + VariableBackup mockPidfdOpen(&NEO::SysCalls::sysCallsPidfdOpen, [](pid_t, unsigned int) -> int { + return -1; + }); + + uint64_t handle = 57; + + EXPECT_NE(nullptr, context->getMemHandlePtr(device, handle, NEO::AllocationType::buffer, 0)); + EXPECT_EQ(1, NEO::SysCalls::pidfdopenCalled); + EXPECT_EQ(0, NEO::SysCalls::pidfdgetfdCalled); +} + +TEST_F(GetMemHandlePtrTest, whenCallingGetMemHandlePtrWithPidfdMethodAndPidfdGetSyscallReturnFailThenCorrectHandleIsReturned) { + DebugManagerStateRestore restorer; + debugManager.flags.EnablePidFdOrSocketsForIpc.set(1); + + VariableBackup pidfdOpenCalledBackup(&NEO::SysCalls::pidfdopenCalled, 0u); + VariableBackup pidfdGetFdCalledBackup(&NEO::SysCalls::pidfdgetfdCalled, 0u); + VariableBackup mockPidfdGet(&NEO::SysCalls::sysCallsPidfdGetfd, [](int, int, unsigned int) -> int { + return -1; + }); + uint64_t handle = 57; + + EXPECT_NE(nullptr, context->getMemHandlePtr(device, handle, NEO::AllocationType::buffer, 0)); + EXPECT_EQ(1, NEO::SysCalls::pidfdopenCalled); + EXPECT_EQ(1, NEO::SysCalls::pidfdgetfdCalled); +} + } // namespace ult } // namespace L0 diff --git a/shared/source/debug_settings/debug_variables_base.inl b/shared/source/debug_settings/debug_variables_base.inl index 489bcf0c5f..96f52b7bde 100644 --- a/shared/source/debug_settings/debug_variables_base.inl +++ b/shared/source/debug_settings/debug_variables_base.inl @@ -315,6 +315,7 @@ DECLARE_DEBUG_VARIABLE(int32_t, ForceIndirectDetectionForCMKernels, -1, "-1: def DECLARE_DEBUG_VARIABLE(int32_t, PipelinedEuThreadArbitration, -1, "-1: default. 1: Use Walker field, 0: Use StateComputeMode command to program pipelinedEuThreadArbitration") DECLARE_DEBUG_VARIABLE(bool, ForceUseOnlyGlobalTimestamps, 0, "0- default disabled, 1: enable use only global timestamp") DECLARE_DEBUG_VARIABLE(int32_t, GetSipBinaryFromExternalLib, -1, "-1: default, 0: disabled, 1: enabled. If enabled, then retrieve Sip from external library") +DECLARE_DEBUG_VARIABLE(int32_t, EnablePidFdOrSocketsForIpc, -1, "-1: default, 0: disabled (default), 1: enabled. If enabled, L0 IPC handles are opaque and pidfd or sockets are used for IPC exchange") /*LOGGING FLAGS*/ DECLARE_DEBUG_VARIABLE(int32_t, PrintDriverDiagnostics, -1, "prints driver diagnostics messages to standard output, value corresponds to hint level") diff --git a/shared/test/common/test_files/igdrcl.config b/shared/test/common/test_files/igdrcl.config index f9d40ecbab..f35351c610 100644 --- a/shared/test/common/test_files/igdrcl.config +++ b/shared/test/common/test_files/igdrcl.config @@ -670,4 +670,5 @@ GetSipBinaryFromExternalLib = -1 LogUsmReuse = 0 ExperimentalUSMAllocationReuseLimitThreshold = -1 UseIgcAsFcl = 0 +EnablePidFdOrSocketsForIpc = -1 # Please don't edit below this line