diff --git a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp index ae06e50ee9..d1a29958d7 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp @@ -778,8 +778,40 @@ bool IoctlHelperXe::setVmBoAdviseForChunking(int32_t handle, uint64_t start, uin } bool IoctlHelperXe::setVmPrefetch(uint64_t start, uint64_t length, uint32_t region, uint32_t vmId) { - xeLog(" -> IoctlHelperXe::%s\n", __FUNCTION__); - return false; + xeLog(" -> IoctlHelperXe::%s s=0x%llx l=0x%llx vmid=0x%x\n", __FUNCTION__, start, length, vmId); + drm_xe_vm_bind bind = {}; + bind.vm_id = vmId; + bind.num_binds = 1; + + bind.bind.range = length; + bind.bind.addr = start; + bind.bind.op = DRM_XE_VM_BIND_OP_PREFETCH; + + auto pHwInfo = this->drm.getRootDeviceEnvironment().getHardwareInfo(); + constexpr uint32_t subDeviceMaskSize = DeviceBitfield().size(); + constexpr uint32_t subDeviceMaskMax = (1u << subDeviceMaskSize) - 1u; + uint32_t subDeviceId = region & subDeviceMaskMax; + DeviceBitfield subDeviceMask = (1u << subDeviceId); + MemoryClassInstance regionInstanceClass = this->drm.getMemoryInfo()->getMemoryRegionClassAndInstance(subDeviceMask, *pHwInfo); + bind.bind.prefetch_mem_region_instance = regionInstanceClass.memoryInstance; + + int ret = IoctlHelper::ioctl(DrmIoctl::gemVmBind, &bind); + + xeLog(" vm=%d addr=0x%lx range=0x%lx region=0x%x operation=%d(%s) ret=%d\n", + bind.vm_id, + bind.bind.addr, + bind.bind.range, + bind.bind.prefetch_mem_region_instance, + bind.bind.op, + xeGetBindOperationName(bind.bind.op), + ret); + + if (ret != 0) { + xeLog("error: %s ret=%d\n", xeGetBindOperationName(bind.bind.op), ret); + return false; + } + + return true; } uint32_t IoctlHelperXe::getDirectSubmissionFlag() { diff --git a/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.cpp b/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.cpp index ca75cb8c86..8072d19857 100644 --- a/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.cpp @@ -324,8 +324,6 @@ TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingAnyMethodThenDummyValueIsRe EXPECT_FALSE(xeIoctlHelper->isChunkingAvailable()); - EXPECT_FALSE(xeIoctlHelper->setVmPrefetch(0, 0, 0, 0)); - EXPECT_EQ(0u, xeIoctlHelper->getDirectSubmissionFlag()); EXPECT_EQ(0u, xeIoctlHelper->getFlagsForVmBind(false, false, false, false, false)); @@ -2541,4 +2539,78 @@ TEST(IoctlHelperXeTest, givenIoctlWhenQueryDeviceParamsIsCalledThenFalseIsReturn uint32_t moduleId = 0; uint16_t serverType = 0; EXPECT_FALSE(xeIoctlHelper->queryDeviceParams(&moduleId, &serverType)); -} \ No newline at end of file +} + +TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingSetVmPrefetchThenVmBindIsCalled) { + DebugManagerStateRestore restorer; + debugManager.flags.EnableLocalMemory.set(1); + + auto executionEnvironment = std::make_unique(); + auto drm = DrmMockXe::create(*executionEnvironment->rootDeviceEnvironments[0]); + auto xeIoctlHelper = static_cast(drm->getIoctlHelper()); + xeIoctlHelper->initialize(); + + uint64_t start = 0x12u; + uint64_t length = 0x34u; + uint32_t subDeviceId = 0u; + uint32_t vmId = 1u; + + auto memoryInfo = xeIoctlHelper->createMemoryInfo(); + MemoryClassInstance targetMemoryRegion = memoryInfo->getLocalMemoryRegions()[subDeviceId].region; + ASSERT_NE(nullptr, memoryInfo); + drm->memoryInfo.reset(memoryInfo.release()); + + EXPECT_TRUE(xeIoctlHelper->setVmPrefetch(start, length, subDeviceId, vmId)); + EXPECT_EQ(1u, drm->vmBindInputs.size()); + + EXPECT_EQ(drm->vmBindInputs[0].vm_id, vmId); + EXPECT_EQ(drm->vmBindInputs[0].bind.addr, start); + EXPECT_EQ(drm->vmBindInputs[0].bind.range, length); + EXPECT_EQ(drm->vmBindInputs[0].bind.prefetch_mem_region_instance, targetMemoryRegion.memoryInstance); +} + +TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingSetVmPrefetchOnSecondTileThenVmBindIsCalled) { + DebugManagerStateRestore restorer; + debugManager.flags.EnableLocalMemory.set(1); + + auto executionEnvironment = std::make_unique(); + auto drm = DrmMockXe::create(*executionEnvironment->rootDeviceEnvironments[0]); + auto xeIoctlHelper = static_cast(drm->getIoctlHelper()); + xeIoctlHelper->initialize(); + + uint64_t start = 0x12u; + uint64_t length = 0x34u; + uint32_t subDeviceId = 1u; + uint32_t vmId = 1u; + + auto memoryInfo = xeIoctlHelper->createMemoryInfo(); + MemoryClassInstance targetMemoryRegion = memoryInfo->getLocalMemoryRegions()[subDeviceId].region; + ASSERT_NE(nullptr, memoryInfo); + drm->memoryInfo.reset(memoryInfo.release()); + + EXPECT_TRUE(xeIoctlHelper->setVmPrefetch(start, length, subDeviceId, vmId)); + EXPECT_EQ(1u, drm->vmBindInputs.size()); + + EXPECT_EQ(drm->vmBindInputs[0].vm_id, vmId); + EXPECT_EQ(drm->vmBindInputs[0].bind.addr, start); + EXPECT_EQ(drm->vmBindInputs[0].bind.range, length); + EXPECT_EQ(drm->vmBindInputs[0].bind.prefetch_mem_region_instance, targetMemoryRegion.memoryInstance); +} + +TEST(IoctlHelperXeTest, givenIoctlFailureWhenCallingSetVmPrefetchThenFalseIsReturned) { + DebugManagerStateRestore restorer; + debugManager.flags.EnableLocalMemory.set(1); + + auto executionEnvironment = std::make_unique(); + auto drm = DrmMockXe::create(*executionEnvironment->rootDeviceEnvironments[0]); + auto xeIoctlHelper = static_cast(drm->getIoctlHelper()); + xeIoctlHelper->initialize(); + + auto memoryInfo = xeIoctlHelper->createMemoryInfo(); + ASSERT_NE(nullptr, memoryInfo); + drm->memoryInfo.reset(memoryInfo.release()); + drm->testMode(1, -1); + + EXPECT_FALSE(xeIoctlHelper->setVmPrefetch(0u, 0u, 0u, 0u)); + EXPECT_EQ(0u, drm->vmBindInputs.size()); +}