From 269009c29936beea89952f97684ed3239b39dc57 Mon Sep 17 00:00:00 2001 From: Joshua Santosh Ranjan Date: Mon, 18 Dec 2023 18:43:47 +0000 Subject: [PATCH] feature(sysman): enable guc based engine utilization counters Related-To: NEO-8554 Signed-off-by: Joshua Santosh Ranjan --- .../sysman/engine/linux/os_engine_imp.cpp | 24 +++-- .../sysman/engine/linux/os_engine_imp.h | 16 ++- .../engine/linux/os_engine_imp_prelim.cpp | 102 ++++++++++++++---- .../test/black_box_tests/zello_sysman.cpp | 43 +++++--- .../sysman/engine/linux/mock_engine_prelim.h | 19 +++- .../engine/linux/test_zes_engine_prelim.cpp | 94 +++++++++++++++- 6 files changed, 243 insertions(+), 55 deletions(-) diff --git a/level_zero/tools/source/sysman/engine/linux/os_engine_imp.cpp b/level_zero/tools/source/sysman/engine/linux/os_engine_imp.cpp index caad733eb9..33817d5c8a 100644 --- a/level_zero/tools/source/sysman/engine/linux/os_engine_imp.cpp +++ b/level_zero/tools/source/sysman/engine/linux/os_engine_imp.cpp @@ -51,12 +51,12 @@ ze_result_t OsEngine::getNumEngineTypeAndInstances(std::setpmuRead(static_cast(fd), data, sizeof(data)); + auto ret = pPmuInterface->pmuRead(static_cast(fdList[0].first), data, sizeof(data)); if (ret < 0) { NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():pmuRead is returning value:%d and error:0x%x \n", __FUNCTION__, ret, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; @@ -77,12 +77,24 @@ ze_result_t LinuxEngineImp::getProperties(zes_engine_properties_t &properties) { void LinuxEngineImp::init() { auto i915EngineClass = engineToI915Map.find(engineGroup); // I915_PMU_ENGINE_BUSY macro provides the perf type config which we want to listen to get the engine busyness. - fd = pPmuInterface->pmuInterfaceOpen(I915_PMU_ENGINE_BUSY(i915EngineClass->second, engineInstance), -1, PERF_FORMAT_TOTAL_TIME_ENABLED); + auto fd = pPmuInterface->pmuInterfaceOpen(I915_PMU_ENGINE_BUSY(i915EngineClass->second, engineInstance), -1, PERF_FORMAT_TOTAL_TIME_ENABLED); + if (fd >= 0) { + fdList.push_back(std::make_pair(fd, -1)); + } +} + +LinuxEngineImp::~LinuxEngineImp() { + for (auto &fdPair : fdList) { + if (fdPair.first != -1) { + close(static_cast(fdPair.first)); + } + } + fdList.clear(); } bool LinuxEngineImp::isEngineModuleSupported() { - if (fd < 0) { - NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): as fileDescriptor value = %d Engine Module is not supported \n", __FUNCTION__, fd); + if (fdList.size() == 0) { + NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():No valid Filedescriptors: Engine Module is not supported \n", __FUNCTION__); return false; } return true; diff --git a/level_zero/tools/source/sysman/engine/linux/os_engine_imp.h b/level_zero/tools/source/sysman/engine/linux/os_engine_imp.h index 07822ec6c1..b477a9e610 100644 --- a/level_zero/tools/source/sysman/engine/linux/os_engine_imp.h +++ b/level_zero/tools/source/sysman/engine/linux/os_engine_imp.h @@ -10,6 +10,7 @@ #include "shared/source/os_interface/linux/drm_neo.h" #include "level_zero/tools/source/sysman/engine/os_engine.h" +#include "level_zero/tools/source/sysman/linux/fs_access.h" #include "level_zero/tools/source/sysman/sysman_const.h" #include @@ -20,20 +21,13 @@ struct Device; class LinuxEngineImp : public OsEngine, NEO::NonCopyableOrMovableClass { public: ze_result_t getActivity(zes_engine_stats_t *pStats) override; - ze_result_t getActivityExt(uint32_t *pCount, zes_engine_stats_t *pStats) override { - return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; - } + ze_result_t getActivityExt(uint32_t *pCount, zes_engine_stats_t *pStats) override; ze_result_t getProperties(zes_engine_properties_t &properties) override; bool isEngineModuleSupported() override; static zes_engine_group_t getGroupFromEngineType(zes_engine_group_t type); LinuxEngineImp() = default; LinuxEngineImp(OsSysman *pOsSysman, zes_engine_group_t type, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubDevice); - ~LinuxEngineImp() override { - if (fd != -1) { - close(static_cast(fd)); - fd = -1; - } - } + ~LinuxEngineImp() override; protected: zes_engine_group_t engineGroup = ZES_ENGINE_GROUP_ALL; @@ -43,10 +37,12 @@ class LinuxEngineImp : public OsEngine, NEO::NonCopyableOrMovableClass { Device *pDevice = nullptr; uint32_t subDeviceId = 0; ze_bool_t onSubDevice = false; + uint32_t numberOfVfs = 0; + SysfsAccess *pSysfsAccess = nullptr; private: void init(); - int64_t fd = -1; + std::vector> fdList{}; }; } // namespace L0 diff --git a/level_zero/tools/source/sysman/engine/linux/os_engine_imp_prelim.cpp b/level_zero/tools/source/sysman/engine/linux/os_engine_imp_prelim.cpp index ff3f668651..cee921a703 100644 --- a/level_zero/tools/source/sysman/engine/linux/os_engine_imp_prelim.cpp +++ b/level_zero/tools/source/sysman/engine/linux/os_engine_imp_prelim.cpp @@ -10,11 +10,13 @@ #include "shared/source/os_interface/linux/i915_prelim.h" #include "level_zero/tools/source/sysman/engine/linux/os_engine_imp.h" +#include "level_zero/tools/source/sysman/linux/fs_access.h" #include "level_zero/tools/source/sysman/linux/os_sysman_imp.h" namespace L0 { -using NEO::PrelimI915::I915_SAMPLE_BUSY; +constexpr std::string_view pathForNumberOfVfs = "device/sriov_numvfs"; +using NEO::PrelimI915::drm_i915_pmu_engine_sample::I915_SAMPLE_BUSY; static const std::multimap<__u16, zes_engine_group_t> i915ToEngineMap = { {static_cast<__u16>(drm_i915_gem_engine_class::I915_ENGINE_CLASS_RENDER), ZES_ENGINE_GROUP_RENDER_SINGLE}, @@ -70,20 +72,64 @@ ze_result_t OsEngine::getNumEngineTypeAndInstances(std::setpmuRead(static_cast(fd), data, sizeof(data)); +static ze_result_t readBusynessFromGroupFd(PmuInterface *pPmuInterface, std::pair &fdPair, zes_engine_stats_t *pStats) { + uint64_t data[4] = {}; + auto ret = pPmuInterface->pmuRead(static_cast(fdPair.first), data, sizeof(data)); if (ret < 0) { NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():pmuRead is returning value:%d and error:0x%x \n", __FUNCTION__, ret, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; } - // In data[], First u64 is "active time", And second u64 is "timestamp". Both in nanoseconds - pStats->activeTime = data[0] / microSecondsToNanoSeconds; - pStats->timestamp = data[1] / microSecondsToNanoSeconds; + // In data[], First u64 is "active time", And second u64 is "timestamp". Both in ticks + pStats->activeTime = data[2]; + pStats->timestamp = data[3]; + + return ZE_RESULT_SUCCESS; +} + +ze_result_t LinuxEngineImp::getActivity(zes_engine_stats_t *pStats) { + // read from global busyness fd + return readBusynessFromGroupFd(pPmuInterface, fdList[0], pStats); +} + +LinuxEngineImp::~LinuxEngineImp() { + + for (auto &fdPair : fdList) { + if (fdPair.first != -1) { + close(static_cast(fdPair.first)); + } + if (fdPair.second != -1) { + close(static_cast(fdPair.second)); + } + } + fdList.clear(); +} + +ze_result_t LinuxEngineImp::getActivityExt(uint32_t *pCount, zes_engine_stats_t *pStats) { + + if (numberOfVfs == 0) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + if (*pCount == 0) { + // +1 for PF + *pCount = numberOfVfs + 1; + return ZE_RESULT_SUCCESS; + } + + *pCount = std::min(*pCount, numberOfVfs + 1); + memset(pStats, 0, *pCount * sizeof(zes_engine_stats_t)); + for (uint32_t i = 0; i < *pCount; i++) { + // +1 to consider the global busyness value + const auto fdListIndex = i + 1; + if (fdList[fdListIndex].first >= 0) { + auto status = readBusynessFromGroupFd(pPmuInterface, fdList[fdListIndex], &pStats[i]); + if (status != ZE_RESULT_SUCCESS) { + return status; + } + continue; + } + return ZE_RESULT_ERROR_NOT_AVAILABLE; + } return ZE_RESULT_SUCCESS; } @@ -98,29 +144,44 @@ void LinuxEngineImp::init() { uint64_t config = UINT64_MAX; switch (engineGroup) { case ZES_ENGINE_GROUP_ALL: - config = __PRELIM_I915_PMU_ANY_ENGINE_GROUP_BUSY(subDeviceId); + config = __PRELIM_I915_PMU_ANY_ENGINE_GROUP_BUSY_TICKS(subDeviceId); break; case ZES_ENGINE_GROUP_COMPUTE_ALL: case ZES_ENGINE_GROUP_RENDER_ALL: - config = __PRELIM_I915_PMU_RENDER_GROUP_BUSY(subDeviceId); + config = __PRELIM_I915_PMU_RENDER_GROUP_BUSY_TICKS(subDeviceId); break; case ZES_ENGINE_GROUP_COPY_ALL: - config = __PRELIM_I915_PMU_COPY_GROUP_BUSY(subDeviceId); + config = __PRELIM_I915_PMU_COPY_GROUP_BUSY_TICKS(subDeviceId); break; case ZES_ENGINE_GROUP_MEDIA_ALL: - config = __PRELIM_I915_PMU_MEDIA_GROUP_BUSY(subDeviceId); + config = __PRELIM_I915_PMU_MEDIA_GROUP_BUSY_TICKS(subDeviceId); break; default: auto i915EngineClass = engineToI915Map.find(engineGroup); - config = I915_PMU_ENGINE_BUSY(i915EngineClass->second, engineInstance); + config = PRELIM_I915_PMU_ENGINE_BUSY_TICKS(i915EngineClass->second, engineInstance); break; } - fd = pPmuInterface->pmuInterfaceOpen(config, -1, PERF_FORMAT_TOTAL_TIME_ENABLED); + int64_t fd[2]; + + // Fds for global busyness + fd[0] = pPmuInterface->pmuInterfaceOpen(config, -1, PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP); + fd[1] = pPmuInterface->pmuInterfaceOpen(__PRELIM_I915_PMU_TOTAL_ACTIVE_TICKS(subDeviceId), static_cast(fd[0]), PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP); + fdList.push_back(std::make_pair(fd[0], fd[1])); + + pSysfsAccess->read(pathForNumberOfVfs.data(), numberOfVfs); + // +1 to include PF + for (uint64_t i = 0; i < numberOfVfs + 1; i++) { + uint64_t functionConfig = ___PRELIM_I915_PMU_FN_EVENT(config, i); + + fd[0] = pPmuInterface->pmuInterfaceOpen(functionConfig, -1, PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP); + fd[1] = pPmuInterface->pmuInterfaceOpen(__PRELIM_I915_PMU_TOTAL_ACTIVE_TICKS(subDeviceId), static_cast(fd[0]), PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP); + fdList.push_back(std::make_pair(fd[0], fd[1])); + } } bool LinuxEngineImp::isEngineModuleSupported() { - if (fd < 0) { - NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): as fileDescriptor value = %d Engine Module is not supported \n", __FUNCTION__, fd); + if (fdList[0].second < 0) { + NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): as fileDescriptor value = %d Engine Module is not supported \n", __FUNCTION__, fdList[0].second); return false; } return true; @@ -131,11 +192,12 @@ LinuxEngineImp::LinuxEngineImp(OsSysman *pOsSysman, zes_engine_group_t type, uin pDrm = &pLinuxSysmanImp->getDrm(); pDevice = pLinuxSysmanImp->getDeviceHandle(); pPmuInterface = pLinuxSysmanImp->getPmuInterface(); + pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); init(); } std::unique_ptr OsEngine::create(OsSysman *pOsSysman, zes_engine_group_t type, uint32_t engineInstance, uint32_t subDeviceId, ze_bool_t onSubDevice) { - std::unique_ptr pLinuxEngineImp = std::make_unique(pOsSysman, type, engineInstance, subDeviceId, onSubDevice); + std::unique_ptr pLinuxEngineImp = std::make_unique(pOsSysman, type, engineInstance, subDeviceId, onSubDevice); return pLinuxEngineImp; } diff --git a/level_zero/tools/test/black_box_tests/zello_sysman.cpp b/level_zero/tools/test/black_box_tests/zello_sysman.cpp index 2cd4f167d1..7e146c4ea5 100644 --- a/level_zero/tools/test/black_box_tests/zello_sysman.cpp +++ b/level_zero/tools/test/black_box_tests/zello_sysman.cpp @@ -856,6 +856,16 @@ std::string getEngineType(zes_engine_group_t engineGroup) { void testSysmanEngine(ze_device_handle_t &device) { std::cout << std::endl << " ---- Engine tests ---- " << std::endl; + ze_device_properties_t deviceProperties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; + VALIDATECALL(zeDeviceGetProperties(device, &deviceProperties)); + if (verbose) { + std::cout << "Device UUID: "; + for (uint32_t i = 0; i < ZE_MAX_UUID_SIZE; i++) { + std::cout << static_cast(deviceProperties.uuid.id[i]) << " "; + } + std::cout << std::endl; + } + uint32_t count = 0; VALIDATECALL(zesDeviceEnumEngineGroups(device, &count, nullptr)); if (count == 0) { @@ -864,26 +874,33 @@ void testSysmanEngine(ze_device_handle_t &device) { } std::vector handles(count, nullptr); VALIDATECALL(zesDeviceEnumEngineGroups(device, &count, handles.data())); - for (const auto &handle : handles) { - zes_engine_properties_t engineProperties = {}; - zes_engine_stats_t engineStats = {}; + for (uint32_t i = 0; i < 10; i++) { + std::cout << "[" << i << "]" << std::endl; + for (const auto &handle : handles) { + zes_engine_properties_t engineProperties = {}; + zes_engine_stats_t engineStats = {}; - VALIDATECALL(zesEngineGetProperties(handle, &engineProperties)); + VALIDATECALL(zesEngineGetProperties(handle, &engineProperties)); - if (verbose) { - std::cout << "Engine Type = " << getEngineType(engineProperties.type) << std::endl; - if (engineProperties.onSubdevice) { - std::cout << "Subdevice Id = " << engineProperties.subdeviceId << std::endl; + if (verbose) { + std::cout << "Engine Type = " << getEngineType(engineProperties.type); + if (engineProperties.onSubdevice) { + std::cout << " || Subdevice Id = " << engineProperties.subdeviceId; + } } - } - VALIDATECALL(zesEngineGetActivity(handle, &engineStats)); - if (verbose) { - std::cout << "Active Time = " << engineStats.activeTime << std::endl; - std::cout << "Timestamp = " << engineStats.timestamp << std::endl; + VALIDATECALL(zesEngineGetActivity(handle, &engineStats)); + if (verbose) { + std::cout << " || Active Time = " << engineStats.activeTime; + std::cout << " || Timestamp = " << engineStats.timestamp; + } + std::cout << std::endl; } + std::this_thread::sleep_for(std::chrono::milliseconds(150)); + std::cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" << std::endl; } } + std::string getSchedulerModeName(zes_sched_mode_t mode) { static const std::map mgetSchedulerModeName{ {ZES_SCHED_MODE_TIMEOUT, "ZES_SCHED_MODE_TIMEOUT"}, diff --git a/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/mock_engine_prelim.h b/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/mock_engine_prelim.h index 44925274b7..18f26b8750 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/mock_engine_prelim.h +++ b/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/mock_engine_prelim.h @@ -21,7 +21,6 @@ namespace ult { constexpr int64_t mockPmuFd = 10; constexpr uint64_t mockTimestamp = 87654321; constexpr uint64_t mockActiveTime = 987654321; -const uint32_t microSecondsToNanoSeconds = 1000u; constexpr uint16_t invalidEngineClass = UINT16_MAX; const std::string deviceDir("device"); constexpr uint32_t numberOfMockedEnginesForSingleTileDevice = 7u; @@ -106,10 +105,13 @@ struct MockEnginePmuInterfaceImp : public PmuInterfaceImp { bool mockPmuRead = false; bool mockPerfEventOpenRead = false; + uint32_t mockPerfEventOpenFailAtCount = 1; int64_t perfEventOpen(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) override { - if (mockPerfEventOpenRead == true) { + mockPerfEventOpenFailAtCount = std::max(mockPerfEventOpenFailAtCount - 1, 1u); + const bool shouldCheckForError = (mockPerfEventOpenFailAtCount == 1); + if (shouldCheckForError && mockPerfEventOpenRead == true) { return mockedPerfEventOpenAndFailureReturn(attr, pid, cpu, groupFd, flags); } @@ -122,12 +124,18 @@ struct MockEnginePmuInterfaceImp : public PmuInterfaceImp { int pmuRead(int fd, uint64_t *data, ssize_t sizeOfdata) override { + if (fd < 0) { + return -1; + } + if (mockPmuRead == true) { return mockedPmuReadAndFailureReturn(fd, data, sizeOfdata); } data[0] = mockActiveTime; data[1] = mockTimestamp; + data[2] = mockActiveTime; + data[3] = mockTimestamp; return 0; } @@ -160,6 +168,7 @@ struct MockEngineSysfsAccess : public SysfsAccess { bool mockReadSymLinkFailure = false; bool mockReadSymLinkSuccess = false; + uint32_t mockReadVal = 0; ze_result_t readSymLink(const std::string file, std::string &val) override { @@ -180,6 +189,7 @@ struct MockEngineSysfsAccess : public SysfsAccess { val = "/sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0/0000:02:01.0/0000:03:00.0"; return ZE_RESULT_SUCCESS; } + return ZE_RESULT_ERROR_NOT_AVAILABLE; } @@ -187,6 +197,11 @@ struct MockEngineSysfsAccess : public SysfsAccess { return ZE_RESULT_ERROR_NOT_AVAILABLE; } + ze_result_t read(const std::string file, uint32_t &val) override { + val = mockReadVal; + return ZE_RESULT_SUCCESS; + } + MockEngineSysfsAccess() = default; }; } // namespace ult diff --git a/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/test_zes_engine_prelim.cpp b/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/test_zes_engine_prelim.cpp index bf95b301e6..ccbca84049 100644 --- a/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/test_zes_engine_prelim.cpp +++ b/level_zero/tools/test/unit_tests/sources/sysman/engine/linux/test_zes_engine_prelim.cpp @@ -184,8 +184,8 @@ TEST_F(ZesEngineFixture, GivenValidEngineHandleAndIntegratedDeviceWhenCallingZes for (auto handle : handles) { ASSERT_NE(nullptr, handle); EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivity(handle, &stats)); - EXPECT_EQ(mockActiveTime / microSecondsToNanoSeconds, stats.activeTime); - EXPECT_EQ(mockTimestamp / microSecondsToNanoSeconds, stats.timestamp); + EXPECT_EQ(mockActiveTime, stats.activeTime); + EXPECT_EQ(mockTimestamp, stats.timestamp); } } @@ -200,11 +200,97 @@ TEST_F(ZesEngineFixture, GivenValidEngineHandleAndDiscreteDeviceWhenCallingZesEn for (auto handle : handles) { ASSERT_NE(nullptr, handle); EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivity(handle, &stats)); - EXPECT_EQ(mockActiveTime / microSecondsToNanoSeconds, stats.activeTime); - EXPECT_EQ(mockTimestamp / microSecondsToNanoSeconds, stats.timestamp); + EXPECT_EQ(mockActiveTime, stats.activeTime); + EXPECT_EQ(mockTimestamp, stats.timestamp); } } +TEST_F(ZesEngineFixture, GivenValidEngineHandleAndDiscreteDeviceWhenCallingZesEngineGetActivityExtThenVerifyCallReturnsSuccess) { + auto pMemoryManagerTest = std::make_unique(*neoDevice->getExecutionEnvironment()); + pMemoryManagerTest->localMemorySupported[0] = true; + device->getDriverHandle()->setMemoryManager(pMemoryManagerTest.get()); + pSysfsAccess->mockReadVal = 2; + pSysfsAccess->mockReadSymLinkSuccess = true; + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->pEngineHandleContext->init(deviceHandles); + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + ASSERT_NE(nullptr, handle); + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivityExt(handle, &count, nullptr)); + EXPECT_EQ(count, pSysfsAccess->mockReadVal + 1); + std::vector engineStats(count); + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivityExt(handle, &count, engineStats.data())); + for (auto &stat : engineStats) { + EXPECT_EQ(mockActiveTime, stat.activeTime); + EXPECT_EQ(mockTimestamp, stat.timestamp); + } + } +} + +TEST_F(ZesEngineFixture, GivenDiscreteDeviceWithNoVfsWhenCallingZesEngineGetActivityExtThenReturnFailure) { + auto pMemoryManagerTest = std::make_unique(*neoDevice->getExecutionEnvironment()); + pMemoryManagerTest->localMemorySupported[0] = true; + device->getDriverHandle()->setMemoryManager(pMemoryManagerTest.get()); + pSysfsAccess->mockReadVal = 0; + pSysfsAccess->mockReadSymLinkSuccess = true; + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->pEngineHandleContext->init(deviceHandles); + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + ASSERT_NE(nullptr, handle); + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesEngineGetActivityExt(handle, &count, nullptr)); + } +} + +TEST_F(ZesEngineFixture, GivenDiscreteDeviceWithValidVfsWhenPmuReadingFailsWhenCallingZesEngineGetActivityExtThenReturnFailure) { + auto pMemoryManagerTest = std::make_unique(*neoDevice->getExecutionEnvironment()); + pMemoryManagerTest->localMemorySupported[0] = true; + device->getDriverHandle()->setMemoryManager(pMemoryManagerTest.get()); + pSysfsAccess->mockReadVal = 2; + pSysfsAccess->mockReadSymLinkSuccess = true; + pPmuInterface->mockPmuRead = true; + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->pEngineHandleContext->init(deviceHandles); + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + + for (auto handle : handles) { + ASSERT_NE(nullptr, handle); + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivityExt(handle, &count, nullptr)); + EXPECT_EQ(count, pSysfsAccess->mockReadVal + 1); + std::vector engineStats(count); + EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesEngineGetActivityExt(handle, &count, engineStats.data())); + } +} + +TEST_F(ZesEngineFixture, GivenDiscreteDeviceWithOneInvalidVfWhenCallingZesEngineGetActivityExtThenReturnFailure) { + auto pMemoryManagerTest = std::make_unique(*neoDevice->getExecutionEnvironment()); + pMemoryManagerTest->localMemorySupported[0] = true; + device->getDriverHandle()->setMemoryManager(pMemoryManagerTest.get()); + pSysfsAccess->mockReadVal = 1; + pSysfsAccess->mockReadSymLinkSuccess = true; + pPmuInterface->mockPerfEventOpenRead = true; + pPmuInterface->mockPerfEventOpenFailAtCount = 4; + pSysmanDeviceImp->pEngineHandleContext->handleList.clear(); + pSysmanDeviceImp->pEngineHandleContext->init(deviceHandles); + auto handles = getEngineHandles(handleComponentCount); + EXPECT_EQ(handleComponentCount, handles.size()); + auto handle = handles[0]; + ASSERT_NE(nullptr, handle); + uint32_t count = 0; + EXPECT_EQ(ZE_RESULT_SUCCESS, zesEngineGetActivityExt(handle, &count, nullptr)); + EXPECT_EQ(count, pSysfsAccess->mockReadVal + 1); + std::vector engineStats(count); + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, zesEngineGetActivityExt(handle, &count, engineStats.data())); +} + TEST_F(ZesEngineFixture, GivenTestDiscreteDevicesAndValidEngineHandleWhenCallingZesEngineGetActivityAndPMUGetEventTypeFailsThenVerifyEngineGetActivityReturnsFailure) { auto pMemoryManagerTest = std::make_unique(*neoDevice->getExecutionEnvironment()); pMemoryManagerTest->localMemorySupported[0] = true;