From f2c4231a27796d23c040978affa8ee0d99cd0dfa Mon Sep 17 00:00:00 2001 From: Daniel Chabrowski Date: Fri, 28 Jan 2022 21:00:05 +0000 Subject: [PATCH] Extend DRM mock and queryTopology tests - part 1 Signed-off-by: Daniel Chabrowski daniel.chabrowski@intel.com Related-To: NEO-6591 --- .../sysman/engine/linux/test_zes_engine.cpp | 2 +- .../sysman/linux/mock_sysman_fixture.h | 2 +- .../linux/drm_command_stream_fixture.h | 2 +- .../os_interface/linux/drm_mock_impl.h | 2 +- .../os_interface/linux/drm_tests.cpp | 8 +- .../linux/ioctl_helper_tests_prelim.cpp | 2 +- .../test/unit_test/test_files/igdrcl.config | 1 + .../debug_settings/debug_variables_base.inl | 1 + shared/source/os_interface/linux/drm_neo.cpp | 81 ++++- shared/source/os_interface/linux/drm_neo.h | 2 +- .../source/os_interface/linux/drm_query.cpp | 17 - .../source/os_interface/linux/ioctl_helper.h | 5 +- .../linux/ioctl_helper_getter.cpp | 6 +- .../linux/ioctl_helper_getter_upstream.cpp | 6 +- .../linux/ioctl_helper_prelim.cpp | 4 + .../linux/ioctl_helper_upstream.cpp | 4 + .../test/common/libult/linux/CMakeLists.txt | 14 +- shared/test/common/libult/linux/drm_mock.h | 2 +- .../common/libult/linux/drm_prelim_helper.cpp | 14 + .../common/libult/linux/drm_prelim_helper.h | 12 + .../common/libult/linux/drm_query_mock.cpp | 35 ++ .../test/common/libult/linux/drm_query_mock.h | 40 +++ .../libult/linux/drm_query_mock_context.h | 17 + .../libult/linux/drm_query_mock_prelim.cpp | 197 +++++++++++ .../linux/device_command_stream_fixture.cpp | 2 +- .../os_interface/linux/drm_neo_create.cpp | 2 +- .../os_interface/linux/CMakeLists.txt | 7 + .../os_interface/linux/drm_query_tests.cpp | 42 --- .../linux/drm_query_topology_prelim_tests.cpp | 316 ++++++++++++++++++ .../drm_query_topology_upstream_tests.cpp | 57 ++++ 30 files changed, 818 insertions(+), 84 deletions(-) create mode 100644 shared/test/common/libult/linux/drm_prelim_helper.cpp create mode 100644 shared/test/common/libult/linux/drm_prelim_helper.h create mode 100644 shared/test/common/libult/linux/drm_query_mock.cpp create mode 100644 shared/test/common/libult/linux/drm_query_mock.h create mode 100644 shared/test/common/libult/linux/drm_query_mock_context.h create mode 100644 shared/test/common/libult/linux/drm_query_mock_prelim.cpp create mode 100644 shared/test/unit_test/os_interface/linux/drm_query_topology_prelim_tests.cpp create mode 100644 shared/test/unit_test/os_interface/linux/drm_query_topology_upstream_tests.cpp diff --git a/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/test_zes_engine.cpp b/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/test_zes_engine.cpp index e7cfc6130a..9e83518030 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/test_zes_engine.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/test_zes_engine.cpp @@ -50,7 +50,7 @@ class ZesEngineFixture : public SysmanDeviceFixture { EngineHandleContext *pEngineHandleContext = pSysmanDeviceImp->pEngineHandleContext; pDrm = std::make_unique>>(const_cast(neoDevice->getRootDeviceEnvironment())); - pDrm->setupIoctlHelper(); + pDrm->setupIoctlHelper(neoDevice->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily); pPmuInterface = std::make_unique>>(pLinuxSysmanImp); pOriginalDrm = pLinuxSysmanImp->pDrm; pOriginalPmuInterface = pLinuxSysmanImp->pPmuInterface; diff --git a/level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h b/level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h index a020d15643..49d8c47e4b 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/linux/mock_sysman_fixture.h @@ -32,7 +32,7 @@ constexpr int mockFd = 0; class SysmanMockDrm : public Drm { public: SysmanMockDrm(RootDeviceEnvironment &rootDeviceEnvironment) : Drm(std::make_unique(mockFd, ""), rootDeviceEnvironment) { - setupIoctlHelper(); + setupIoctlHelper(rootDeviceEnvironment.getHardwareInfo()->platform.eProductFamily); } }; diff --git a/opencl/test/unit_test/os_interface/linux/drm_command_stream_fixture.h b/opencl/test/unit_test/os_interface/linux/drm_command_stream_fixture.h index 4ad215d29e..a94e2c1ec6 100644 --- a/opencl/test/unit_test/os_interface/linux/drm_command_stream_fixture.h +++ b/opencl/test/unit_test/os_interface/linux/drm_command_stream_fixture.h @@ -40,7 +40,7 @@ class DrmCommandStreamTest : public ::testing::Test { auto hwInfo = executionEnvironment.rootDeviceEnvironments[0]->getHardwareInfo(); mock->createVirtualMemoryAddressSpace(HwHelper::getSubDevicesCount(hwInfo)); - mock->setupIoctlHelper(); + mock->setupIoctlHelper(hwInfo->platform.eProductFamily); osContext = std::make_unique(*mock, 0u, EngineDescriptorHelper::getDefaultDescriptor(HwHelper::get(hwInfo->platform.eRenderCoreFamily).getGpgpuEngineInstances(*hwInfo)[0], PreemptionHelper::getDefaultPreemptionMode(*hwInfo))); diff --git a/opencl/test/unit_test/os_interface/linux/drm_mock_impl.h b/opencl/test/unit_test/os_interface/linux/drm_mock_impl.h index 457ac5bee2..727c53ae49 100644 --- a/opencl/test/unit_test/os_interface/linux/drm_mock_impl.h +++ b/opencl/test/unit_test/os_interface/linux/drm_mock_impl.h @@ -20,7 +20,7 @@ class DrmTipMock : public DrmMock { DrmTipMock(RootDeviceEnvironment &rootDeviceEnvironment) : DrmTipMock(rootDeviceEnvironment, defaultHwInfo.get()) {} DrmTipMock(RootDeviceEnvironment &rootDeviceEnvironment, const HardwareInfo *inputHwInfo) : DrmMock(rootDeviceEnvironment) { rootDeviceEnvironment.setHwInfo(inputHwInfo); - setupIoctlHelper(); + setupIoctlHelper(inputHwInfo->platform.eProductFamily); } uint32_t i915QuerySuccessCount = std::numeric_limits::max(); diff --git a/opencl/test/unit_test/os_interface/linux/drm_tests.cpp b/opencl/test/unit_test/os_interface/linux/drm_tests.cpp index 246c2dfb59..5eff2102a2 100644 --- a/opencl/test/unit_test/os_interface/linux/drm_tests.cpp +++ b/opencl/test/unit_test/os_interface/linux/drm_tests.cpp @@ -736,6 +736,7 @@ TEST(DrmQueryTest, GivenDrmWhenSetupHardwareInfoCalledThenCorrectMaxValuesInGtSy auto setupHardwareInfo = [](HardwareInfo *, bool) {}; DeviceDescriptor device = {0, hwInfo, setupHardwareInfo}; + drm.ioctlHelper.reset(); drm.setupHardwareInfo(&device, false); EXPECT_NE(nullptr, drm.getIoctlHelper()); EXPECT_EQ(NEO::defaultHwInfo->gtSystemInfo.MaxSlicesSupported, hwInfo->gtSystemInfo.MaxSlicesSupported); @@ -1005,7 +1006,8 @@ TEST(DrmQueryTest, givenUapiPrelimVersionWithInvalidPathThenReturnEmptyString) { } TEST(DrmTest, givenInvalidUapiPrelimVersionThenFallbackToBasePrelim) { - std::unique_ptr ioctlHelper(IoctlHelper::get(defaultHwInfo.get(), "-1")); + const auto productFamily = defaultHwInfo.get()->platform.eProductFamily; + std::unique_ptr ioctlHelper(IoctlHelper::get(productFamily, "-1")); EXPECT_NE(nullptr, ioctlHelper.get()); } @@ -1192,7 +1194,9 @@ TEST(DrmTest, givenSetupIoctlHelperThenIoctlHelperNotNull) { DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; drm.ioctlHelper.reset(nullptr); - drm.setupIoctlHelper(); + + const auto productFamily = executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo()->platform.eProductFamily; + drm.setupIoctlHelper(productFamily); EXPECT_NE(nullptr, drm.ioctlHelper.get()); } diff --git a/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_prelim.cpp b/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_prelim.cpp index 33dd065801..6fb088e39a 100644 --- a/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_prelim.cpp +++ b/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_prelim.cpp @@ -45,7 +45,7 @@ class IoctlHelperPrelimFixture : public ::testing::Test { executionEnvironment = std::make_unique(); executionEnvironment->prepareRootDeviceEnvironments(1); drm = std::make_unique(*executionEnvironment->rootDeviceEnvironments[0]); - drm->setupIoctlHelper(); + drm->setupIoctlHelper(executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo()->platform.eProductFamily); } std::unique_ptr executionEnvironment; diff --git a/opencl/test/unit_test/test_files/igdrcl.config b/opencl/test/unit_test/test_files/igdrcl.config index 2acdde3aaa..c48f4b2c27 100644 --- a/opencl/test/unit_test/test_files/igdrcl.config +++ b/opencl/test/unit_test/test_files/igdrcl.config @@ -369,3 +369,4 @@ ForceExtendedBufferSize = -1 MakeIndirectAllocationsResidentAsPack = -1 EnableChipsetUniqueUUID = -1 ForceSimdMessageSizeInWalker = -1 +UseNewQueryTopoIoctl = 1 diff --git a/shared/source/debug_settings/debug_variables_base.inl b/shared/source/debug_settings/debug_variables_base.inl index 28bb13d152..19e8ed7c6a 100644 --- a/shared/source/debug_settings/debug_variables_base.inl +++ b/shared/source/debug_settings/debug_variables_base.inl @@ -73,6 +73,7 @@ DECLARE_DEBUG_VARIABLE(bool, AllowMixingRegularAndCooperativeKernels, false, "tr DECLARE_DEBUG_VARIABLE(bool, AllowPatchingVfeStateInCommandLists, false, "true: MEDIA_VFE_STATE may be programmed in a command list") DECLARE_DEBUG_VARIABLE(bool, PrintMemoryRegionSizes, false, "print memory bank type, instance and it's size") DECLARE_DEBUG_VARIABLE(bool, UpdateCrossThreadDataSize, false, "Turn on cross thread data size calculation for PATCH TOKEN binary") +DECLARE_DEBUG_VARIABLE(bool, UseNewQueryTopoIoctl, true, "Use DRM_I915_QUERY_COMPUTE_SLICES") DECLARE_DEBUG_VARIABLE(std::string, ForceDeviceId, std::string("unk"), "DeviceId selected for testing") DECLARE_DEBUG_VARIABLE(std::string, FilterDeviceId, std::string("unk"), "Device id filter, adapter matching device id will be opened. Ignored when unk.") DECLARE_DEBUG_VARIABLE(std::string, FilterBdfPath, std::string("unk"), "Linux-only, BDF path filter, only matching paths will be opened. Ignored when unk.") diff --git a/shared/source/os_interface/linux/drm_neo.cpp b/shared/source/os_interface/linux/drm_neo.cpp index 848ec267f3..fb6125ed0c 100644 --- a/shared/source/os_interface/linux/drm_neo.cpp +++ b/shared/source/os_interface/linux/drm_neo.cpp @@ -481,6 +481,9 @@ int Drm::setupHardwareInfo(DeviceDescriptor *device, bool setupFeatureTableAndWo HardwareInfo *hwInfo = const_cast(device->pHwInfo); int ret; + const auto productFamily = hwInfo->platform.eProductFamily; + setupIoctlHelper(productFamily); + Drm::QueryTopologyData topologyData = {}; bool status = queryTopology(*hwInfo, topologyData); @@ -506,7 +509,6 @@ int Drm::setupHardwareInfo(DeviceDescriptor *device, bool setupFeatureTableAndWo hwInfo->gtSystemInfo.DualSubSliceCount = static_cast(topologyData.subSliceCount); hwInfo->gtSystemInfo.EUCount = static_cast(topologyData.euCount); rootDeviceEnvironment.setHwInfo(hwInfo); - setupIoctlHelper(); status = querySystemInfo(); if (status) { @@ -1081,11 +1083,82 @@ bool Drm::completionFenceSupport() { return completionFenceSupported; } -void Drm::setupIoctlHelper() { - auto hwInfo = rootDeviceEnvironment.getHardwareInfo(); +void Drm::setupIoctlHelper(const PRODUCT_FAMILY productFamily) { std::string prelimVersion = ""; getPrelimVersion(prelimVersion); - this->ioctlHelper.reset(IoctlHelper::get(hwInfo, prelimVersion)); + this->ioctlHelper.reset(IoctlHelper::get(productFamily, prelimVersion)); +} + +bool Drm::queryTopology(const HardwareInfo &hwInfo, QueryTopologyData &topologyData) { + topologyData.sliceCount = 0; + topologyData.subSliceCount = 0; + topologyData.euCount = 0; + + int sliceCount = 0; + int subSliceCount = 0; + int euCount = 0; + + const auto queryComputeSlicesIoctl = ioctlHelper->getComputeSlicesIoctlVal(); + if (DebugManager.flags.UseNewQueryTopoIoctl.get() && this->engineInfo && hwInfo.gtSystemInfo.MultiTileArchInfo.TileCount > 0 && queryComputeSlicesIoctl != 0) { + bool success = true; + + for (uint32_t i = 0; i < hwInfo.gtSystemInfo.MultiTileArchInfo.TileCount; i++) { + auto classInstance = this->engineInfo->getEngineInstance(i, hwInfo.capabilityTable.defaultEngineType); + UNRECOVERABLE_IF(!classInstance); + + uint32_t flags = classInstance->engineClass; + flags |= (classInstance->engineInstance << 8); + + auto dataQuery = this->query(queryComputeSlicesIoctl, flags); + if (dataQuery.empty()) { + success = false; + break; + } + auto data = reinterpret_cast(dataQuery.data()); + + QueryTopologyData tileTopologyData = {}; + TopologyMapping mapping; + if (!translateTopologyInfo(data, tileTopologyData, mapping)) { + success = false; + break; + } + + // pick smallest config + sliceCount = (sliceCount == 0) ? tileTopologyData.sliceCount : std::min(sliceCount, tileTopologyData.sliceCount); + subSliceCount = (subSliceCount == 0) ? tileTopologyData.subSliceCount : std::min(subSliceCount, tileTopologyData.subSliceCount); + euCount = (euCount == 0) ? tileTopologyData.euCount : std::min(euCount, tileTopologyData.euCount); + + topologyData.maxSliceCount = std::max(topologyData.maxSliceCount, tileTopologyData.maxSliceCount); + topologyData.maxSubSliceCount = std::max(topologyData.maxSubSliceCount, tileTopologyData.maxSubSliceCount); + topologyData.maxEuCount = std::max(topologyData.maxEuCount, static_cast(data->max_eus_per_subslice)); + + this->topologyMap[i] = mapping; + } + + if (success) { + topologyData.sliceCount = sliceCount; + topologyData.subSliceCount = subSliceCount; + topologyData.euCount = euCount; + return true; + } + } + + // fallback to DRM_I915_QUERY_TOPOLOGY_INFO + + auto dataQuery = this->query(DRM_I915_QUERY_TOPOLOGY_INFO, DrmQueryItemFlags::topology); + if (dataQuery.empty()) { + return false; + } + auto data = reinterpret_cast(dataQuery.data()); + + TopologyMapping mapping; + auto retVal = translateTopologyInfo(data, topologyData, mapping); + topologyData.maxEuCount = data->max_eus_per_subslice; + + this->topologyMap.clear(); + this->topologyMap[0] = mapping; + + return retVal; } } // namespace NEO diff --git a/shared/source/os_interface/linux/drm_neo.h b/shared/source/os_interface/linux/drm_neo.h index 06c0e688f8..ce03821bde 100644 --- a/shared/source/os_interface/linux/drm_neo.h +++ b/shared/source/os_interface/linux/drm_neo.h @@ -267,7 +267,7 @@ class Drm : public DriverModel { std::string getSysFsPciPath(); std::vector query(uint32_t queryId, uint32_t queryItemFlags); void printIoctlStatistics(); - void setupIoctlHelper(); + void setupIoctlHelper(const PRODUCT_FAMILY productFamily); #pragma pack(1) struct PCIConfig { diff --git a/shared/source/os_interface/linux/drm_query.cpp b/shared/source/os_interface/linux/drm_query.cpp index dbee0bb2ba..9b3628c7c4 100644 --- a/shared/source/os_interface/linux/drm_query.cpp +++ b/shared/source/os_interface/linux/drm_query.cpp @@ -49,23 +49,6 @@ int Drm::createDrmVirtualMemory(uint32_t &drmVmId) { return ret; } -bool Drm::queryTopology(const HardwareInfo &hwInfo, QueryTopologyData &topologyData) { - auto dataQuery = this->query(DRM_I915_QUERY_TOPOLOGY_INFO, DrmQueryItemFlags::topology); - if (dataQuery.empty()) { - return false; - } - auto data = reinterpret_cast(dataQuery.data()); - - topologyData.maxSliceCount = data->max_slices; - topologyData.maxSubSliceCount = data->max_subslices; - topologyData.maxEuCount = data->max_eus_per_subslice; - - TopologyMapping mapping; - auto result = translateTopologyInfo(data, topologyData, mapping); - this->topologyMap[0] = mapping; - return result; -} - bool Drm::isDebugAttachAvailable() { return false; } diff --git a/shared/source/os_interface/linux/ioctl_helper.h b/shared/source/os_interface/linux/ioctl_helper.h index 87b657e864..68a1a9e12c 100644 --- a/shared/source/os_interface/linux/ioctl_helper.h +++ b/shared/source/os_interface/linux/ioctl_helper.h @@ -59,7 +59,7 @@ using MemRegionsVec = StackVec; class IoctlHelper { public: virtual ~IoctlHelper() {} - static IoctlHelper *get(const HardwareInfo *hwInfo, const std::string &prelimVersion); + static IoctlHelper *get(const PRODUCT_FAMILY productFamily, const std::string &prelimVersion); static uint32_t ioctl(Drm *drm, unsigned long request, void *arg); virtual IoctlHelper *clone() = 0; @@ -77,6 +77,7 @@ class IoctlHelper { virtual uint32_t getDirectSubmissionFlag() = 0; virtual int32_t getMemRegionsIoctlVal() = 0; virtual int32_t getEngineInfoIoctlVal() = 0; + virtual uint32_t getComputeSlicesIoctlVal() = 0; virtual std::vector translateToEngineCaps(const std::vector &data) = 0; virtual uint32_t queryDistances(Drm *drm, std::vector &queryItems, std::vector &distanceInfos) = 0; virtual int32_t getComputeEngineClass() = 0; @@ -102,6 +103,7 @@ class IoctlHelperUpstream : public IoctlHelper { uint32_t getDirectSubmissionFlag() override; int32_t getMemRegionsIoctlVal() override; int32_t getEngineInfoIoctlVal() override; + uint32_t getComputeSlicesIoctlVal() override; std::vector translateToEngineCaps(const std::vector &data) override; uint32_t queryDistances(Drm *drm, std::vector &queryItems, std::vector &distanceInfos) override; int32_t getComputeEngineClass() override; @@ -140,6 +142,7 @@ class IoctlHelperPrelim20 : public IoctlHelper { uint32_t getDirectSubmissionFlag() override; int32_t getMemRegionsIoctlVal() override; int32_t getEngineInfoIoctlVal() override; + uint32_t getComputeSlicesIoctlVal() override; std::vector translateToEngineCaps(const std::vector &data) override; uint32_t queryDistances(Drm *drm, std::vector &queryItems, std::vector &distanceInfos) override; int32_t getComputeEngineClass() override; diff --git a/shared/source/os_interface/linux/ioctl_helper_getter.cpp b/shared/source/os_interface/linux/ioctl_helper_getter.cpp index 3d49a8b500..f4d0ec3f6a 100644 --- a/shared/source/os_interface/linux/ioctl_helper_getter.cpp +++ b/shared/source/os_interface/linux/ioctl_helper_getter.cpp @@ -20,10 +20,8 @@ std::map> ioctlHelperImpls{ {"", std::make_shared()}, {"2.0", std::make_shared()}}; -IoctlHelper *IoctlHelper::get(const HardwareInfo *hwInfo, const std::string &prelimVersion) { - auto product = hwInfo->platform.eProductFamily; - - auto productSpecificIoctlHelper = ioctlHelperFactory[product]; +IoctlHelper *IoctlHelper::get(const PRODUCT_FAMILY productFamily, const std::string &prelimVersion) { + auto productSpecificIoctlHelper = ioctlHelperFactory[productFamily]; if (productSpecificIoctlHelper) { return productSpecificIoctlHelper->clone(); } diff --git a/shared/source/os_interface/linux/ioctl_helper_getter_upstream.cpp b/shared/source/os_interface/linux/ioctl_helper_getter_upstream.cpp index bb72ae2e9e..81d257721c 100644 --- a/shared/source/os_interface/linux/ioctl_helper_getter_upstream.cpp +++ b/shared/source/os_interface/linux/ioctl_helper_getter_upstream.cpp @@ -13,10 +13,8 @@ namespace NEO { IoctlHelper *ioctlHelperFactory[IGFX_MAX_PRODUCT] = {}; -IoctlHelper *IoctlHelper::get(const HardwareInfo *hwInfo, const std::string &prelimVersion) { - auto product = hwInfo->platform.eProductFamily; - - auto productSpecificIoctlHelper = ioctlHelperFactory[product]; +IoctlHelper *IoctlHelper::get(const PRODUCT_FAMILY productFamily, const std::string &prelimVersion) { + auto productSpecificIoctlHelper = ioctlHelperFactory[productFamily]; if (productSpecificIoctlHelper) { return productSpecificIoctlHelper->clone(); } diff --git a/shared/source/os_interface/linux/ioctl_helper_prelim.cpp b/shared/source/os_interface/linux/ioctl_helper_prelim.cpp index c4139ad646..772044be34 100644 --- a/shared/source/os_interface/linux/ioctl_helper_prelim.cpp +++ b/shared/source/os_interface/linux/ioctl_helper_prelim.cpp @@ -194,6 +194,10 @@ int32_t IoctlHelperPrelim20::getEngineInfoIoctlVal() { return PRELIM_DRM_I915_QUERY_ENGINE_INFO; } +uint32_t IoctlHelperPrelim20::getComputeSlicesIoctlVal() { + return PRELIM_DRM_I915_QUERY_COMPUTE_SLICES; +} + std::vector IoctlHelperPrelim20::translateToEngineCaps(const std::vector &data) { auto engineInfo = reinterpret_cast(data.data()); std::vector engines; diff --git a/shared/source/os_interface/linux/ioctl_helper_upstream.cpp b/shared/source/os_interface/linux/ioctl_helper_upstream.cpp index 63c48d7fae..bac468c4e2 100644 --- a/shared/source/os_interface/linux/ioctl_helper_upstream.cpp +++ b/shared/source/os_interface/linux/ioctl_helper_upstream.cpp @@ -109,6 +109,10 @@ int32_t IoctlHelperUpstream::getEngineInfoIoctlVal() { return DRM_I915_QUERY_ENGINE_INFO; } +uint32_t IoctlHelperUpstream::getComputeSlicesIoctlVal() { + return 0; +} + std::vector IoctlHelperUpstream::translateToEngineCaps(const std::vector &data) { auto engineInfo = reinterpret_cast(data.data()); std::vector engines; diff --git a/shared/test/common/libult/linux/CMakeLists.txt b/shared/test/common/libult/linux/CMakeLists.txt index 0b96ad5992..15ed91354f 100644 --- a/shared/test/common/libult/linux/CMakeLists.txt +++ b/shared/test/common/libult/linux/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2021 Intel Corporation +# Copyright (C) 2021-2022 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -11,6 +11,18 @@ if(UNIX) ${CMAKE_CURRENT_SOURCE_DIR}/drm_mock.h ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}drm_mock_engine.cpp ) + + if(NEO_ENABLE_i915_PRELIM_DETECTION) + target_sources(neo_libult_common PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/drm_query_mock.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drm_query_mock.h + ${CMAKE_CURRENT_SOURCE_DIR}/drm_query_mock_context.h + ${CMAKE_CURRENT_SOURCE_DIR}/drm_query_mock_prelim.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drm_prelim_helper.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drm_prelim_helper.h + ) + endif() + target_sources(neo_libult PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/directory_linux.cpp ) diff --git a/shared/test/common/libult/linux/drm_mock.h b/shared/test/common/libult/linux/drm_mock.h index bb041879ce..6144057965 100644 --- a/shared/test/common/libult/linux/drm_mock.h +++ b/shared/test/common/libult/linux/drm_mock.h @@ -58,7 +58,7 @@ class DrmMock : public Drm { if (!isPerContextVMRequired()) { createVirtualMemoryAddressSpace(HwHelper::getSubDevicesCount(rootDeviceEnvironment.getHardwareInfo())); } - setupIoctlHelper(); + setupIoctlHelper(rootDeviceEnvironment.getHardwareInfo()->platform.eProductFamily); } DrmMock(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMock(mockFd, rootDeviceEnvironment) {} diff --git a/shared/test/common/libult/linux/drm_prelim_helper.cpp b/shared/test/common/libult/linux/drm_prelim_helper.cpp new file mode 100644 index 0000000000..0dd163c510 --- /dev/null +++ b/shared/test/common/libult/linux/drm_prelim_helper.cpp @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/common/libult/linux/drm_prelim_helper.h" + +#include "third_party/uapi/prelim/drm/i915_drm.h" + +uint32_t getQueryComputeSlicesIoctl() { + return PRELIM_DRM_I915_QUERY_COMPUTE_SLICES; +} diff --git a/shared/test/common/libult/linux/drm_prelim_helper.h b/shared/test/common/libult/linux/drm_prelim_helper.h new file mode 100644 index 0000000000..29e3325204 --- /dev/null +++ b/shared/test/common/libult/linux/drm_prelim_helper.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include + +uint32_t getQueryComputeSlicesIoctl(); diff --git a/shared/test/common/libult/linux/drm_query_mock.cpp b/shared/test/common/libult/linux/drm_query_mock.cpp new file mode 100644 index 0000000000..828be7c98d --- /dev/null +++ b/shared/test/common/libult/linux/drm_query_mock.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/test/common/libult/linux/drm_query_mock.h" + +extern int handlePrelimDrmQueryRequests(DrmQueryMockContext &context, unsigned long request, void *arg); +extern bool handlePrelimDrmQueryItem(DrmQueryMockContext &context, void *arg); + +int DrmQueryMock::handleRemainingRequests(unsigned long request, void *arg) { + if (request == DRM_IOCTL_I915_QUERY && arg) { + auto query = static_cast(arg); + if (query->items_ptr == 0) { + return EINVAL; + } + + for (auto i = 0u; i < query->num_items; ++i) { + const auto queryItem = reinterpret_cast(query->items_ptr) + i; + if (!this->handleQueryItem(queryItem)) { + return EINVAL; + } + } + + return 0; + } + + return handlePrelimDrmQueryRequests(context, request, arg); +} + +bool DrmQueryMock::handleQueryItem(void *arg) { + return handlePrelimDrmQueryItem(context, arg); +} diff --git a/shared/test/common/libult/linux/drm_query_mock.h b/shared/test/common/libult/linux/drm_query_mock.h new file mode 100644 index 0000000000..0a34e7d7ad --- /dev/null +++ b/shared/test/common/libult/linux/drm_query_mock.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "shared/source/execution_environment/root_device_environment.h" +#include "shared/source/os_interface/linux/ioctl_helper.h" +#include "shared/test/common/helpers/default_hw_info.h" +#include "shared/test/common/libult/linux/drm_mock.h" +#include "shared/test/common/libult/linux/drm_query_mock_context.h" + +using namespace NEO; + +class DrmQueryMock : public DrmMock { + public: + DrmQueryMock(RootDeviceEnvironment &rootDeviceEnvironment) : DrmQueryMock(rootDeviceEnvironment, defaultHwInfo.get()) {} + DrmQueryMock(RootDeviceEnvironment &rootDeviceEnvironment, const HardwareInfo *inputHwInfo) : DrmMock(rootDeviceEnvironment) { + rootDeviceEnvironment.setHwInfo(inputHwInfo); + context.hwInfo = rootDeviceEnvironment.getHardwareInfo(); + + setupIoctlHelper(IGFX_UNKNOWN); + } + + void getPrelimVersion(std::string &prelimVersion) override { + prelimVersion = "2.0"; + } + + DrmQueryMockContext context{ + .hwInfo = nullptr, + .rootDeviceEnvironment = rootDeviceEnvironment, + .failRetTopology = failRetTopology, + }; + + int handleRemainingRequests(unsigned long request, void *arg) override; + virtual bool handleQueryItem(void *queryItem); +}; diff --git a/shared/test/common/libult/linux/drm_query_mock_context.h b/shared/test/common/libult/linux/drm_query_mock_context.h new file mode 100644 index 0000000000..c1f36a136a --- /dev/null +++ b/shared/test/common/libult/linux/drm_query_mock_context.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/execution_environment/root_device_environment.h" +#include "shared/source/helpers/hw_info.h" + +using namespace NEO; + +struct DrmQueryMockContext { + const HardwareInfo *hwInfo; + const RootDeviceEnvironment &rootDeviceEnvironment; + const bool &failRetTopology; +}; diff --git a/shared/test/common/libult/linux/drm_query_mock_prelim.cpp b/shared/test/common/libult/linux/drm_query_mock_prelim.cpp new file mode 100644 index 0000000000..d6d63db7ff --- /dev/null +++ b/shared/test/common/libult/linux/drm_query_mock_prelim.cpp @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/helpers/basic_math.h" +#include "shared/source/helpers/ptr_math.h" +#include "shared/test/common/libult/linux/drm_query_mock_context.h" + +#include "third_party/uapi/prelim/drm/i915_drm.h" +#include + +#include +#include + +namespace { + +uint32_t getTileFromEngineOrMemoryInstance(uint16_t instanceValue) { + uint8_t tileMask = (instanceValue >> 8); + return Math::log2(static_cast(tileMask)); +} + +uint16_t getEngineOrMemoryInstanceValue(uint16_t tile, uint16_t id) { + EXPECT_TRUE(id < 256); + uint16_t tileMask = ((1 << tile) << 8); + return (id | tileMask); +} + +constexpr BcsInfoMask supportedCopyEnginesMask = 1; + +constexpr std::array copyEnginesCapsMap = {{ + PRELIM_I915_COPY_CLASS_CAP_SATURATE_LMEM, + PRELIM_I915_COPY_CLASS_CAP_SATURATE_PCIE, + PRELIM_I915_COPY_CLASS_CAP_SATURATE_PCIE, + PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, + PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, + PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, + PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, + PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, + PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, +}}; + +} // namespace + +int handlePrelimDrmQueryRequests(DrmQueryMockContext &context, unsigned long request, void *arg) { + return -1; +} + +bool handlePrelimDrmQueryItem(DrmQueryMockContext &context, void *arg) { + auto queryItem = reinterpret_cast(arg); + + auto >SystemInfo = context.hwInfo->gtSystemInfo; + auto numberOfCCS = gtSystemInfo.CCSInfo.IsValid ? gtSystemInfo.CCSInfo.NumberOfCCSEnabled : 0u; + + switch (queryItem->query_id) { + case PRELIM_DRM_I915_QUERY_ENGINE_INFO: { + auto numberOfTiles = gtSystemInfo.MultiTileArchInfo.IsValid ? gtSystemInfo.MultiTileArchInfo.TileCount : 1u; + uint32_t numberOfEngines = numberOfTiles * (4u + numberOfCCS + static_cast(supportedCopyEnginesMask.count())); + int engineInfoSize = sizeof(prelim_drm_i915_query_engine_info) + numberOfEngines * sizeof(prelim_drm_i915_engine_info); + if (queryItem->length == 0) { + queryItem->length = engineInfoSize; + } else { + EXPECT_EQ(engineInfoSize, queryItem->length); + auto queryEngineInfo = reinterpret_cast(queryItem->data_ptr); + EXPECT_EQ(0u, queryEngineInfo->num_engines); + queryEngineInfo->num_engines = numberOfEngines; + auto p = queryEngineInfo->engines; + for (uint32_t tile = 0u; tile < numberOfTiles; tile++) { + p++->engine = {I915_ENGINE_CLASS_RENDER, getEngineOrMemoryInstanceValue(tile, 0)}; + for (uint32_t i = 0u; i < supportedCopyEnginesMask.size(); i++) { + if (supportedCopyEnginesMask.test(i)) { + auto copyEngineInfo = p++; + copyEngineInfo->engine = {I915_ENGINE_CLASS_COPY, getEngineOrMemoryInstanceValue(tile, i)}; + copyEngineInfo->capabilities = copyEnginesCapsMap[i]; + } + } + p++->engine = {I915_ENGINE_CLASS_VIDEO, getEngineOrMemoryInstanceValue(tile, 0)}; + p++->engine = {I915_ENGINE_CLASS_VIDEO, getEngineOrMemoryInstanceValue(tile, 0)}; + p++->engine = {I915_ENGINE_CLASS_VIDEO_ENHANCE, getEngineOrMemoryInstanceValue(tile, 0)}; + for (auto i = 0u; i < numberOfCCS; i++) { + p++->engine = {PRELIM_I915_ENGINE_CLASS_COMPUTE, getEngineOrMemoryInstanceValue(tile, i)}; + } + } + } + break; + } + + case PRELIM_DRM_I915_QUERY_MEMORY_REGIONS: { + auto numberOfLocalMemories = gtSystemInfo.MultiTileArchInfo.IsValid ? gtSystemInfo.MultiTileArchInfo.TileCount : 0u; + auto numberOfRegions = 1u + numberOfLocalMemories; + + int regionInfoSize = sizeof(prelim_drm_i915_query_memory_regions) + numberOfRegions * sizeof(prelim_drm_i915_memory_region_info); + if (queryItem->length == 0) { + queryItem->length = regionInfoSize; + } else { + EXPECT_EQ(regionInfoSize, queryItem->length); + auto queryMemoryRegionInfo = reinterpret_cast(queryItem->data_ptr); + EXPECT_EQ(0u, queryMemoryRegionInfo->num_regions); + queryMemoryRegionInfo->num_regions = numberOfRegions; + queryMemoryRegionInfo->regions[0].region.memory_class = PRELIM_I915_MEMORY_CLASS_SYSTEM; + queryMemoryRegionInfo->regions[0].region.memory_instance = 1; + queryMemoryRegionInfo->regions[0].probed_size = 2 * MemoryConstants::gigaByte; + for (auto tile = 0u; tile < numberOfLocalMemories; tile++) { + queryMemoryRegionInfo->regions[1 + tile].region.memory_class = PRELIM_I915_MEMORY_CLASS_DEVICE; + queryMemoryRegionInfo->regions[1 + tile].region.memory_instance = getEngineOrMemoryInstanceValue(tile, 0); + queryMemoryRegionInfo->regions[1 + tile].probed_size = 2 * MemoryConstants::gigaByte; + } + } + } break; + + case PRELIM_DRM_I915_QUERY_DISTANCE_INFO: { + auto queryDistanceInfo = reinterpret_cast(queryItem->data_ptr); + switch (queryDistanceInfo->region.memory_class) { + case PRELIM_I915_MEMORY_CLASS_SYSTEM: + EXPECT_EQ(sizeof(prelim_drm_i915_query_distance_info), static_cast(queryItem->length)); + queryDistanceInfo->distance = -1; + break; + case PRELIM_I915_MEMORY_CLASS_DEVICE: { + EXPECT_EQ(sizeof(prelim_drm_i915_query_distance_info), static_cast(queryItem->length)); + + auto engineTile = getTileFromEngineOrMemoryInstance(queryDistanceInfo->engine.engine_instance); + auto memoryTile = getTileFromEngineOrMemoryInstance(queryDistanceInfo->region.memory_instance); + + queryDistanceInfo->distance = (memoryTile == engineTile) ? 0 : 100; + break; + } + default: + queryItem->length = -EINVAL; + break; + } + } break; + + case PRELIM_DRM_I915_QUERY_COMPUTE_SLICES: { + auto >SystemInfo = context.rootDeviceEnvironment.getHardwareInfo()->gtSystemInfo; + auto maxEuPerSubslice = gtSystemInfo.MaxEuPerSubSlice; + auto maxSlices = gtSystemInfo.MaxSlicesSupported; + auto maxSubslices = gtSystemInfo.MaxSubSlicesSupported / maxSlices; + auto threadsPerEu = gtSystemInfo.ThreadCount / gtSystemInfo.EUCount; + auto realEuCount = threadsPerEu * maxEuPerSubslice * maxSubslices * maxSlices; + + auto dataSize = static_cast(std::ceil(realEuCount / 8.0)) + maxSlices * static_cast(std::ceil(maxSubslices / 8.0)) + + static_cast(std::ceil(maxSlices / 8.0)); + + if (queryItem->length == 0) { + queryItem->length = static_cast(sizeof(drm_i915_query_topology_info) + dataSize); + break; + } else { + auto topologyArg = reinterpret_cast(queryItem->data_ptr); + if (context.failRetTopology) { + return false; + } + topologyArg->max_slices = maxSlices; + topologyArg->max_subslices = maxSubslices; + topologyArg->max_eus_per_subslice = maxEuPerSubslice; + + topologyArg->subslice_stride = static_cast(std::ceil(maxSubslices / 8.0)); + topologyArg->eu_stride = static_cast(std::ceil(maxEuPerSubslice / 8.0)); + topologyArg->subslice_offset = static_cast(std::ceil(maxSlices / 8.0)); + topologyArg->eu_offset = static_cast(std::ceil(maxSubslices / 8.0)) * maxSlices; + + int threadData = (threadsPerEu == 8) ? 0xff : 0x7f; + + uint8_t *data = topologyArg->data; + for (uint32_t sliceId = 0; sliceId < maxSlices; sliceId++) { + data[0] |= 1 << (sliceId % 8); + if (sliceId == 7 || sliceId == maxSlices - 1) { + data++; + } + } + + DEBUG_BREAK_IF(ptrDiff(data, topologyArg->data) != topologyArg->subslice_offset); + + data = ptrOffset(topologyArg->data, topologyArg->subslice_offset); + for (uint32_t sliceId = 0; sliceId < maxSlices; sliceId++) { + for (uint32_t i = 0; i < maxSubslices; i++) { + data[0] |= 1 << (i % 8); + + if (i == 7 || i == maxSubslices - 1) { + data++; + } + } + } + + DEBUG_BREAK_IF(ptrDiff(data, topologyArg->data) != topologyArg->eu_offset); + auto size = dataSize - topologyArg->eu_offset; + memset(ptrOffset(topologyArg->data, topologyArg->eu_offset), threadData, size); + } + } break; + + default: + queryItem->length = -EINVAL; + break; + } + return true; +} diff --git a/shared/test/common/os_interface/linux/device_command_stream_fixture.cpp b/shared/test/common/os_interface/linux/device_command_stream_fixture.cpp index f5033e06d3..b827bbecef 100644 --- a/shared/test/common/os_interface/linux/device_command_stream_fixture.cpp +++ b/shared/test/common/os_interface/linux/device_command_stream_fixture.cpp @@ -202,7 +202,7 @@ DrmMockCustom::DrmMockCustom(RootDeviceEnvironment &rootDeviceEnvironment) ioctl_expected.contextDestroy = ioctl_expected.contextCreate.load(); createVirtualMemoryAddressSpace(NEO::HwHelper::getSubDevicesCount(rootDeviceEnvironment.getHardwareInfo())); isVmBindAvailable(); - setupIoctlHelper(); + setupIoctlHelper(rootDeviceEnvironment.getHardwareInfo()->platform.eProductFamily); reset(); } diff --git a/shared/test/common/os_interface/linux/drm_neo_create.cpp b/shared/test/common/os_interface/linux/drm_neo_create.cpp index 4579edef4e..b552928b35 100644 --- a/shared/test/common/os_interface/linux/drm_neo_create.cpp +++ b/shared/test/common/os_interface/linux/drm_neo_create.cpp @@ -41,7 +41,7 @@ Drm *Drm::create(std::unique_ptr &&hwDeviceId, RootDeviceEnvironm const HardwareInfo *hwInfo = rootDeviceEnvironment.getHardwareInfo(); - drm->setupIoctlHelper(); + drm->setupIoctlHelper(hwInfo->platform.eProductFamily); drm->queryAdapterBDF(); diff --git a/shared/test/unit_test/os_interface/linux/CMakeLists.txt b/shared/test/unit_test/os_interface/linux/CMakeLists.txt index 5f0b8deaee..8d3e6a9799 100644 --- a/shared/test/unit_test/os_interface/linux/CMakeLists.txt +++ b/shared/test/unit_test/os_interface/linux/CMakeLists.txt @@ -7,12 +7,19 @@ set(NEO_CORE_OS_INTERFACE_TESTS_LINUX ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}${BRANCH_DIR_SUFFIX}drm_query_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drm_query_topology_upstream_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drm_special_heap_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/hw_info_config_uuid_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/os_context_linux_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drm_command_stream_l0_tests.cpp ) +if(NEO_ENABLE_i915_PRELIM_DETECTION) + list(APPEND NEO_CORE_OS_INTERFACE_TESTS_LINUX + ${CMAKE_CURRENT_SOURCE_DIR}/drm_query_topology_prelim_tests.cpp + ) +endif() + set_property(GLOBAL PROPERTY NEO_CORE_OS_INTERFACE_TESTS_LINUX ${NEO_CORE_OS_INTERFACE_TESTS_LINUX}) if(UNIX) diff --git a/shared/test/unit_test/os_interface/linux/drm_query_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_query_tests.cpp index d50ba90cf9..2a52b068ea 100644 --- a/shared/test/unit_test/os_interface/linux/drm_query_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_query_tests.cpp @@ -27,48 +27,6 @@ TEST(DrmQueryTest, WhenCallingIsDebugAttachAvailableThenReturnValueIsFalse) { EXPECT_FALSE(drm.isDebugAttachAvailable()); } -TEST(DrmQueryTest, GivenDrmWhenQueryingTopologyInfoCorrectMaxValuesAreSet) { - auto executionEnvironment = std::make_unique(); - executionEnvironment->prepareRootDeviceEnvironments(1); - - *executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo() = *NEO::defaultHwInfo.get(); - DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; - - Drm::QueryTopologyData topologyData = {}; - - EXPECT_TRUE(drm.queryTopology(*executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo(), topologyData)); - - EXPECT_EQ(drm.storedSVal, topologyData.sliceCount); - EXPECT_EQ(drm.storedSSVal, topologyData.subSliceCount); - EXPECT_EQ(drm.storedEUVal, topologyData.euCount); - - EXPECT_EQ(drm.storedSVal, topologyData.maxSliceCount); - EXPECT_EQ(drm.storedSSVal / drm.storedSVal, topologyData.maxSubSliceCount); - EXPECT_EQ(drm.storedEUVal / drm.storedSSVal, topologyData.maxEuCount); -} - -TEST(DrmQueryTest, givenDrmWhenGettingSliceMappingsThenCorrectMappingReturned) { - auto executionEnvironment = std::make_unique(); - executionEnvironment->prepareRootDeviceEnvironments(1); - - *executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo() = *NEO::defaultHwInfo.get(); - DrmMock drmMock{*executionEnvironment->rootDeviceEnvironments[0]}; - - Drm::QueryTopologyData topologyData = {}; - - EXPECT_TRUE(drmMock.queryTopology(*executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo(), topologyData)); - - auto device0SliceMapping = drmMock.getSliceMappings(0); - auto device1SliceMapping = drmMock.getSliceMappings(1); - - ASSERT_EQ(static_cast(topologyData.maxSliceCount), device0SliceMapping.size()); - EXPECT_EQ(0u, device1SliceMapping.size()); - - for (int i = 0; i < topologyData.maxSliceCount; i++) { - EXPECT_EQ(i, device0SliceMapping[i]); - } -} - using HwConfigTopologyQuery = ::testing::Test; HWTEST2_F(HwConfigTopologyQuery, WhenGettingTopologyFailsThenSetMaxValuesBasedOnSubsliceIoctlQuery, MatchAny) { diff --git a/shared/test/unit_test/os_interface/linux/drm_query_topology_prelim_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_query_topology_prelim_tests.cpp new file mode 100644 index 0000000000..98262aaa20 --- /dev/null +++ b/shared/test/unit_test/os_interface/linux/drm_query_topology_prelim_tests.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/helpers/hw_info.h" +#include "shared/source/os_interface/hw_info_config.h" +#include "shared/source/os_interface/os_interface.h" +#include "shared/test/common/helpers/debug_manager_state_restore.h" +#include "shared/test/common/helpers/default_hw_info.h" +#include "shared/test/common/libult/linux/drm_prelim_helper.h" +#include "shared/test/common/libult/linux/drm_query_mock.h" +#include "shared/test/common/test_macros/test.h" + +#include "gtest/gtest.h" + +TEST(DrmQueryTopologyTest, givenDrmWhenQueryTopologyCalledThenPassNoFlags) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmQueryMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + Drm::QueryTopologyData topologyData = {}; + + EXPECT_TRUE(drm.queryTopology(*drm.context.hwInfo, topologyData)); + + constexpr uint32_t expectedFlag = 0; + EXPECT_EQ(expectedFlag, drm.storedQueryItem.flags); +} + +struct QueryTopologyTests : ::testing::Test { + class MyDrmQueryMock : public DrmQueryMock { + public: + using DrmQueryMock::DrmQueryMock; + + bool handleQueryItem(void *arg) override { + const auto queryItem = reinterpret_cast(arg); + if (queryItem->query_id != getQueryComputeSlicesIoctl()) { + return DrmQueryMock::handleQueryItem(queryItem); + } + + queryComputeSlicesCallCount++; + + if (failOnQuery) { + return false; + } + + auto realEuCount = rootDeviceEnvironment.getHardwareInfo()->gtSystemInfo.EUCount; + auto dataSize = static_cast(std::ceil(realEuCount / 8.0)); + + if (queryItem->length == 0) { + queryItem->length = static_cast(sizeof(drm_i915_query_topology_info) + dataSize); + } else { + auto topologyArg = reinterpret_cast(queryItem->data_ptr); + + uint16_t finalSVal = queryComputeSlicesSCount; + uint16_t finalSSVal = queryComputeSlicesSSCount; + uint16_t finalEUVal = queryComputeSlicesEuCount; + + if (useSmallerValuesOnSecondCall && queryComputeSlicesCallCount == 2) { + finalSVal /= 2; + finalSSVal /= 2; + finalEUVal /= 2; + } + + topologyArg->max_slices = finalSVal; + topologyArg->max_subslices = (finalSSVal / finalSVal); + topologyArg->max_eus_per_subslice = (finalEUVal / finalSSVal); + + memset(topologyArg->data, 0xFF, dataSize); + } + + return true; + } + + uint32_t queryComputeSlicesCallCount = 0; + + uint16_t queryComputeSlicesSCount = 0; + uint16_t queryComputeSlicesSSCount = 0; + uint16_t queryComputeSlicesEuCount = 0; + + bool useSmallerValuesOnSecondCall = false; + bool failOnQuery = false; + }; + + void SetUp() override { + executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + + rootDeviceEnvironment = executionEnvironment->rootDeviceEnvironments[0].get(); + rootDeviceEnvironment->setHwInfo(NEO::defaultHwInfo.get()); + } + + void createDrm(uint32_t tileCount) { + GT_MULTI_TILE_ARCH_INFO &multiTileArch = rootDeviceEnvironment->getMutableHardwareInfo()->gtSystemInfo.MultiTileArchInfo; + multiTileArch.IsValid = (tileCount > 0); + multiTileArch.TileCount = tileCount; + multiTileArch.TileMask = static_cast(maxNBitValue(tileCount)); + + drmMock = std::make_unique(*rootDeviceEnvironment, rootDeviceEnvironment->getHardwareInfo()); + + drmMock->storedSVal = 8; + drmMock->storedSSVal = 32; + drmMock->storedEUVal = 512; + + drmMock->queryComputeSlicesSCount = 4; + drmMock->queryComputeSlicesSSCount = 16; + drmMock->queryComputeSlicesEuCount = 256; + + EXPECT_TRUE(drmMock->queryMemoryInfo()); + EXPECT_TRUE(drmMock->queryEngineInfo()); + } + + DebugManagerStateRestore stateRestorer; + std::unique_ptr executionEnvironment; + std::unique_ptr drmMock; + RootDeviceEnvironment *rootDeviceEnvironment; + int receivedSliceCount = 0; + int receivedSubSliceCount = 0; + int receivedEuCount = 0; +}; + +TEST_F(QueryTopologyTests, givenZeroTilesWhenQueryingThenFallbackToQueryTopology) { + createDrm(0); + + Drm::QueryTopologyData topologyData = {}; + + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + EXPECT_EQ(0u, drmMock->queryComputeSlicesCallCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.sliceCount); + EXPECT_EQ(drmMock->storedSSVal, topologyData.subSliceCount); + EXPECT_EQ(drmMock->storedEUVal, topologyData.euCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.maxSliceCount); + EXPECT_EQ(drmMock->storedSSVal / drmMock->storedSVal, topologyData.maxSubSliceCount); + EXPECT_EQ(drmMock->storedEUVal / drmMock->storedSSVal, topologyData.maxEuCount); +} + +TEST_F(QueryTopologyTests, givenNonZeroTilesWhenDebugFlagDisabledThenFallbackToQueryTopology) { + DebugManager.flags.UseNewQueryTopoIoctl.set(false); + createDrm(2); + + Drm::QueryTopologyData topologyData = {}; + + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + EXPECT_EQ(0u, drmMock->queryComputeSlicesCallCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.sliceCount); + EXPECT_EQ(drmMock->storedSSVal, topologyData.subSliceCount); + EXPECT_EQ(drmMock->storedEUVal, topologyData.euCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.maxSliceCount); + EXPECT_EQ(drmMock->storedSSVal / drmMock->storedSVal, topologyData.maxSubSliceCount); + EXPECT_EQ(drmMock->storedEUVal / drmMock->storedSSVal, topologyData.maxEuCount); +} + +TEST_F(QueryTopologyTests, givenNonZeroTilesWhenQueryingThenUseOnlyNewIoctl) { + createDrm(2); + + Drm::QueryTopologyData topologyData = {}; + + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + EXPECT_EQ(4u, drmMock->queryComputeSlicesCallCount); // 2x length + 2x query + + EXPECT_EQ(drmMock->queryComputeSlicesSCount, topologyData.sliceCount); + EXPECT_EQ(drmMock->queryComputeSlicesSSCount, topologyData.subSliceCount); + EXPECT_EQ(drmMock->queryComputeSlicesEuCount, topologyData.euCount); + + EXPECT_EQ(drmMock->queryComputeSlicesSCount, topologyData.maxSliceCount); + EXPECT_EQ(drmMock->queryComputeSlicesSSCount / drmMock->queryComputeSlicesSCount, topologyData.maxSubSliceCount); + EXPECT_EQ(drmMock->queryComputeSlicesEuCount / drmMock->queryComputeSlicesSSCount, topologyData.maxEuCount); +} + +TEST_F(QueryTopologyTests, givenNonZeroTilesWithoutEngineInfoThenFallback) { + createDrm(2); + + drmMock->engineInfo.reset(); + + Drm::QueryTopologyData topologyData = {}; + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + EXPECT_EQ(0u, drmMock->queryComputeSlicesCallCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.sliceCount); + EXPECT_EQ(drmMock->storedSSVal, topologyData.subSliceCount); + EXPECT_EQ(drmMock->storedEUVal, topologyData.euCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.maxSliceCount); + EXPECT_EQ(drmMock->storedSSVal / drmMock->storedSVal, topologyData.maxSubSliceCount); + EXPECT_EQ(drmMock->storedEUVal / drmMock->storedSSVal, topologyData.maxEuCount); +} + +TEST_F(QueryTopologyTests, givenNonZeroTilesWhenFailOnNewQueryThenFallback) { + createDrm(2); + + drmMock->queryComputeSlicesEuCount = 0; + + Drm::QueryTopologyData topologyData = {}; + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + EXPECT_EQ(2u, drmMock->queryComputeSlicesCallCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.sliceCount); + EXPECT_EQ(drmMock->storedSSVal, topologyData.subSliceCount); + EXPECT_EQ(drmMock->storedEUVal, topologyData.euCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.maxSliceCount); + EXPECT_EQ(drmMock->storedSSVal / drmMock->storedSVal, topologyData.maxSubSliceCount); + EXPECT_EQ(drmMock->storedEUVal / drmMock->storedSSVal, topologyData.maxEuCount); +} + +TEST_F(QueryTopologyTests, givenNonZeroTilesWhenIncorrectValuesQueriedThenFallback) { + createDrm(2); + + drmMock->failOnQuery = true; + + Drm::QueryTopologyData topologyData = {}; + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + EXPECT_EQ(1u, drmMock->queryComputeSlicesCallCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.sliceCount); + EXPECT_EQ(drmMock->storedSSVal, topologyData.subSliceCount); + EXPECT_EQ(drmMock->storedEUVal, topologyData.euCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.maxSliceCount); + EXPECT_EQ(drmMock->storedSSVal / drmMock->storedSVal, topologyData.maxSubSliceCount); + EXPECT_EQ(drmMock->storedEUVal / drmMock->storedSSVal, topologyData.maxEuCount); +} + +TEST_F(QueryTopologyTests, givenAsymetricTilesWhenQueryingThenPickSmallerValue) { + createDrm(2); + + drmMock->useSmallerValuesOnSecondCall = true; + + Drm::QueryTopologyData topologyData = {}; + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + EXPECT_EQ(drmMock->queryComputeSlicesSCount / 2, topologyData.sliceCount); + EXPECT_EQ(drmMock->queryComputeSlicesSSCount / 2, topologyData.subSliceCount); + EXPECT_EQ(drmMock->queryComputeSlicesEuCount / 2, topologyData.euCount); + + EXPECT_EQ(drmMock->queryComputeSlicesSCount, topologyData.maxSliceCount); + EXPECT_EQ(drmMock->queryComputeSlicesSSCount / drmMock->queryComputeSlicesSCount, topologyData.maxSubSliceCount); + EXPECT_EQ(drmMock->queryComputeSlicesEuCount / drmMock->queryComputeSlicesSSCount, topologyData.maxEuCount); +} + +TEST_F(QueryTopologyTests, givenAsymetricTilesWhenGettingSliceMappingsThenCorrectMappingsReturnedForBothDeviceIndexes) { + createDrm(2); + + drmMock->useSmallerValuesOnSecondCall = true; + + Drm::QueryTopologyData topologyData = {}; + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + auto device0SliceMapping = drmMock->getSliceMappings(0); + auto device1SliceMapping = drmMock->getSliceMappings(1); + + ASSERT_EQ(static_cast(drmMock->queryComputeSlicesSCount / 2), device0SliceMapping.size()); + for (int i = 0; i < drmMock->queryComputeSlicesSCount / 2; i++) { + EXPECT_EQ(i, device0SliceMapping[i]); + } + + ASSERT_EQ(static_cast(drmMock->queryComputeSlicesSCount), device1SliceMapping.size()); + for (int i = 0; i < drmMock->queryComputeSlicesSCount; i++) { + EXPECT_EQ(i, device1SliceMapping[i]); + } +} + +TEST_F(QueryTopologyTests, givenNonZeroTilesAndFallbackPathWhenGettingSliceMappingsThenMappingStoredForIndexZeroOnly) { + DebugManager.flags.UseNewQueryTopoIoctl.set(false); + createDrm(2); + + Drm::QueryTopologyData topologyData = {}; + + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + EXPECT_EQ(0u, drmMock->queryComputeSlicesCallCount); + + EXPECT_EQ(drmMock->storedSVal, topologyData.sliceCount); + EXPECT_EQ(drmMock->storedSSVal, topologyData.subSliceCount); + EXPECT_EQ(drmMock->storedEUVal, topologyData.euCount); + + auto device0SliceMapping = drmMock->getSliceMappings(0); + auto device1SliceMapping = drmMock->getSliceMappings(1); + + ASSERT_EQ(static_cast(drmMock->storedSVal), device0SliceMapping.size()); + for (int i = 0; i < drmMock->storedSVal; i++) { + EXPECT_EQ(i, device0SliceMapping[i]); + } + + ASSERT_EQ(0u, device1SliceMapping.size()); +} + +TEST_F(QueryTopologyTests, givenDrmWhenGettingTopologyMapThenCorrectMapIsReturned) { + createDrm(2); + Drm::QueryTopologyData topologyData = {}; + drmMock->queryTopology(*rootDeviceEnvironment->getHardwareInfo(), topologyData); + + auto topologyMap = drmMock->getTopologyMap(); + + if (executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo()->gtSystemInfo.MultiTileArchInfo.TileCount > 0) { + EXPECT_EQ(executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo()->gtSystemInfo.MultiTileArchInfo.TileCount, topologyMap.size()); + } else { + EXPECT_EQ(1u, topologyMap.size()); + } + + for (uint32_t i = 0; i < topologyMap.size(); i++) { + EXPECT_EQ(drmMock->queryComputeSlicesSCount, topologyMap.at(i).sliceIndices.size()); + } +} diff --git a/shared/test/unit_test/os_interface/linux/drm_query_topology_upstream_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_query_topology_upstream_tests.cpp new file mode 100644 index 0000000000..84bb7c567d --- /dev/null +++ b/shared/test/unit_test/os_interface/linux/drm_query_topology_upstream_tests.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/helpers/hw_info.h" +#include "shared/source/os_interface/hw_info_config.h" +#include "shared/source/os_interface/os_interface.h" +#include "shared/test/common/helpers/default_hw_info.h" +#include "shared/test/common/libult/linux/drm_mock.h" +#include "shared/test/common/test_macros/test.h" + +#include "gtest/gtest.h" + +TEST(DrmQueryTopologyTest, GivenDrmWhenQueryingTopologyInfoCorrectMaxValuesAreSet) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + + *executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo() = *NEO::defaultHwInfo.get(); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + Drm::QueryTopologyData topologyData = {}; + + EXPECT_TRUE(drm.queryTopology(*executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo(), topologyData)); + + EXPECT_EQ(drm.storedSVal, topologyData.sliceCount); + EXPECT_EQ(drm.storedSSVal, topologyData.subSliceCount); + EXPECT_EQ(drm.storedEUVal, topologyData.euCount); + + EXPECT_EQ(drm.storedSVal, topologyData.maxSliceCount); + EXPECT_EQ(drm.storedSSVal / drm.storedSVal, topologyData.maxSubSliceCount); + EXPECT_EQ(drm.storedEUVal / drm.storedSSVal, topologyData.maxEuCount); +} + +TEST(DrmQueryTopologyTest, givenDrmWhenGettingSliceMappingsThenCorrectMappingReturned) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + + *executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo() = *NEO::defaultHwInfo.get(); + DrmMock drmMock{*executionEnvironment->rootDeviceEnvironments[0]}; + + Drm::QueryTopologyData topologyData = {}; + + EXPECT_TRUE(drmMock.queryTopology(*executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo(), topologyData)); + + auto device0SliceMapping = drmMock.getSliceMappings(0); + auto device1SliceMapping = drmMock.getSliceMappings(1); + + ASSERT_EQ(static_cast(topologyData.maxSliceCount), device0SliceMapping.size()); + EXPECT_EQ(0u, device1SliceMapping.size()); + + for (int i = 0; i < topologyData.maxSliceCount; i++) { + EXPECT_EQ(i, device0SliceMapping[i]); + } +}