diff --git a/level_zero/core/source/driver/driver_handle_imp.h b/level_zero/core/source/driver/driver_handle_imp.h index 89c6e88aa5..815806cdae 100644 --- a/level_zero/core/source/driver/driver_handle_imp.h +++ b/level_zero/core/source/driver/driver_handle_imp.h @@ -93,6 +93,7 @@ struct DriverHandleImp : public DriverHandle { std::vector devices; // Spec extensions const std::vector> extensionsSupported = { + {ZE_RELAXED_ALLOCATION_LIMITS_EXP_NAME, ZE_RELAXED_ALLOCATION_LIMITS_EXP_VERSION_CURRENT}, {ZE_MODULE_PROGRAM_EXP_NAME, ZE_MODULE_PROGRAM_EXP_VERSION_CURRENT}, {ZE_GLOBAL_OFFSET_EXP_NAME, ZE_GLOBAL_OFFSET_EXP_VERSION_CURRENT}}; diff --git a/level_zero/core/source/memory/memory.cpp b/level_zero/core/source/memory/memory.cpp index 1cfa6ac531..c176650383 100644 --- a/level_zero/core/source/memory/memory.cpp +++ b/level_zero/core/source/memory/memory.cpp @@ -133,11 +133,8 @@ ze_result_t DriverHandleImp::allocHostMem(const ze_host_mem_alloc_desc_t *hostDe ze_result_t DriverHandleImp::allocDeviceMem(ze_device_handle_t hDevice, const ze_device_mem_alloc_desc_t *deviceDesc, size_t size, size_t alignment, void **ptr) { - if (size > this->devices[0]->getNEODevice()->getHardwareCapabilities().maxMemAllocSize) { - *ptr = nullptr; - return ZE_RESULT_ERROR_UNSUPPORTED_SIZE; - } + bool relaxedSizeAllowed = false; if (deviceDesc->pNext) { const ze_base_desc_t *extendedDesc = reinterpret_cast(deviceDesc->pNext); if (extendedDesc->stype == ZE_STRUCTURE_TYPE_EXTERNAL_MEMORY_EXPORT_DESC) { @@ -160,9 +157,22 @@ ze_result_t DriverHandleImp::allocDeviceMem(ze_device_handle_t hDevice, const ze return ZE_RESULT_ERROR_INVALID_ARGUMENT; } return ZE_RESULT_SUCCESS; + } else if (extendedDesc->stype == ZE_STRUCTURE_TYPE_RELAXED_ALLOCATION_LIMITS_EXP_DESC) { + const ze_relaxed_allocation_limits_exp_desc_t *relaxedLimitsDesc = + reinterpret_cast(extendedDesc); + if (!(relaxedLimitsDesc->flags & ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE)) { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + relaxedSizeAllowed = true; } } + if (relaxedSizeAllowed == false && + (size > this->devices[0]->getNEODevice()->getHardwareCapabilities().maxMemAllocSize)) { + *ptr = nullptr; + return ZE_RESULT_ERROR_UNSUPPORTED_SIZE; + } + auto neoDevice = Device::fromHandle(hDevice)->getNEODevice(); auto rootDeviceIndex = neoDevice->getRootDeviceIndex(); auto deviceBitfields = this->deviceBitfields; @@ -192,6 +202,25 @@ ze_result_t DriverHandleImp::allocSharedMem(ze_device_handle_t hDevice, const ze size_t size, size_t alignment, void **ptr) { + bool relaxedSizeAllowed = false; + if (deviceDesc->pNext) { + const ze_base_desc_t *extendedDesc = reinterpret_cast(deviceDesc->pNext); + if (extendedDesc->stype == ZE_STRUCTURE_TYPE_RELAXED_ALLOCATION_LIMITS_EXP_DESC) { + const ze_relaxed_allocation_limits_exp_desc_t *relaxedLimitsDesc = + reinterpret_cast(extendedDesc); + if (!(relaxedLimitsDesc->flags & ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE)) { + return ZE_RESULT_ERROR_INVALID_ARGUMENT; + } + relaxedSizeAllowed = true; + } + } + + if (relaxedSizeAllowed == false && + (size > this->devices[0]->getNEODevice()->getHardwareCapabilities().maxMemAllocSize)) { + *ptr = nullptr; + return ZE_RESULT_ERROR_UNSUPPORTED_SIZE; + } + auto neoDevice = this->devices[0]->getNEODevice(); auto deviceBitfields = this->deviceBitfields; @@ -210,11 +239,6 @@ ze_result_t DriverHandleImp::allocSharedMem(ze_device_handle_t hDevice, const ze unifiedMemoryProperties.allocationFlags.flags.locallyUncachedResource = 1; } - if (size > neoDevice->getDeviceInfo().maxMemAllocSize) { - *ptr = nullptr; - return ZE_RESULT_ERROR_UNSUPPORTED_SIZE; - } - auto usmPtr = svmAllocsManager->createSharedUnifiedMemoryAllocation(size, unifiedMemoryProperties, 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 69f0f4c9c8..c714c207b8 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 @@ -88,6 +88,206 @@ TEST_F(MemoryTest, whenAllocatingSharedMemoryWithUncachedFlagThenLocallyUncached ASSERT_EQ(result, ZE_RESULT_SUCCESS); } +struct SVMAllocsManagerRelaxedSizeMock : public NEO::SVMAllocsManager { + SVMAllocsManagerRelaxedSizeMock(MemoryManager *memoryManager) : NEO::SVMAllocsManager(memoryManager, false) {} + void *createUnifiedMemoryAllocation(size_t size, + const UnifiedMemoryProperties &svmProperties) override { + return alignedMalloc(4096u, 4096u); + } + + void *createSharedUnifiedMemoryAllocation(size_t size, + const UnifiedMemoryProperties &svmProperties, + void *cmdQ) override { + return alignedMalloc(4096u, 4096u); + } +}; + +struct DriverHandleRelaxedSizeMock : public DriverHandleImp { + ze_result_t freeMem(const void *ptr) override { + alignedFree(const_cast(ptr)); + return ZE_RESULT_SUCCESS; + } +}; + +struct MemoryRelaxedSizeTests : public ::testing::Test { + void SetUp() override { + neoDevice = + NEO::MockDevice::createWithNewExecutionEnvironment(NEO::defaultHwInfo.get()); + auto mockBuiltIns = new MockBuiltins(); + neoDevice->executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(mockBuiltIns); + NEO::DeviceVector devices; + devices.push_back(std::unique_ptr(neoDevice)); + driverHandle = std::make_unique(); + driverHandle->initialize(std::move(devices)); + prevSvmAllocsManager = driverHandle->svmAllocsManager; + currSvmAllocsManager = new SVMAllocsManagerRelaxedSizeMock(driverHandle->memoryManager); + driverHandle->svmAllocsManager = currSvmAllocsManager; + device = driverHandle->devices[0]; + } + + void TearDown() override { + driverHandle->svmAllocsManager = prevSvmAllocsManager; + delete currSvmAllocsManager; + } + NEO::SVMAllocsManager *prevSvmAllocsManager; + NEO::SVMAllocsManager *currSvmAllocsManager; + std::unique_ptr driverHandle; + NEO::MockDevice *neoDevice = nullptr; + L0::Device *device = nullptr; +}; + +TEST_F(MemoryRelaxedSizeTests, + givenCallToDeviceAllocWithAllowedSizeAndWithoutRelaxedFlagThenAllocationIsMade) { + size_t size = device->getNEODevice()->getHardwareCapabilities().maxMemAllocSize - 1; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = driverHandle->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + result = driverHandle->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryRelaxedSizeTests, + givenCallToDeviceAllocWithLargerThanAllowdSizeAndWithoutRelaxedFlagThenAllocationIsNotMade) { + size_t size = device->getNEODevice()->getHardwareCapabilities().maxMemAllocSize + 1; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_result_t result = driverHandle->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_SIZE, result); + EXPECT_EQ(nullptr, ptr); +} + +TEST_F(MemoryRelaxedSizeTests, + givenCallToDeviceAllocWithLargerThanAllowdSizeAndRelaxedFlagThenAllocationIsMade) { + size_t size = device->getNEODevice()->getHardwareCapabilities().maxMemAllocSize + 1; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + deviceDesc.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC; + ze_relaxed_allocation_limits_exp_desc_t relaxedSizeDesc = {}; + relaxedSizeDesc.stype = ZE_STRUCTURE_TYPE_RELAXED_ALLOCATION_LIMITS_EXP_DESC; + relaxedSizeDesc.flags = ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE; + deviceDesc.pNext = &relaxedSizeDesc; + ze_result_t result = driverHandle->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + result = driverHandle->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryRelaxedSizeTests, + givenCallToDeviceAllocWithLargerThanAllowdSizeAndRelaxedFlagWithIncorrectFlagThenAllocationIsNotMade) { + size_t size = device->getNEODevice()->getHardwareCapabilities().maxMemAllocSize + 1; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + deviceDesc.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC; + ze_relaxed_allocation_limits_exp_desc_t relaxedSizeDesc = {}; + relaxedSizeDesc.stype = ZE_STRUCTURE_TYPE_RELAXED_ALLOCATION_LIMITS_EXP_DESC; + relaxedSizeDesc.flags = static_cast(ZE_BIT(1)); + deviceDesc.pNext = &relaxedSizeDesc; + ze_result_t result = driverHandle->allocDeviceMem(device->toHandle(), + &deviceDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, result); + EXPECT_EQ(nullptr, ptr); +} + +TEST_F(MemoryRelaxedSizeTests, + givenCallToSharedAllocWithAllowedSizeAndWithoutRelaxedFlagThenAllocationIsMade) { + size_t size = device->getNEODevice()->getHardwareCapabilities().maxMemAllocSize - 1; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_host_mem_alloc_desc_t hostDesc = {}; + ze_result_t result = driverHandle->allocSharedMem(device->toHandle(), + &deviceDesc, + &hostDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + result = driverHandle->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryRelaxedSizeTests, + givenCallToSharedAllocWithLargerThanAllowedSizeAndWithoutRelaxedFlagThenAllocationIsNotMade) { + size_t size = device->getNEODevice()->getHardwareCapabilities().maxMemAllocSize + 1; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + ze_host_mem_alloc_desc_t hostDesc = {}; + ze_result_t result = driverHandle->allocSharedMem(device->toHandle(), + &deviceDesc, + &hostDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_SIZE, result); + EXPECT_EQ(nullptr, ptr); +} + +TEST_F(MemoryRelaxedSizeTests, + givenCallToSharedAllocWithLargerThanAllowdSizeAndRelaxedFlagThenAllocationIsMade) { + size_t size = device->getNEODevice()->getHardwareCapabilities().maxMemAllocSize + 1; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + deviceDesc.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC; + ze_relaxed_allocation_limits_exp_desc_t relaxedSizeDesc = {}; + relaxedSizeDesc.stype = ZE_STRUCTURE_TYPE_RELAXED_ALLOCATION_LIMITS_EXP_DESC; + relaxedSizeDesc.flags = ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE; + deviceDesc.pNext = &relaxedSizeDesc; + ze_host_mem_alloc_desc_t hostDesc = {}; + ze_result_t result = driverHandle->allocSharedMem(device->toHandle(), + &deviceDesc, + &hostDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); + EXPECT_NE(nullptr, ptr); + + result = driverHandle->freeMem(ptr); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +TEST_F(MemoryRelaxedSizeTests, + givenCallToSharedAllocWithLargerThanAllowdSizeAndRelaxedFlagWithIncorrectFlagThenAllocationIsNotMade) { + size_t size = device->getNEODevice()->getHardwareCapabilities().maxMemAllocSize + 1; + size_t alignment = 1u; + void *ptr = nullptr; + + ze_device_mem_alloc_desc_t deviceDesc = {}; + deviceDesc.stype = ZE_STRUCTURE_TYPE_DEVICE_MEM_ALLOC_DESC; + ze_relaxed_allocation_limits_exp_desc_t relaxedSizeDesc = {}; + relaxedSizeDesc.stype = ZE_STRUCTURE_TYPE_RELAXED_ALLOCATION_LIMITS_EXP_DESC; + relaxedSizeDesc.flags = static_cast(ZE_BIT(1)); + deviceDesc.pNext = &relaxedSizeDesc; + ze_host_mem_alloc_desc_t hostDesc = {}; + ze_result_t result = driverHandle->allocSharedMem(device->toHandle(), + &deviceDesc, + &hostDesc, + size, alignment, &ptr); + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, result); + EXPECT_EQ(nullptr, ptr); +} + struct DriverHandleGetFdMock : public DriverHandleImp { void *importFdHandle(ze_device_handle_t hDevice, uint64_t handle) override { if (mockFd == allocationMap.second) { diff --git a/shared/source/memory_manager/unified_memory_manager.h b/shared/source/memory_manager/unified_memory_manager.h index 60ad464f31..b3ebd2c7ce 100644 --- a/shared/source/memory_manager/unified_memory_manager.h +++ b/shared/source/memory_manager/unified_memory_manager.h @@ -113,11 +113,11 @@ class SVMAllocsManager { const std::map &subdeviceBitfields); void *createHostUnifiedMemoryAllocation(size_t size, const UnifiedMemoryProperties &svmProperties); - void *createUnifiedMemoryAllocation(size_t size, - const UnifiedMemoryProperties &svmProperties); - void *createSharedUnifiedMemoryAllocation(size_t size, - const UnifiedMemoryProperties &svmProperties, - void *cmdQ); + MOCKABLE_VIRTUAL void *createUnifiedMemoryAllocation(size_t size, + const UnifiedMemoryProperties &svmProperties); + MOCKABLE_VIRTUAL void *createSharedUnifiedMemoryAllocation(size_t size, + const UnifiedMemoryProperties &svmProperties, + void *cmdQ); void *createUnifiedKmdMigratedAllocation(size_t size, const SvmAllocationProperties &svmProperties, const UnifiedMemoryProperties &unifiedMemoryProperties);