From 51d767daea3b6adfdc9be75d8813608e7c48f0a0 Mon Sep 17 00:00:00 2001 From: Jaime Arteaga Date: Thu, 19 Jan 2023 09:14:03 +0000 Subject: [PATCH] refactor: Add IPC memory data Refactor structure and add field to pass USM memory type. To maintain backwards compatibility with current applications, pass 0 as type for device allocations, and 1 for host allocations. Related-To: LOCI-3771 Signed-off-by: Jaime Arteaga --- .../core/source/context/context_imp.cpp | 58 ++++++---- level_zero/core/source/context/context_imp.h | 8 ++ .../unit_tests/fixtures/memory_ipc_fixture.h | 26 +++-- .../unit_tests/sources/memory/test_memory.cpp | 105 ++++++++++++++++++ .../memory/test_memory_drm_or_wddm.cpp | 20 ++++ shared/source/unified_memory/unified_memory.h | 5 + 6 files changed, 195 insertions(+), 27 deletions(-) diff --git a/level_zero/core/source/context/context_imp.cpp b/level_zero/core/source/context/context_imp.cpp index 39351a479d..365c7243b6 100644 --- a/level_zero/core/source/context/context_imp.cpp +++ b/level_zero/core/source/context/context_imp.cpp @@ -500,10 +500,13 @@ ze_result_t ContextImp::getIpcMemHandle(const void *ptr, return ZE_RESULT_ERROR_OUT_OF_HOST_MEMORY; } - memcpy_s(reinterpret_cast(pIpcHandle->data), - sizeof(ze_ipc_mem_handle_t), - &handle, - sizeof(handle)); + IpcMemoryData &ipcData = *reinterpret_cast(pIpcHandle->data); + ipcData = {}; + ipcData.handle = handle; + auto type = allocData->memoryType; + if (type == HOST_UNIFIED_MEMORY) { + ipcData.type = static_cast(InternalIpcMemoryType::IPC_HOST_UNIFIED_MEMORY); + } return ZE_RESULT_SUCCESS; } @@ -527,16 +530,23 @@ ze_result_t ContextImp::getIpcMemHandles(const void *ptr, return ZE_RESULT_SUCCESS; } + auto type = allocData->memoryType; + auto ipcType = InternalIpcMemoryType::IPC_DEVICE_UNIFIED_MEMORY; + if (type == HOST_UNIFIED_MEMORY) { + ipcType = InternalIpcMemoryType::IPC_HOST_UNIFIED_MEMORY; + } + for (uint32_t i = 0; i < *numIpcHandles; 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(int)); + + IpcMemoryData &ipcData = *reinterpret_cast(pIpcHandles[i].data); + ipcData = {}; + ipcData.handle = handle; + ipcData.type = static_cast(ipcType); } return ZE_RESULT_SUCCESS; @@ -548,15 +558,23 @@ ze_result_t ContextImp::openIpcMemHandle(ze_device_handle_t hDevice, const ze_ipc_mem_handle_t &pIpcHandle, ze_ipc_memory_flags_t flags, void **ptr) { - uint64_t handle = 0u; - memcpy_s(&handle, - sizeof(handle), - pIpcHandle.data, - sizeof(handle)); + const IpcMemoryData &ipcData = *reinterpret_cast(pIpcHandle.data); + + uint64_t handle = ipcData.handle; + uint8_t type = ipcData.type; + + NEO::AllocationType allocationType = NEO::AllocationType::UNKNOWN; + if (type == static_cast(InternalIpcMemoryType::IPC_DEVICE_UNIFIED_MEMORY)) { + allocationType = NEO::AllocationType::BUFFER; + } else if (type == static_cast(InternalIpcMemoryType::IPC_HOST_UNIFIED_MEMORY)) { + allocationType = NEO::AllocationType::BUFFER_HOST_MEMORY; + } else { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } *ptr = getMemHandlePtr(hDevice, handle, - NEO::AllocationType::BUFFER, + allocationType, flags); if (nullptr == *ptr) { return ZE_RESULT_ERROR_INVALID_ARGUMENT; @@ -574,11 +592,13 @@ ze_result_t ContextImp::openIpcMemHandles(ze_device_handle_t hDevice, handles.reserve(numIpcHandles); for (uint32_t i = 0; i < numIpcHandles; i++) { - uint64_t handle = 0; - memcpy_s(&handle, - sizeof(handle), - reinterpret_cast(pIpcHandles[i].data), - sizeof(handle)); + const IpcMemoryData &ipcData = *reinterpret_cast(pIpcHandles[i].data); + uint64_t handle = ipcData.handle; + + if (ipcData.type != static_cast(InternalIpcMemoryType::IPC_DEVICE_UNIFIED_MEMORY)) { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + handles.push_back(static_cast(handle)); } auto neoDevice = Device::fromHandle(hDevice)->getNEODevice()->getRootDevice(); diff --git a/level_zero/core/source/context/context_imp.h b/level_zero/core/source/context/context_imp.h index 652207fae2..0b562efe2c 100644 --- a/level_zero/core/source/context/context_imp.h +++ b/level_zero/core/source/context/context_imp.h @@ -19,6 +19,14 @@ struct StructuresLookupTable; struct DriverHandleImp; struct Device; +#pragma pack(1) +struct IpcMemoryData { + uint64_t handle = 0; + uint8_t type = 0; +}; +#pragma pack() +static_assert(sizeof(IpcMemoryData) <= ZE_MAX_IPC_HANDLE_SIZE, "IpcMemoryData is bigger than ZE_MAX_IPC_HANDLE_SIZE"); + struct ContextImp : Context { ContextImp(DriverHandle *driverHandle); ~ContextImp() override = default; 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 4c79143508..cc4fc13d72 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 @@ -377,10 +377,15 @@ struct ContextGetIpcHandleMock : public L0::ContextImp { ze_result_t getIpcMemHandle(const void *ptr, ze_ipc_mem_handle_t *pIpcHandle) override { uint64_t handle = driverHandle->mockFd; - memcpy_s(reinterpret_cast(pIpcHandle->data), - sizeof(ze_ipc_mem_handle_t), - &handle, - sizeof(handle)); + NEO::SvmAllocationData *allocData = this->driverHandle->svmAllocsManager->getSVMAlloc(ptr); + + IpcMemoryData &ipcData = *reinterpret_cast(pIpcHandle->data); + ipcData = {}; + ipcData.handle = handle; + auto type = Context::parseUSMType(allocData->memoryType); + if (type == ZE_MEMORY_TYPE_HOST) { + ipcData.type = static_cast(InternalIpcMemoryType::IPC_HOST_UNIFIED_MEMORY); + } return ZE_RESULT_SUCCESS; } @@ -552,10 +557,15 @@ struct ContextIpcMock : public L0::ContextImp { ze_result_t getIpcMemHandle(const void *ptr, ze_ipc_mem_handle_t *pIpcHandle) override { uint64_t handle = mockFd; - memcpy_s(reinterpret_cast(pIpcHandle->data), - sizeof(ze_ipc_mem_handle_t), - &handle, - sizeof(handle)); + NEO::SvmAllocationData *allocData = this->driverHandle->svmAllocsManager->getSVMAlloc(ptr); + + IpcMemoryData &ipcData = *reinterpret_cast(pIpcHandle->data); + ipcData = {}; + ipcData.handle = handle; + auto type = Context::parseUSMType(allocData->memoryType); + if (type == ZE_MEMORY_TYPE_HOST) { + ipcData.type = static_cast(InternalIpcMemoryType::IPC_HOST_UNIFIED_MEMORY); + } return ZE_RESULT_SUCCESS; } 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 1fb13e0701..31766eaf37 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 @@ -109,6 +109,39 @@ TEST_F(MemoryExportImportImplicitScalingTest, EXPECT_EQ(ZE_RESULT_SUCCESS, result); } +TEST_F(MemoryExportImportImplicitScalingTest, + whenCallingOpenIpcHandlesWithIpcHandleAndHostTypeAllocationTheninvalidArgumentIsReturned) { + size_t size = 10; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_host_mem_alloc_desc_t hostDesc = {}; + ze_result_t result = context->allocHostMem(&hostDesc, + 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); + + std::vector ipcHandles(numIpcHandles); + result = context->getIpcMemHandles(ptr, &numIpcHandles, ipcHandles.data()); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new NEO::OSInterface()); + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::make_unique()); + + ze_ipc_memory_flags_t flags = {}; + void *ipcPtr; + result = context->openIpcMemHandles(device->toHandle(), numIpcHandles, ipcHandles.data(), flags, &ipcPtr); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + TEST_F(MemoryExportImportImplicitScalingTest, whenCallingOpenIpcHandlesWithIpcHandleThenDeviceAllocationIsReturned) { size_t size = 10; @@ -146,6 +179,78 @@ TEST_F(MemoryExportImportImplicitScalingTest, EXPECT_EQ(ZE_RESULT_SUCCESS, result); } +TEST_F(MemoryExportImportImplicitScalingTest, + whenCallingOpenIpcHandleWithIpcHandleAndSharedMemoryTypeThenInvalidArgumentIsReturned) { + DebugManagerStateRestore restorer; + DebugManager.flags.EnableImplicitScaling.set(0u); + + 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); + + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new NEO::OSInterface()); + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::make_unique()); + + ze_ipc_memory_flags_t flags = {}; + void *ipcPtr; + + IpcMemoryData &ipcData = *reinterpret_cast(ipcHandle.data); + ipcData.type = static_cast(ZE_MEMORY_TYPE_SHARED); + + result = context->openIpcMemHandle(device->toHandle(), ipcHandle, flags, &ipcPtr); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryExportImportImplicitScalingTest, + whenCallingOpenIpcHandleWithIpcHandleAndHostMemoryTypeThenInvalidArgumentIsReturned) { + DebugManagerStateRestore restorer; + DebugManager.flags.EnableImplicitScaling.set(0u); + + 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); + + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new NEO::OSInterface()); + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::make_unique()); + + ze_ipc_memory_flags_t flags = {}; + void *ipcPtr; + + IpcMemoryData &ipcData = *reinterpret_cast(ipcHandle.data); + ipcData.type = static_cast(ZE_MEMORY_TYPE_HOST); + + result = context->openIpcMemHandle(device->toHandle(), ipcHandle, flags, &ipcPtr); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, result); + + result = context->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + TEST_F(MemoryExportImportImplicitScalingTest, whenCallingImportFdHandlesWithAllocationPointerThenAllocationIsReturned) { size_t size = 10; 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 e65954c0a5..56b618ec0c 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 @@ -46,6 +46,26 @@ TEST_F(MemoryIPCTests, EXPECT_EQ(ZE_RESULT_SUCCESS, result); } +TEST_F(MemoryIPCTests, + whenCallingGetIpcHandleWithHostAllocationThenSuccessIsReturned) { + size_t size = 10; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_host_mem_alloc_desc_t hostDesc = {}; + ze_result_t result = context->allocHostMem(&hostDesc, + 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); +} + TEST_F(MemoryIPCTests, whenCallingOpenIpcHandleWithIpcHandleThenDeviceAllocationIsReturned) { size_t size = 10; diff --git a/shared/source/unified_memory/unified_memory.h b/shared/source/unified_memory/unified_memory.h index a20dc6bde6..4abde88270 100644 --- a/shared/source/unified_memory/unified_memory.h +++ b/shared/source/unified_memory/unified_memory.h @@ -17,6 +17,11 @@ enum InternalMemoryType : uint32_t { SHARED_UNIFIED_MEMORY = 0b1000 }; +enum class InternalIpcMemoryType : uint32_t { + IPC_DEVICE_UNIFIED_MEMORY = 0, + IPC_HOST_UNIFIED_MEMORY = 1 +}; + enum TransferType : uint32_t { HOST_NON_USM_TO_HOST_USM = 0, HOST_NON_USM_TO_DEVICE_USM = 1,