From 98dae70415682c3820545abeefc9d15da164c250 Mon Sep 17 00:00:00 2001 From: "Cencelewska, Katarzyna" Date: Wed, 6 Sep 2023 11:04:13 +0000 Subject: [PATCH] fix: add helper to proper call GemCreate on xe kmd Related-To: NEO-8325 Signed-off-by: Cencelewska, Katarzyna --- .../os_interface/linux/drm_memory_manager.cpp | 25 +- .../os_interface/linux/ioctl_helper.cpp | 8 + .../source/os_interface/linux/ioctl_helper.h | 1 + .../os_interface/linux/xe/ioctl_helper_xe.cpp | 29 +- .../os_interface/linux/xe/ioctl_helper_xe.h | 1 + .../os_interface/linux/drm_tests.cpp | 21 + .../linux/xe/ioctl_helper_xe_tests.cpp | 507 ++++++++++-------- 7 files changed, 345 insertions(+), 247 deletions(-) diff --git a/shared/source/os_interface/linux/drm_memory_manager.cpp b/shared/source/os_interface/linux/drm_memory_manager.cpp index 14dc64d55d..ea66b79767 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager.cpp @@ -591,18 +591,14 @@ GraphicsAllocation *DrmMemoryManager::allocatePhysicalDeviceMemory(const Allocat allocationData.size, 0u, CacheSettingsHelper::getGmmUsageType(allocationData.type, allocationData.flags.uncacheable, productHelper), false, systemMemoryStorageInfo, true); size_t bufferSize = allocationData.size; - GemCreate create{}; - create.size = bufferSize; - auto &drm = getDrm(allocationData.rootDeviceIndex); auto ioctlHelper = drm.getIoctlHelper(); - [[maybe_unused]] auto ret = ioctlHelper->ioctl(DrmIoctl::GemCreate, &create); - DEBUG_BREAK_IF(ret != 0); + uint32_t handle = ioctlHelper->createGem(bufferSize, static_cast(allocationData.storageInfo.memoryBanks.to_ulong())); auto patIndex = drm.getPatIndex(gmm.get(), allocationData.type, CacheRegion::Default, CachePolicy::WriteBack, false); - std::unique_ptr bo(new BufferObject(allocationData.rootDeviceIndex, &drm, patIndex, create.handle, bufferSize, maxOsContextCount)); + std::unique_ptr bo(new BufferObject(allocationData.rootDeviceIndex, &drm, patIndex, handle, bufferSize, maxOsContextCount)); auto allocation = new DrmAllocation(allocationData.rootDeviceIndex, allocationData.type, bo.get(), nullptr, 0u, bufferSize, MemoryPool::SystemCpuInaccessible); allocation->setDefaultGmm(gmm.release()); @@ -621,18 +617,14 @@ GraphicsAllocation *DrmMemoryManager::allocateMemoryByKMD(const AllocationData & size_t bufferSize = allocationData.size; uint64_t gpuRange = acquireGpuRangeWithCustomAlignment(bufferSize, allocationData.rootDeviceIndex, HeapIndex::HEAP_STANDARD64KB, allocationData.alignment); - GemCreate create{}; - create.size = bufferSize; - auto &drm = getDrm(allocationData.rootDeviceIndex); auto ioctlHelper = drm.getIoctlHelper(); - [[maybe_unused]] auto ret = ioctlHelper->ioctl(DrmIoctl::GemCreate, &create); - DEBUG_BREAK_IF(ret != 0); + uint32_t handle = ioctlHelper->createGem(bufferSize, static_cast(allocationData.storageInfo.memoryBanks.to_ulong())); auto patIndex = drm.getPatIndex(gmm.get(), allocationData.type, CacheRegion::Default, CachePolicy::WriteBack, false); - std::unique_ptr bo(new BufferObject(allocationData.rootDeviceIndex, &drm, patIndex, create.handle, bufferSize, maxOsContextCount)); + std::unique_ptr bo(new BufferObject(allocationData.rootDeviceIndex, &drm, patIndex, handle, bufferSize, maxOsContextCount)); bo->setAddress(gpuRange); auto allocation = new DrmAllocation(allocationData.rootDeviceIndex, allocationData.type, bo.get(), nullptr, gpuRange, bufferSize, MemoryPool::SystemCpuInaccessible); @@ -655,18 +647,13 @@ GraphicsAllocation *DrmMemoryManager::allocateGraphicsMemoryForImageImpl(const A uint64_t gpuRange = acquireGpuRange(allocationData.imgInfo->size, allocationData.rootDeviceIndex, HeapIndex::HEAP_STANDARD); - GemCreate create{}; - create.size = allocationData.imgInfo->size; - auto &drm = this->getDrm(allocationData.rootDeviceIndex); auto ioctlHelper = drm.getIoctlHelper(); - - [[maybe_unused]] auto ret = ioctlHelper->ioctl(DrmIoctl::GemCreate, &create); - DEBUG_BREAK_IF(ret != 0); + uint32_t handle = ioctlHelper->createGem(allocationData.imgInfo->size, static_cast(allocationData.storageInfo.memoryBanks.to_ulong())); auto patIndex = drm.getPatIndex(gmm.get(), allocationData.type, CacheRegion::Default, CachePolicy::WriteBack, false); - std::unique_ptr bo(new (std::nothrow) BufferObject(allocationData.rootDeviceIndex, &drm, patIndex, create.handle, allocationData.imgInfo->size, maxOsContextCount)); + std::unique_ptr bo(new (std::nothrow) BufferObject(allocationData.rootDeviceIndex, &drm, patIndex, handle, allocationData.imgInfo->size, maxOsContextCount)); if (!bo) { return nullptr; } diff --git a/shared/source/os_interface/linux/ioctl_helper.cpp b/shared/source/os_interface/linux/ioctl_helper.cpp index 00b6647c50..420310fa1d 100644 --- a/shared/source/os_interface/linux/ioctl_helper.cpp +++ b/shared/source/os_interface/linux/ioctl_helper.cpp @@ -556,4 +556,12 @@ std::unique_ptr IoctlHelper::createEngineInfo(bool isSysmanEnabled) return std::make_unique(&drm, tileCount, distanceInfos, queryItems, engines); } + +uint32_t IoctlHelper::createGem(uint64_t size, uint32_t memoryBanks) { + GemCreate gemCreate = {}; + gemCreate.size = size; + [[maybe_unused]] auto ret = ioctl(DrmIoctl::GemCreate, &gemCreate); + DEBUG_BREAK_IF(ret != 0); + return gemCreate.handle; +} } // namespace NEO diff --git a/shared/source/os_interface/linux/ioctl_helper.h b/shared/source/os_interface/linux/ioctl_helper.h index b6d1b04e9e..dbff72fa76 100644 --- a/shared/source/os_interface/linux/ioctl_helper.h +++ b/shared/source/os_interface/linux/ioctl_helper.h @@ -81,6 +81,7 @@ class IoctlHelper { virtual bool isChunkingAvailable() = 0; virtual bool isVmBindAvailable() = 0; virtual int createGemExt(const MemRegionsVec &memClassInstances, size_t allocSize, uint32_t &handle, uint64_t patIndex, std::optional vmId, int32_t pairHandle, bool isChunked, uint32_t numOfChunks) = 0; + virtual uint32_t createGem(uint64_t size, uint32_t memoryBanks); virtual CacheRegion closAlloc() = 0; virtual uint16_t closAllocWays(CacheRegion closIndex, uint16_t cacheLevel, uint16_t numWays) = 0; virtual CacheRegion closFree(CacheRegion closIndex) = 0; 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 5f21f5b317..28ff79f563 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp @@ -472,6 +472,29 @@ int IoctlHelperXe::createGemExt(const MemRegionsVec &memClassInstances, size_t a return ret; } +uint32_t IoctlHelperXe::createGem(uint64_t size, uint32_t memoryBanks) { + struct drm_xe_gem_create create = {}; + create.size = size; + auto pHwInfo = drm.getRootDeviceEnvironment().getHardwareInfo(); + auto memoryInfo = drm.getMemoryInfo(); + std::bitset<32> memoryInstances{}; + auto banks = std::bitset<4>(memoryBanks); + size_t currentBank = 0; + size_t i = 0; + while (i < banks.count()) { + if (banks.test(currentBank)) { + auto regionClassAndInstance = memoryInfo->getMemoryRegionClassAndInstance(1u << currentBank, *pHwInfo); + memoryInstances.set(regionClassAndInstance.memoryInstance); + i++; + } + currentBank++; + } + create.flags = static_cast(memoryInstances.to_ulong()); + [[maybe_unused]] auto ret = ioctl(DrmIoctl::GemCreate, &create); + DEBUG_BREAK_IF(ret != 0); + return create.handle; +} + CacheRegion IoctlHelperXe::closAlloc() { xeLog(" -> IoctlHelperXe::%s\n", __FUNCTION__); return CacheRegion::None; @@ -1132,10 +1155,10 @@ int IoctlHelperXe::ioctl(DrmIoctl request, void *arg) { prime->handle, prime->flags, prime->fileDescriptor, ret); } break; case DrmIoctl::GemCreate: { - GemCreate *gemCreate = static_cast(arg); + drm_xe_gem_create *gemCreate = static_cast(arg); ret = IoctlHelper::ioctl(request, arg); - xeLog(" -> IoctlHelperXe::ioctl GemCreate h=0x%x s=0x%llx r=%d\n", - gemCreate->handle, gemCreate->size, ret); + xeLog(" -> IoctlHelperXe::ioctl GemCreate h=0x%x s=0x%llx f=0x%x r=%d\n", + gemCreate->handle, gemCreate->size, gemCreate->flags, ret); } break; default: xeLog("Not handled 0x%x\n", request); diff --git a/shared/source/os_interface/linux/xe/ioctl_helper_xe.h b/shared/source/os_interface/linux/xe/ioctl_helper_xe.h index 1694bc932e..280b4d1337 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe.h +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe.h @@ -48,6 +48,7 @@ class IoctlHelperXe : public IoctlHelper { bool isChunkingAvailable() override; bool isVmBindAvailable() override; int createGemExt(const MemRegionsVec &memClassInstances, size_t allocSize, uint32_t &handle, uint64_t patIndex, std::optional vmId, int32_t pairHandle, bool isChunked, uint32_t numOfChunks) override; + uint32_t createGem(uint64_t size, uint32_t memoryBanks) override; CacheRegion closAlloc() override; uint16_t closAllocWays(CacheRegion closIndex, uint16_t cacheLevel, uint16_t numWays) override; CacheRegion closFree(CacheRegion closIndex) override; diff --git a/shared/test/unit_test/os_interface/linux/drm_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_tests.cpp index e1dc77c6db..20d81fc29c 100644 --- a/shared/test/unit_test/os_interface/linux/drm_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_tests.cpp @@ -1563,6 +1563,27 @@ TEST(IoctlHelperTest, whenGettingFileNameForFrequencyFilesThenProperStringIsRetu EXPECT_STREQ("/gt/gt1/mem_RP0_freq_mhz", ioctlHelper->getFileForMaxMemoryFrequencyOfSubDevice(1).c_str()); } +TEST(IoctlHelperTest, givenIoctlHelperWhenCallCreateGemThenProperValuesSet) { + auto executionEnvironment = std::make_unique(); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + auto ioctlHelper = drm.getIoctlHelper(); + ASSERT_NE(nullptr, ioctlHelper); + + uint64_t size = 1234; + uint32_t memoryBanks = 3u; + + EXPECT_EQ(0, drm.ioctlCount.gemCreate); + uint32_t handle = ioctlHelper->createGem(size, memoryBanks); + EXPECT_EQ(1, drm.ioctlCount.gemCreate); + + EXPECT_EQ(size, drm.createParamsSize); + + // dummy mock handle + EXPECT_EQ(1u, drm.createParamsHandle); + EXPECT_EQ(handle, drm.createParamsHandle); +} + TEST(DistanceInfoTest, givenDistanceInfosWhenAssignRegionsFromDistancesThenCorrectRegionsSet) { auto executionEnvironment = std::make_unique(); DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; 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 d63bf9c84e..41a90a56e9 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 @@ -69,9 +69,9 @@ TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingGemCreateExtWithRegionsThen ASSERT_NE(nullptr, xeIoctlHelper); std::vector regionInfo(2); - regionInfo[0].region = {drm_i915_gem_memory_class::I915_MEMORY_CLASS_SYSTEM, 0}; + regionInfo[0].region = {0, 0}; regionInfo[0].probedSize = 8 * GB; - regionInfo[1].region = {drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE, 0}; + regionInfo[1].region = {1, 0}; regionInfo[1].probedSize = 16 * GB; MemRegionsVec memRegions = {regionInfo[0].region, regionInfo[1].region}; @@ -87,9 +87,9 @@ TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingGemCreateExtWithRegionsAndV ASSERT_NE(nullptr, xeIoctlHelper); std::vector regionInfo(2); - regionInfo[0].region = {drm_i915_gem_memory_class::I915_MEMORY_CLASS_SYSTEM, 0}; + regionInfo[0].region = {0, 0}; regionInfo[0].probedSize = 8 * GB; - regionInfo[1].region = {drm_i915_gem_memory_class::I915_MEMORY_CLASS_DEVICE, 0}; + regionInfo[1].region = {1, 0}; regionInfo[1].probedSize = 16 * GB; MemRegionsVec memRegions = {regionInfo[0].region, regionInfo[1].region}; @@ -99,6 +99,280 @@ TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingGemCreateExtWithRegionsAndV EXPECT_NE(0, xeIoctlHelper->createGemExt(memRegions, 0u, handle, 0, test.vmId, -1, false, numOfChunks)); } +inline constexpr int testValueVmId = 0x5764; +inline constexpr int testValueMapOff = 0x7788; +inline constexpr int testValuePrime = 0x4321; +inline constexpr uint32_t testValueGemCreate = 0x8273; +class DrmMockXe : public DrmMockCustom { + public: + DrmMockXe(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMockCustom(rootDeviceEnvironment) { + auto xeQueryMemUsage = reinterpret_cast(queryMemUsage); + xeQueryMemUsage->num_regions = 3; + xeQueryMemUsage->regions[0] = { + XE_MEM_REGION_CLASS_VRAM, // class + 1, // instance + 0, // padding + MemoryConstants::pageSize, // min page size + MemoryConstants::pageSize, // max page size + 2 * MemoryConstants::gigaByte, // total size + MemoryConstants::megaByte // used size + }; + xeQueryMemUsage->regions[1] = { + XE_MEM_REGION_CLASS_SYSMEM, // class + 0, // instance + 0, // padding + MemoryConstants::pageSize, // min page size + MemoryConstants::pageSize, // max page size + MemoryConstants::gigaByte, // total size + MemoryConstants::kiloByte // used size + }; + xeQueryMemUsage->regions[2] = { + XE_MEM_REGION_CLASS_VRAM, // class + 2, // instance + 0, // padding + MemoryConstants::pageSize, // min page size + MemoryConstants::pageSize, // max page size + 4 * MemoryConstants::gigaByte, // total size + MemoryConstants::gigaByte // used size + }; + + auto xeQueryGts = reinterpret_cast(queryGts); + xeQueryGts->num_gt = 2; + xeQueryGts->gts[0] = { + XE_QUERY_GT_TYPE_MAIN, // type + 0, // instance + 12500000, // clock freq + 0, // features + 0b100, // native mem regions + 0x011, // slow mem regions + 0 // inaccessible mem regions + }; + xeQueryGts->gts[1] = { + XE_QUERY_GT_TYPE_REMOTE, // type + 1, // instance + 12500000, // clock freq + 0, // features + 0b010, // native mem regions + 0x101, // slow mem regions + 0 // inaccessible mem regions + }; + } + + void testMode(int f, int a = 0) { + forceIoctlAnswer = f; + setIoctlAnswer = a; + } + int ioctl(DrmIoctl request, void *arg) override { + int ret = -1; + if (forceIoctlAnswer) { + return setIoctlAnswer; + } + switch (request) { + case DrmIoctl::RegRead: { + struct drm_xe_mmio *reg = static_cast(arg); + reg->value = reg->addr; + ret = 0; + } break; + case DrmIoctl::GemVmCreate: { + struct drm_xe_vm_create *v = static_cast(arg); + v->vm_id = testValueVmId; + ret = 0; + } break; + case DrmIoctl::GemUserptr: + case DrmIoctl::GemClose: + ret = 0; + break; + case DrmIoctl::GemVmDestroy: { + struct drm_xe_vm_destroy *v = static_cast(arg); + if (v->vm_id == testValueVmId) + ret = 0; + } break; + case DrmIoctl::GemMmapOffset: { + struct drm_xe_gem_mmap_offset *v = static_cast(arg); + if (v->handle == testValueMapOff) { + v->offset = v->handle; + ret = 0; + } + } break; + case DrmIoctl::PrimeFdToHandle: { + PrimeHandle *v = static_cast(arg); + if (v->fileDescriptor == testValuePrime) { + v->handle = testValuePrime; + ret = 0; + } + } break; + case DrmIoctl::PrimeHandleToFd: { + PrimeHandle *v = static_cast(arg); + if (v->handle == testValuePrime) { + v->fileDescriptor = testValuePrime; + ret = 0; + } + } break; + case DrmIoctl::GemCreate: { + ioctlCnt.gemCreate++; + auto createParams = static_cast(arg); + this->createParamsSize = createParams->size; + this->createParamsFlags = createParams->flags; + this->createParamsHandle = createParams->handle = testValueGemCreate; + if (0 == this->createParamsSize || 0 == this->createParamsFlags) { + return EINVAL; + } + ret = 0; + } break; + case DrmIoctl::Getparam: + case DrmIoctl::GetResetStats: + ret = -2; + break; + case DrmIoctl::Query: { + struct drm_xe_device_query *deviceQuery = static_cast(arg); + switch (deviceQuery->query) { + case DRM_XE_DEVICE_QUERY_ENGINES: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryEngines, sizeof(queryEngines)); + } + deviceQuery->size = sizeof(queryEngines); + break; + case DRM_XE_DEVICE_QUERY_MEM_USAGE: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryMemUsage, sizeof(queryMemUsage)); + } + deviceQuery->size = sizeof(queryMemUsage); + break; + case DRM_XE_DEVICE_QUERY_GTS: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryGts, sizeof(queryGts)); + } + deviceQuery->size = sizeof(queryGts); + break; + case DRM_XE_DEVICE_QUERY_GT_TOPOLOGY: + if (deviceQuery->data) { + memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryTopology.data(), queryTopology.size()); + } + deviceQuery->size = static_cast(queryTopology.size()); + break; + }; + ret = 0; + } break; + case DrmIoctl::GemVmBind: { + ret = gemVmBindReturn; + auto vmBindInput = static_cast(arg); + vmBindInputs.push_back(*vmBindInput); + + EXPECT_EQ(1u, vmBindInput->num_syncs); + + auto &syncInput = reinterpret_cast(vmBindInput->syncs)[0]; + syncInputs.push_back(syncInput); + } break; + + case DrmIoctl::GemWaitUserFence: { + ret = waitUserFenceReturn; + auto waitUserFenceInput = static_cast(arg); + waitUserFenceInputs.push_back(*waitUserFenceInput); + } break; + + case DrmIoctl::GemContextSetparam: + case DrmIoctl::GemContextGetparam: + + default: + break; + } + return ret; + } + + void addMockedQueryTopologyData(uint16_t tileId, uint16_t maskType, uint32_t nBytes, const std::vector &mask) { + + ASSERT_EQ(nBytes, mask.size()); + + auto additionalSize = 8u + nBytes; + auto oldSize = queryTopology.size(); + auto newSize = oldSize + additionalSize; + queryTopology.resize(newSize, 0u); + + uint8_t *dataPtr = queryTopology.data() + oldSize; + + drm_xe_query_topology_mask *topo = reinterpret_cast(dataPtr); + topo->gt_id = tileId; + topo->type = maskType; + topo->num_bytes = nBytes; + + memcpy_s(reinterpret_cast(topo->mask), nBytes, mask.data(), nBytes); + } + + int forceIoctlAnswer = 0; + int setIoctlAnswer = 0; + int gemVmBindReturn = 0; + const drm_xe_engine_class_instance queryEngines[9] = { + {DRM_XE_ENGINE_CLASS_RENDER, 0, 0}, + {DRM_XE_ENGINE_CLASS_COPY, 1, 0}, + {DRM_XE_ENGINE_CLASS_COPY, 2, 0}, + {DRM_XE_ENGINE_CLASS_COMPUTE, 3, 0}, + {DRM_XE_ENGINE_CLASS_COMPUTE, 4, 0}, + {DRM_XE_ENGINE_CLASS_COMPUTE, 5, 1}, + {DRM_XE_ENGINE_CLASS_COMPUTE, 6, 1}, + {DRM_XE_ENGINE_CLASS_VIDEO_DECODE, 7, 1}, + {DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE, 8, 0}}; + + uint64_t queryMemUsage[37]{}; // 1 qword for num regions and 12 qwords per region + uint64_t queryGts[27]{}; // 1 qword for num gts and 13 qwords per gt + std::vector queryTopology; + + StackVec waitUserFenceInputs; + StackVec vmBindInputs; + StackVec syncInputs; + int waitUserFenceReturn = 0; + uint32_t createParamsFlags = 0u; +}; + +TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallGemCreateAndNoLocalMemoryThenProperValuesSet) { + DebugManagerStateRestore restorer; + DebugManager.flags.EnableLocalMemory.set(0); + auto executionEnvironment = std::make_unique(); + DrmMockXe drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + auto xeIoctlHelper = std::make_unique(drm); + drm.memoryInfo.reset(xeIoctlHelper->createMemoryInfo().release()); + ASSERT_NE(nullptr, xeIoctlHelper); + + uint64_t size = 1234; + uint32_t memoryBanks = 3u; + + EXPECT_EQ(0, drm.ioctlCnt.gemCreate); + uint32_t handle = xeIoctlHelper->createGem(size, memoryBanks); + EXPECT_EQ(1, drm.ioctlCnt.gemCreate); + + EXPECT_EQ(size, drm.createParamsSize); + EXPECT_EQ(1u, drm.createParamsFlags); + + // dummy mock handle + EXPECT_EQ(handle, drm.createParamsHandle); + EXPECT_EQ(handle, testValueGemCreate); +} + +TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallGemCreateAndLocalMemoryThenProperValuesSet) { + DebugManagerStateRestore restorer; + DebugManager.flags.EnableLocalMemory.set(1); + auto executionEnvironment = std::make_unique(); + DrmMockXe drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + auto xeIoctlHelper = std::make_unique(drm); + drm.memoryInfo.reset(xeIoctlHelper->createMemoryInfo().release()); + ASSERT_NE(nullptr, xeIoctlHelper); + + uint64_t size = 1234; + uint32_t memoryBanks = 3u; + + EXPECT_EQ(0, drm.ioctlCnt.gemCreate); + uint32_t handle = xeIoctlHelper->createGem(size, memoryBanks); + EXPECT_EQ(1, drm.ioctlCnt.gemCreate); + + EXPECT_EQ(size, drm.createParamsSize); + EXPECT_EQ(6u, drm.createParamsFlags); + + // dummy mock handle + EXPECT_EQ(handle, drm.createParamsHandle); + EXPECT_EQ(handle, testValueGemCreate); +} + TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingAnyMethodThenDummyValueIsReturned) { auto executionEnvironment = std::make_unique(); DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; @@ -413,225 +687,6 @@ TEST(IoctlHelperXeTest, whenGettingFileNamesForFrequencyThenProperStringIsReturn EXPECT_STREQ("/device/gt1/freq_rp0", ioctlHelper->getFileForMaxMemoryFrequencyOfSubDevice(1).c_str()); } -inline constexpr int testValueVmId = 0x5764; -inline constexpr int testValueMapOff = 0x7788; -inline constexpr int testValuePrime = 0x4321; -inline constexpr int testValueGemCreate = 0x8273; - -class DrmMockXe : public DrmMockCustom { - public: - DrmMockXe(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMockCustom(rootDeviceEnvironment) { - auto xeQueryMemUsage = reinterpret_cast(queryMemUsage); - xeQueryMemUsage->num_regions = 3; - xeQueryMemUsage->regions[0] = { - XE_MEM_REGION_CLASS_VRAM, // class - 1, // instance - 0, // padding - MemoryConstants::pageSize, // min page size - MemoryConstants::pageSize, // max page size - 2 * MemoryConstants::gigaByte, // total size - MemoryConstants::megaByte // used size - }; - xeQueryMemUsage->regions[1] = { - XE_MEM_REGION_CLASS_SYSMEM, // class - 0, // instance - 0, // padding - MemoryConstants::pageSize, // min page size - MemoryConstants::pageSize, // max page size - MemoryConstants::gigaByte, // total size - MemoryConstants::kiloByte // used size - }; - xeQueryMemUsage->regions[2] = { - XE_MEM_REGION_CLASS_VRAM, // class - 2, // instance - 0, // padding - MemoryConstants::pageSize, // min page size - MemoryConstants::pageSize, // max page size - 4 * MemoryConstants::gigaByte, // total size - MemoryConstants::gigaByte // used size - }; - - auto xeQueryGts = reinterpret_cast(queryGts); - xeQueryGts->num_gt = 2; - xeQueryGts->gts[0] = { - XE_QUERY_GT_TYPE_MAIN, // type - 0, // instance - 12500000, // clock freq - 0, // features - 0b100, // native mem regions - 0x011, // slow mem regions - 0 // inaccessible mem regions - }; - xeQueryGts->gts[1] = { - XE_QUERY_GT_TYPE_REMOTE, // type - 1, // instance - 12500000, // clock freq - 0, // features - 0b010, // native mem regions - 0x101, // slow mem regions - 0 // inaccessible mem regions - }; - } - - void testMode(int f, int a = 0) { - forceIoctlAnswer = f; - setIoctlAnswer = a; - } - int ioctl(DrmIoctl request, void *arg) override { - int ret = -1; - if (forceIoctlAnswer) { - return setIoctlAnswer; - } - switch (request) { - case DrmIoctl::RegRead: { - struct drm_xe_mmio *reg = static_cast(arg); - reg->value = reg->addr; - ret = 0; - } break; - case DrmIoctl::GemVmCreate: { - struct drm_xe_vm_create *v = static_cast(arg); - v->vm_id = testValueVmId; - ret = 0; - } break; - case DrmIoctl::GemUserptr: - case DrmIoctl::GemClose: - ret = 0; - break; - case DrmIoctl::GemVmDestroy: { - struct drm_xe_vm_destroy *v = static_cast(arg); - if (v->vm_id == testValueVmId) - ret = 0; - } break; - case DrmIoctl::GemMmapOffset: { - struct drm_xe_gem_mmap_offset *v = static_cast(arg); - if (v->handle == testValueMapOff) { - v->offset = v->handle; - ret = 0; - } - } break; - case DrmIoctl::PrimeFdToHandle: { - PrimeHandle *v = static_cast(arg); - if (v->fileDescriptor == testValuePrime) { - v->handle = testValuePrime; - ret = 0; - } - } break; - case DrmIoctl::PrimeHandleToFd: { - PrimeHandle *v = static_cast(arg); - if (v->handle == testValuePrime) { - v->fileDescriptor = testValuePrime; - ret = 0; - } - } break; - case DrmIoctl::GemCreate: { - GemCreate *v = static_cast(arg); - if (v->handle == testValueGemCreate) { - ret = 0; - } - } break; - case DrmIoctl::Getparam: - case DrmIoctl::GetResetStats: - ret = -2; - break; - case DrmIoctl::Query: { - struct drm_xe_device_query *deviceQuery = static_cast(arg); - switch (deviceQuery->query) { - case DRM_XE_DEVICE_QUERY_ENGINES: - if (deviceQuery->data) { - memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryEngines, sizeof(queryEngines)); - } - deviceQuery->size = sizeof(queryEngines); - break; - case DRM_XE_DEVICE_QUERY_MEM_USAGE: - if (deviceQuery->data) { - memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryMemUsage, sizeof(queryMemUsage)); - } - deviceQuery->size = sizeof(queryMemUsage); - break; - case DRM_XE_DEVICE_QUERY_GTS: - if (deviceQuery->data) { - memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryGts, sizeof(queryGts)); - } - deviceQuery->size = sizeof(queryGts); - break; - case DRM_XE_DEVICE_QUERY_GT_TOPOLOGY: - if (deviceQuery->data) { - memcpy_s(reinterpret_cast(deviceQuery->data), deviceQuery->size, queryTopology.data(), queryTopology.size()); - } - deviceQuery->size = static_cast(queryTopology.size()); - break; - }; - ret = 0; - } break; - case DrmIoctl::GemVmBind: { - ret = gemVmBindReturn; - auto vmBindInput = static_cast(arg); - vmBindInputs.push_back(*vmBindInput); - - EXPECT_EQ(1u, vmBindInput->num_syncs); - - auto &syncInput = reinterpret_cast(vmBindInput->syncs)[0]; - syncInputs.push_back(syncInput); - } break; - - case DrmIoctl::GemWaitUserFence: { - ret = waitUserFenceReturn; - auto waitUserFenceInput = static_cast(arg); - waitUserFenceInputs.push_back(*waitUserFenceInput); - } break; - - case DrmIoctl::GemContextSetparam: - case DrmIoctl::GemContextGetparam: - - default: - break; - } - return ret; - } - - void addMockedQueryTopologyData(uint16_t tileId, uint16_t maskType, uint32_t nBytes, const std::vector &mask) { - - ASSERT_EQ(nBytes, mask.size()); - - auto additionalSize = 8u + nBytes; - auto oldSize = queryTopology.size(); - auto newSize = oldSize + additionalSize; - queryTopology.resize(newSize, 0u); - - uint8_t *dataPtr = queryTopology.data() + oldSize; - - drm_xe_query_topology_mask *topo = reinterpret_cast(dataPtr); - topo->gt_id = tileId; - topo->type = maskType; - topo->num_bytes = nBytes; - - memcpy_s(reinterpret_cast(topo->mask), nBytes, mask.data(), nBytes); - } - - int forceIoctlAnswer = 0; - int setIoctlAnswer = 0; - int gemVmBindReturn = 0; - const drm_xe_engine_class_instance queryEngines[9] = { - {DRM_XE_ENGINE_CLASS_RENDER, 0, 0}, - {DRM_XE_ENGINE_CLASS_COPY, 1, 0}, - {DRM_XE_ENGINE_CLASS_COPY, 2, 0}, - {DRM_XE_ENGINE_CLASS_COMPUTE, 3, 0}, - {DRM_XE_ENGINE_CLASS_COMPUTE, 4, 0}, - {DRM_XE_ENGINE_CLASS_COMPUTE, 5, 1}, - {DRM_XE_ENGINE_CLASS_COMPUTE, 6, 1}, - {DRM_XE_ENGINE_CLASS_VIDEO_DECODE, 7, 1}, - {DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE, 8, 0}}; - - uint64_t queryMemUsage[37]{}; // 1 qword for num regions and 12 qwords per region - uint64_t queryGts[27]{}; // 1 qword for num gts and 13 qwords per gt - std::vector queryTopology; - - StackVec waitUserFenceInputs; - StackVec vmBindInputs; - StackVec syncInputs; - int waitUserFenceReturn = 0; -}; - TEST(IoctlHelperXeTest, whenCallingIoctlThenProperValueIsReturned) { int ret; DebugManagerStateRestore restorer; @@ -711,8 +766,10 @@ TEST(IoctlHelperXeTest, whenCallingIoctlThenProperValueIsReturned) { EXPECT_EQ(static_cast(test.fileDescriptor), testValuePrime); } { - GemCreate test = {}; - test.handle = testValueGemCreate; + drm_xe_gem_create test = {}; + test.handle = 0; + test.flags = 1; + test.size = 123; ret = mockXeIoctlHelper->ioctl(DrmIoctl::GemCreate, &test); EXPECT_EQ(0, ret); }