diff --git a/shared/source/os_interface/linux/drm_memory_manager.cpp b/shared/source/os_interface/linux/drm_memory_manager.cpp index 83b2eb9338..9ab70c9ea9 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager.cpp @@ -2217,6 +2217,21 @@ GraphicsAllocation *DrmMemoryManager::createSharedUnifiedMemoryAllocation(const [[maybe_unused]] auto success = allocation->setMemAdvise(&drm, memAdviseFlags); DEBUG_BREAK_IF(!success); + if (allocationData.usmInitialPlacement == GraphicsAllocation::UsmInitialPlacement::GPU) { + auto getSubDeviceIds = [](const DeviceBitfield &subDeviceBitfield) { + SubDeviceIdsVec subDeviceIds; + for (auto subDeviceId = 0u; subDeviceId < subDeviceBitfield.size(); subDeviceId++) { + if (subDeviceBitfield.test(subDeviceId)) { + subDeviceIds.push_back(subDeviceId); + } + } + return subDeviceIds; + }; + auto subDeviceIds = getSubDeviceIds(allocationData.storageInfo.subDeviceBitfield); + success = setMemPrefetch(allocation.get(), subDeviceIds, allocationData.rootDeviceIndex); + DEBUG_BREAK_IF(!success); + } + return allocation.release(); } diff --git a/shared/test/common/libult/linux/drm_mock_prelim_context.cpp b/shared/test/common/libult/linux/drm_mock_prelim_context.cpp index 3d08d452ed..abfdf48b5c 100644 --- a/shared/test/common/libult/linux/drm_mock_prelim_context.cpp +++ b/shared/test/common/libult/linux/drm_mock_prelim_context.cpp @@ -240,6 +240,12 @@ int DrmMockPrelimContext::handlePrelimRequest(DrmIoctl request, void *arg) { } return vmAdviseReturn; } break; + case DrmIoctl::GemVmPrefetch: { + const auto req = static_cast(arg); + vmPrefetchCalled++; + receivedVmPrefetch.push_back(VmPrefetch{req->vm_id, req->region}); + return 0; + } break; case DrmIoctl::UuidRegister: { auto uuidControl = reinterpret_cast(arg); diff --git a/shared/test/common/libult/linux/drm_mock_prelim_context.h b/shared/test/common/libult/linux/drm_mock_prelim_context.h index 347aa57ec2..7c91f0c815 100644 --- a/shared/test/common/libult/linux/drm_mock_prelim_context.h +++ b/shared/test/common/libult/linux/drm_mock_prelim_context.h @@ -78,6 +78,11 @@ struct VmAdvise { MemoryClassInstance memoryRegions{0}; }; +struct VmPrefetch { + uint32_t vmId{0}; + uint32_t region{0}; +}; + struct UuidVmBindExt { uint32_t handle{0}; uint64_t nextExtension{0}; @@ -130,6 +135,9 @@ struct DrmMockPrelimContext { std::optional receivedVmAdvise[2]{}; int vmAdviseReturn{0}; + size_t vmPrefetchCalled{0}; + std::vector receivedVmPrefetch{}; + int mmapOffsetReturn{0}; uint32_t uuidHandle{1}; diff --git a/shared/test/common/os_interface/linux/drm_memory_manager_prelim_fixtures.h b/shared/test/common/os_interface/linux/drm_memory_manager_prelim_fixtures.h index 2c3bac7722..e527a3e4a1 100644 --- a/shared/test/common/os_interface/linux/drm_memory_manager_prelim_fixtures.h +++ b/shared/test/common/os_interface/linux/drm_memory_manager_prelim_fixtures.h @@ -18,6 +18,42 @@ #include "shared/test/common/os_interface/linux/drm_memory_manager_fixture.h" #include "shared/test/common/os_interface/linux/drm_mock_memory_info.h" +template +class DrmMemoryManagerWithSubDevicesPrelimTest : public ::testing::Test { + public: + void SetUp() override { + DebugManager.flags.CreateMultipleSubDevices.set(multipleSubDevices ? 2 : 1); + + executionEnvironment = new ExecutionEnvironment(); + executionEnvironment->prepareRootDeviceEnvironments(1); + executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->setHwInfoAndInitHelpers(defaultHwInfo.get()); + + mock = new DrmQueryMock(*executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]); + auto memoryInfo = new MockExtendedMemoryInfo(*mock); + mock->memoryInfo.reset(memoryInfo); + + mock->queryEngineInfo(); + + executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface = std::make_unique(); + executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface->setDriverModel(std::unique_ptr(mock)); + executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock, 0u); + + memoryManager = new TestedDrmMemoryManager(true, false, false, *executionEnvironment); + executionEnvironment->memoryManager.reset(memoryManager); + + device.reset(MockDevice::createWithExecutionEnvironment(defaultHwInfo.get(), executionEnvironment, rootDeviceIndex)); + } + + protected: + DebugManagerStateRestore restorer{}; + ExecutionEnvironment *executionEnvironment{nullptr}; + DrmQueryMock *mock{nullptr}; + std::unique_ptr device; + TestedDrmMemoryManager *memoryManager{nullptr}; + + constexpr static uint32_t rootDeviceIndex{0u}; +}; + class DrmMemoryManagerLocalMemoryPrelimTest : public ::testing::Test { public: void SetUp() override { 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 8af4301591..ad740ec427 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 @@ -776,6 +776,58 @@ TEST_F(DrmMemoryManagerLocalMemoryPrelimTest, givenKMDSupportForCrossTileMigrati unifiedMemoryManager.freeSVMAlloc(ptr); } +using DrmMemoryManagerWithSingleSubDevicePrelimTest = DrmMemoryManagerWithSubDevicesPrelimTest; +TEST_F(DrmMemoryManagerWithSingleSubDevicePrelimTest, givenUnifiedMemoryAllocationOnSingleSubDeviceWhenCreatedWithInitialPlacementOnGpuThenCallMemoryPrefetch) { + DeviceBitfield subDevices = 0b01; + AllocationProperties gpuProperties{0u, + MemoryConstants::pageSize64k, + AllocationType::UNIFIED_SHARED_MEMORY, + subDevices}; + gpuProperties.alignment = 2 * MemoryConstants::megaByte; + gpuProperties.usmInitialPlacement = GraphicsAllocation::UsmInitialPlacement::GPU; + + auto allocation = memoryManager->allocateGraphicsMemoryWithProperties(gpuProperties); + ASSERT_NE(allocation, nullptr); + + EXPECT_EQ(mock->context.vmBindCalled, 1u); + EXPECT_EQ(mock->context.vmPrefetchCalled, 1u); + + ASSERT_EQ(mock->context.receivedVmPrefetch.size(), 1u); + EXPECT_EQ(mock->context.receivedVmPrefetch[0].vmId, 1u); + EXPECT_EQ(mock->context.receivedVmPrefetch[0].region, static_cast(drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE << 16 | 0u)); + + memoryManager->freeGraphicsMemory(allocation); +} + +using DrmMemoryManagerWithMultipleSubDevicesPrelimTest = DrmMemoryManagerWithSubDevicesPrelimTest; +TEST_F(DrmMemoryManagerWithMultipleSubDevicesPrelimTest, givenUnifiedMemoryAllocationOnMultipleSubdevicesWhenCreatedWithInitialPlacementIsOnGpuThenCallVmPrefetchCorrectly) { + DeviceBitfield subDevices = 0b11; + AllocationProperties gpuProperties{0u, + 2 * MemoryConstants::pageSize64k, + AllocationType::UNIFIED_SHARED_MEMORY, + subDevices}; + gpuProperties.alignment = 2 * MemoryConstants::megaByte; + gpuProperties.usmInitialPlacement = GraphicsAllocation::UsmInitialPlacement::GPU; + + auto allocation = memoryManager->allocateGraphicsMemoryWithProperties(gpuProperties); + ASSERT_NE(allocation, nullptr); + + EXPECT_EQ(mock->context.vmBindCalled, 4u); + EXPECT_EQ(mock->context.vmPrefetchCalled, 4u); + + ASSERT_EQ(mock->context.receivedVmPrefetch.size(), 4u); + EXPECT_EQ(mock->context.receivedVmPrefetch[0].vmId, 1u); + EXPECT_EQ(mock->context.receivedVmPrefetch[0].region, static_cast(drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE << 16 | 0u)); + EXPECT_EQ(mock->context.receivedVmPrefetch[1].vmId, 2u); + EXPECT_EQ(mock->context.receivedVmPrefetch[1].region, static_cast(drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE << 16 | 0u)); + EXPECT_EQ(mock->context.receivedVmPrefetch[2].vmId, 1u); + EXPECT_EQ(mock->context.receivedVmPrefetch[2].region, static_cast(drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE << 16 | 1u)); + EXPECT_EQ(mock->context.receivedVmPrefetch[3].vmId, 2u); + EXPECT_EQ(mock->context.receivedVmPrefetch[3].region, static_cast(drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE << 16 | 1u)); + + memoryManager->freeGraphicsMemory(allocation); +} + TEST_F(DrmMemoryManagerLocalMemoryPrelimTest, whenVmAdviseIoctlFailsThenCreateSharedUnifiedMemoryAllocationReturnsNullptr) { DebugManagerStateRestore restorer; DebugManager.flags.UseKmdMigration.set(1);