feature(sysman): feature: Add VF Engine Utilization API implementation

Related-To: NEO-11202

Signed-off-by: Pratik Bari <pratik.bari@intel.com>
This commit is contained in:
Pratik Bari
2024-12-04 08:11:21 +00:00
committed by Compute-Runtime-Automation
parent 819ffea90f
commit ad881e3f2e
13 changed files with 517 additions and 4 deletions

View File

@@ -8,8 +8,11 @@
#include "level_zero/sysman/source/api/vf_management/linux/sysman_os_vf_imp.h"
#include "shared/source/os_interface/driver_info.h"
#include "shared/source/os_interface/linux/engine_info.h"
#include "shared/source/utilities/directory.h"
#include "level_zero/sysman/source/shared/linux/kmd_interface/sysman_kmd_interface.h"
#include "level_zero/sysman/source/shared/linux/pmu/sysman_pmu_imp.h"
#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h"
#include "level_zero/sysman/source/shared/linux/zes_os_sysman_imp.h"
#include "level_zero/sysman/source/sysman_const.h"
@@ -93,8 +96,118 @@ ze_result_t LinuxVfImp::vfOsGetMemoryUtilization(uint32_t *pCount, zes_vf_util_m
return ZE_RESULT_SUCCESS;
}
void LinuxVfImp::vfGetInstancesFromEngineInfo(NEO::EngineInfo *engineInfo, std::set<std::pair<zes_engine_group_t, uint32_t>> &engineGroupAndInstance) {
auto engineTileMap = engineInfo->getEngineTileInfo();
for (const auto &engine : engineTileMap) {
auto engineClassToEngineGroupRange = engineClassToEngineGroup.equal_range(static_cast<uint16_t>(engine.second.engineClass));
for (auto l0EngineEntryInMap = engineClassToEngineGroupRange.first; l0EngineEntryInMap != engineClassToEngineGroupRange.second; l0EngineEntryInMap++) {
auto l0EngineType = l0EngineEntryInMap->second;
engineGroupAndInstance.insert({l0EngineType, static_cast<uint32_t>(engine.second.engineInstance)});
}
}
}
ze_result_t LinuxVfImp::vfEngineDataInit() {
const auto pDrm = pLinuxSysmanImp->getDrm();
const auto pPmuInterface = pLinuxSysmanImp->getPmuInterface();
const auto pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface();
auto hwDeviceId = pLinuxSysmanImp->getSysmanHwDeviceIdInstance();
if (hwDeviceId.getFileDescriptor() < 0) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Could not get Device Id Fd and returning error:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
if (pDrm->sysmanQueryEngineInfo() == false) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s():sysmanQueryEngineInfo is returning false and returning error:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
const auto engineInfo = pDrm->getEngineInfo();
vfGetInstancesFromEngineInfo(engineInfo, engineGroupAndInstance);
for (const auto &engine : engineGroupAndInstance) {
auto engineClass = engineGroupToEngineClass.find(engine.first);
std::pair<uint64_t, uint64_t> configPair{UINT64_MAX, UINT64_MAX};
auto result = pSysmanKmdInterface->getBusyAndTotalTicksConfigs(vfId, engine.second, engineClass->second, configPair);
if (result != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get the busy config and total ticks config and returning error:0x%x \n", __FUNCTION__, result);
cleanup();
return result;
}
uint64_t busyTicksConfig = configPair.first;
int64_t busyTicksFd = pPmuInterface->pmuInterfaceOpen(busyTicksConfig, -1, PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP);
if (busyTicksFd < 0) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Could not open Busy Ticks Handle and returning error:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
cleanup();
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
uint64_t totalTicksConfig = configPair.second;
int64_t totalTicksFd = pPmuInterface->pmuInterfaceOpen(totalTicksConfig, static_cast<int32_t>(busyTicksFd), PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP);
if (totalTicksFd < 0) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Could not open Total Ticks Handle and returning error:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
close(static_cast<int>(busyTicksFd));
cleanup();
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
EngineUtilsData pEngineUtilsData;
pEngineUtilsData.engineType = engine.first;
pEngineUtilsData.busyTicksFd = busyTicksFd;
pEngineUtilsData.totalTicksFd = totalTicksFd;
pEngineUtils.push_back(pEngineUtilsData);
}
return ZE_RESULT_SUCCESS;
}
ze_result_t LinuxVfImp::vfOsGetEngineUtilization(uint32_t *pCount, zes_vf_util_engine_exp2_t *pEngineUtil) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
const auto pSysmanKmdInterface = pLinuxSysmanImp->getSysmanKmdInterface();
if (!pSysmanKmdInterface->isVfEngineUtilizationSupported()) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
std::call_once(initEngineDataOnce, [this]() {
this->vfEngineDataInit();
});
uint32_t engineCount = static_cast<uint32_t>(pEngineUtils.size());
if (engineCount == 0) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): The Total Engine Count Is Zero and hence returning error:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
if (*pCount == 0) {
*pCount = engineCount;
return ZE_RESULT_SUCCESS;
}
if (*pCount > engineCount) {
*pCount = engineCount;
}
if (pEngineUtil != nullptr) {
const auto pPmuInterface = pLinuxSysmanImp->getPmuInterface();
uint32_t index = 0;
for (const auto &pEngineUtilsData : pEngineUtils) {
uint64_t pmuData[4] = {};
auto ret = pPmuInterface->pmuRead(static_cast<int>(pEngineUtilsData.busyTicksFd), pmuData, sizeof(pmuData));
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_UNKNOWN);
return ZE_RESULT_ERROR_UNKNOWN;
}
pEngineUtil[index].vfEngineType = pEngineUtilsData.engineType;
pEngineUtil[index].activeCounterValue = pmuData[2];
pEngineUtil[index].samplingCounterValue = pmuData[3];
index++;
}
}
return ZE_RESULT_SUCCESS;
}
bool LinuxVfImp::vfOsGetLocalMemoryUsed(uint64_t &lMemUsed) {
@@ -138,6 +251,20 @@ LinuxVfImp::LinuxVfImp(
this->vfId = vfId;
}
void LinuxVfImp::cleanup() {
for (const auto &pEngineUtilsData : pEngineUtils) {
DEBUG_BREAK_IF(pEngineUtilsData.busyTicksFd < 0);
close(static_cast<int>(pEngineUtilsData.busyTicksFd));
DEBUG_BREAK_IF(pEngineUtilsData.totalTicksFd < 0);
close(static_cast<int>(pEngineUtilsData.totalTicksFd));
}
pEngineUtils.clear();
}
LinuxVfImp::~LinuxVfImp() {
cleanup();
}
std::unique_ptr<OsVf> OsVf::create(
OsSysman *pOsSysman, uint32_t vfId) {
std::unique_ptr<LinuxVfImp> pLinuxVfImp = std::make_unique<LinuxVfImp>(pOsSysman, vfId);

View File

@@ -13,6 +13,7 @@
#include "level_zero/sysman/source/api/vf_management/sysman_vf_imp.h"
#include "level_zero/sysman/source/shared/linux/zes_os_sysman_imp.h"
#include <set>
#include <string>
namespace L0 {
@@ -21,9 +22,14 @@ class SysFsAccessInterface;
class LinuxVfImp : public OsVf, NEO::NonCopyableOrMovableClass {
public:
LinuxVfImp() = default;
struct EngineUtilsData {
zes_engine_group_t engineType{};
int64_t busyTicksFd = -1;
int64_t totalTicksFd = -1;
};
LinuxVfImp(OsSysman *pOsSysman, uint32_t vfId);
~LinuxVfImp() override = default;
~LinuxVfImp() override;
ze_result_t vfOsGetCapabilities(zes_vf_exp_capabilities_t *pCapability) override;
ze_result_t vfOsGetMemoryUtilization(uint32_t *pCount, zes_vf_util_mem_exp2_t *pMemUtil) override;
@@ -32,11 +38,19 @@ class LinuxVfImp : public OsVf, NEO::NonCopyableOrMovableClass {
bool vfOsGetLocalMemoryUsed(uint64_t &lMemUsed) override;
protected:
ze_result_t vfEngineDataInit();
ze_result_t getVfBDFAddress(uint32_t vfIdMinusOne, zes_pci_address_t *address);
void vfGetInstancesFromEngineInfo(NEO::EngineInfo *engineInfo, std::set<std::pair<zes_engine_group_t, uint32_t>> &engineGroupAndInstance);
void cleanup();
LinuxSysmanImp *pLinuxSysmanImp = nullptr;
SysFsAccessInterface *pSysfsAccess = nullptr;
uint32_t vfId = 0;
static const uint32_t maxMemoryTypes = 1; // Since only the Device Memory Utilization is Supported and not for the Host Memory, this value is 1
private:
std::set<std::pair<zes_engine_group_t, uint32_t>> engineGroupAndInstance = {};
std::vector<EngineUtilsData> pEngineUtils = {};
std::once_flag initEngineDataOnce;
};
} // namespace Sysman

View File

@@ -147,6 +147,8 @@ class SysmanKmdInterface {
virtual bool isSettingTimeoutModeSupported() const = 0;
virtual bool isSettingExclusiveModeSupported() const = 0;
virtual void getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) = 0;
virtual bool isVfEngineUtilizationSupported() const = 0;
virtual ze_result_t getBusyAndTotalTicksConfigs(uint64_t fnNumber, uint64_t engineInstance, uint64_t engineClass, std::pair<uint64_t, uint64_t> &configPair) = 0;
protected:
std::unique_ptr<FsAccessInterface> pFsAccess;
@@ -199,6 +201,8 @@ class SysmanKmdInterfaceI915Upstream : public SysmanKmdInterface, SysmanKmdInter
bool isSettingTimeoutModeSupported() const override { return true; }
bool isSettingExclusiveModeSupported() const override { return true; }
void getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) override;
bool isVfEngineUtilizationSupported() const override { return false; }
ze_result_t getBusyAndTotalTicksConfigs(uint64_t fnNumber, uint64_t engineInstance, uint64_t engineClass, std::pair<uint64_t, uint64_t> &configPair) override;
protected:
std::map<SysfsName, valuePair> sysfsNameToFileMap;
@@ -242,6 +246,8 @@ class SysmanKmdInterfaceI915Prelim : public SysmanKmdInterface, SysmanKmdInterfa
bool isSettingTimeoutModeSupported() const override { return true; }
bool isSettingExclusiveModeSupported() const override { return true; }
void getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) override;
bool isVfEngineUtilizationSupported() const override { return true; }
ze_result_t getBusyAndTotalTicksConfigs(uint64_t fnNumber, uint64_t engineInstance, uint64_t engineClass, std::pair<uint64_t, uint64_t> &configPair) override;
protected:
std::map<SysfsName, valuePair> sysfsNameToFileMap;
@@ -287,6 +293,8 @@ class SysmanKmdInterfaceXe : public SysmanKmdInterface {
bool isSettingTimeoutModeSupported() const override { return false; }
bool isSettingExclusiveModeSupported() const override { return false; }
void getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) override;
bool isVfEngineUtilizationSupported() const override { return false; }
ze_result_t getBusyAndTotalTicksConfigs(uint64_t fnNumber, uint64_t engineInstance, uint64_t engineClass, std::pair<uint64_t, uint64_t> &configPair) override;
protected:
std::map<SysfsName, valuePair> sysfsNameToFileMap;

View File

@@ -173,5 +173,12 @@ void SysmanKmdInterfaceI915Prelim::getDriverVersion(char (&driverVersion)[ZES_ST
return;
}
ze_result_t SysmanKmdInterfaceI915Prelim::getBusyAndTotalTicksConfigs(uint64_t fnNumber, uint64_t engineInstance, uint64_t engineClass, std::pair<uint64_t, uint64_t> &configPair) {
configPair.first = ___PRELIM_I915_PMU_FN_EVENT(PRELIM_I915_PMU_ENGINE_BUSY_TICKS(engineClass, engineInstance), fnNumber);
configPair.second = ___PRELIM_I915_PMU_FN_EVENT(PRELIM_I915_PMU_ENGINE_TOTAL_TICKS(engineClass, engineInstance), fnNumber);
return ZE_RESULT_SUCCESS;
}
} // namespace Sysman
} // namespace L0

View File

@@ -140,5 +140,9 @@ void SysmanKmdInterfaceI915Upstream::getDriverVersion(char (&driverVersion)[ZES_
return;
}
ze_result_t SysmanKmdInterfaceI915Upstream::getBusyAndTotalTicksConfigs(uint64_t fnNumber, uint64_t engineInstance, uint64_t engineClass, std::pair<uint64_t, uint64_t> &configPair) {
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
}
} // namespace Sysman
} // namespace L0

View File

@@ -146,5 +146,9 @@ void SysmanKmdInterfaceXe::getDriverVersion(char (&driverVersion)[ZES_STRING_PRO
return;
}
ze_result_t SysmanKmdInterfaceXe::getBusyAndTotalTicksConfigs(uint64_t fnNumber, uint64_t engineInstance, uint64_t engineClass, std::pair<uint64_t, uint64_t> &configPair) {
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
}
} // namespace Sysman
} // namespace L0

View File

@@ -231,6 +231,11 @@ TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceWhenCheckingWhether
EXPECT_FALSE(pSysmanKmdInterface->clientInfoAvailableInFdInfo());
}
TEST_F(SysmanFixtureDeviceI915Prelim, GivenSysmanKmdInterfaceInstanceWhenCheckingSupportForVfEngineUtilizationThenTrueValueIsReturned) {
auto pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get();
EXPECT_TRUE(pSysmanKmdInterface->isVfEngineUtilizationSupported());
}
} // namespace ult
} // namespace Sysman
} // namespace L0

View File

@@ -237,6 +237,17 @@ TEST_F(SysmanFixtureDeviceI915Upstream, GivenSysmanKmdInterfaceWhenCheckingWheth
EXPECT_FALSE(pSysmanKmdInterface->clientInfoAvailableInFdInfo());
}
TEST_F(SysmanFixtureDeviceI915Upstream, GivenSysmanKmdInterfaceInstanceWhenCheckingSupportForVfEngineUtilizationThenFalseValueIsReturned) {
auto pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get();
EXPECT_FALSE(pSysmanKmdInterface->isVfEngineUtilizationSupported());
}
TEST_F(SysmanFixtureDeviceI915Upstream, GivenSysmanKmdInterfaceInstanceWhenGettingBusyAndTotalTicksConfigsThenErrorIsReturned) {
auto pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get();
std::pair<uint64_t, uint64_t> configPair;
EXPECT_EQ(pSysmanKmdInterface->getBusyAndTotalTicksConfigs(0, 0, 1, configPair), ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE);
}
} // namespace ult
} // namespace Sysman
} // namespace L0

View File

@@ -188,6 +188,17 @@ TEST_F(SysmanFixtureDeviceXe, GivenSingleEngineTypeAndSysmanKmdInterfaceInstance
EXPECT_LT(pSysmanKmdInterface->getEngineActivityFd(ZES_ENGINE_GROUP_COMPUTE_SINGLE, 0, 0, pPmuInterface.get()), 0);
}
TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceInstanceWhenCheckingSupportForVfEngineUtilizationThenFalseValueIsReturned) {
auto pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get();
EXPECT_FALSE(pSysmanKmdInterface->isVfEngineUtilizationSupported());
}
TEST_F(SysmanFixtureDeviceXe, GivenSysmanKmdInterfaceInstanceWhenGettingBusyAndTotalTicksConfigsThenErrorIsReturned) {
auto pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get();
std::pair<uint64_t, uint64_t> configPair;
EXPECT_EQ(pSysmanKmdInterface->getBusyAndTotalTicksConfigs(0, 0, 1, configPair), ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE);
}
} // namespace ult
} // namespace Sysman
} // namespace L0

View File

@@ -10,6 +10,7 @@ set(L0_TESTS_SYSMAN_VF_MANAGEMENT_LINUX
list(APPEND L0_TESTS_SYSMAN_VF_MANAGEMENT_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_sysman_vf_management.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_sysman_vf_management_prelim.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_sysfs_vf_management.h
)

View File

@@ -7,9 +7,13 @@
#pragma once
#include "shared/test/common/test_macros/mock_method_macros.h"
#include "shared/source/os_interface/linux/engine_info.h"
#include "shared/source/os_interface/linux/i915_prelim.h"
#include "level_zero/sysman/source/api/vf_management/linux/sysman_os_vf_imp.h"
#include "level_zero/sysman/source/shared/linux/pmu/sysman_pmu_imp.h"
#include "level_zero/sysman/source/shared/linux/sysman_fs_access_interface.h"
#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_hw_device_id.h"
namespace L0 {
namespace Sysman {
@@ -22,9 +26,93 @@ const std::string pathForVfBdf = "device/virtfn0";
const std::string mockBdfdata = "pci0000:4a/0000:4a:02.0/0000:4b:00.0/0000:4c:01.0/0000:4d:00.1";
const std::string mockInvalidBdfdata = "pci0000:4a";
const std::string mockPathWithInvalidTokens = "pci0000:4a/0000:4a";
const int64_t mockPmuFd = 10;
const uint64_t mockActiveTime = 987654321;
const uint64_t mockTimestamp = 87654321;
const uint64_t mockLmemUsed = 65536;
const uint64_t mockLmemQuota = 128000;
const uint32_t mockNumberOfVfs = 1;
const uint32_t numberMockedEngines = 2;
struct MockVfPmuInterfaceImp : public L0::Sysman::PmuInterfaceImp {
using PmuInterfaceImp::perfEventOpen;
using PmuInterfaceImp::pSysmanKmdInterface;
MockVfPmuInterfaceImp(LinuxSysmanImp *pLinuxSysmanImp) : PmuInterfaceImp(pLinuxSysmanImp) {}
~MockVfPmuInterfaceImp() override = default;
bool mockPmuReadFail = false;
bool mockPerfEventOpenReadFail = false;
int32_t mockErrorNumber = -ENOSPC;
int32_t mockPerfEventOpenFailAtCount = 1;
int64_t perfEventOpen(perf_event_attr *attr, pid_t pid, int cpu, int groupFd, uint64_t flags) override {
mockPerfEventOpenFailAtCount = std::max<int32_t>(mockPerfEventOpenFailAtCount - 1, 1);
const bool shouldCheckForError = (mockPerfEventOpenFailAtCount == 1);
if (shouldCheckForError && mockPerfEventOpenReadFail == true) {
errno = mockErrorNumber;
return -1;
}
return mockPmuFd;
}
int pmuRead(int fd, uint64_t *data, ssize_t sizeOfdata) override {
if (mockPmuReadFail == true) {
return -1;
}
data[0] = mockActiveTime;
data[1] = mockTimestamp;
data[2] = mockActiveTime;
data[3] = mockTimestamp;
return 0;
}
};
struct MockEngineSysmanHwDeviceIdDrm : public MockSysmanHwDeviceIdDrm {
using L0::Sysman::ult::MockSysmanHwDeviceIdDrm::MockSysmanHwDeviceIdDrm;
int returnOpenFileDescriptor = -1;
int returnCloseFileDescriptor = 0;
int openFileDescriptor() override {
return returnOpenFileDescriptor;
}
int closeFileDescriptor() override {
return returnCloseFileDescriptor;
}
};
struct MockVfNeoDrm : public Drm {
using Drm::engineInfo;
using Drm::setupIoctlHelper;
const int mockFd = 0;
MockVfNeoDrm(RootDeviceEnvironment &rootDeviceEnvironment) : Drm(std::make_unique<MockSysmanHwDeviceIdDrm>(mockFd, ""), rootDeviceEnvironment) {}
MockVfNeoDrm(RootDeviceEnvironment &rootDeviceEnvironment, int mockFileDescriptor) : Drm(std::make_unique<MockEngineSysmanHwDeviceIdDrm>(mockFileDescriptor, ""), rootDeviceEnvironment) {}
~MockVfNeoDrm() override = default;
bool mockReadSysmanQueryEngineInfo = true;
bool sysmanQueryEngineInfo() override {
if (mockReadSysmanQueryEngineInfo == false) {
return false;
}
std::vector<NEO::EngineCapabilities> i915QueryEngineInfo(numberMockedEngines);
i915QueryEngineInfo[0].engine.engineClass = prelim_drm_i915_gem_engine_class::PRELIM_I915_ENGINE_CLASS_COMPUTE;
i915QueryEngineInfo[0].engine.engineInstance = 0;
i915QueryEngineInfo[1].engine.engineClass = drm_i915_gem_engine_class::I915_ENGINE_CLASS_COPY;
i915QueryEngineInfo[1].engine.engineInstance = 0;
StackVec<std::vector<NEO::EngineCapabilities>, 2> engineInfos{i915QueryEngineInfo};
this->engineInfo.reset(new EngineInfo(this, engineInfos));
return true;
}
};
struct MockVfSysfsAccessInterface : public L0::Sysman::SysFsAccessInterface {
ze_result_t mockError = ZE_RESULT_SUCCESS;
@@ -98,10 +186,29 @@ struct MockVfSysfsAccessInterface : public L0::Sysman::SysFsAccessInterface {
~MockVfSysfsAccessInterface() override = default;
};
struct MockVfFsAccessInterface : public L0::Sysman::FsAccessInterface {
bool mockReadFail = false;
ze_result_t read(const std::string file, uint32_t &val) override {
if (mockReadFail == true) {
val = 0;
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
val = 23;
return ZE_RESULT_SUCCESS;
}
MockVfFsAccessInterface() = default;
~MockVfFsAccessInterface() override = default;
};
class PublicLinuxVfImp : public L0::Sysman::LinuxVfImp {
public:
PublicLinuxVfImp(L0::Sysman::OsSysman *pOsSysman, uint32_t vfId) : L0::Sysman::LinuxVfImp(pOsSysman, vfId) {}
using L0::Sysman::LinuxVfImp::pSysfsAccess;
using L0::Sysman::LinuxVfImp::vfEngineDataInit;
};
} // namespace ult

View File

@@ -6,6 +6,7 @@
*/
#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h"
#include "level_zero/sysman/test/unit_tests/sources/shared/linux/kmd_interface/mock_sysman_kmd_interface_i915.h"
#include "level_zero/sysman/test/unit_tests/sources/vf_management/linux/mock_sysfs_vf_management.h"
namespace L0 {
@@ -234,6 +235,17 @@ TEST_F(ZesVfFixture, GivenValidVfHandleWhenQueryingMemoryUtilizationAndAndZeroLo
EXPECT_EQ(pVfImp->vfOsGetMemoryUtilization(&mockCount, memUtils.data()), ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
}
TEST_F(ZesVfFixture, GivenValidVfHandleWhenBusyAndTotalTicksConfigNotAvailableAndCallingVfEngineDataInitThenErrorIsReturned) {
auto pDrm = new MockVfNeoDrm(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()));
pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterface->setDriverModel(std::unique_ptr<MockVfNeoDrm>(pDrm));
auto pVfImp = std::make_unique<PublicLinuxVfImp>(pOsSysman, 1);
EXPECT_EQ(pVfImp->vfEngineDataInit(), ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE);
}
} // namespace ult
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,202 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h"
#include "level_zero/sysman/test/unit_tests/sources/shared/linux/kmd_interface/mock_sysman_kmd_interface_i915.h"
#include "level_zero/sysman/test/unit_tests/sources/vf_management/linux/mock_sysfs_vf_management.h"
namespace L0 {
namespace Sysman {
namespace ult {
constexpr uint32_t mockHandleCount = 1u;
class ZesVfFixturePrelim : public SysmanDeviceFixture {
protected:
L0::Sysman::SysmanDevice *device = nullptr;
MockVfSysfsAccessInterface *pSysfsAccess = nullptr;
MockVfFsAccessInterface *pFsAccess = nullptr;
std::unique_ptr<MockVfPmuInterfaceImp> pPmuInterface;
PmuInterface *pOriginalPmuInterface = nullptr;
MockVfNeoDrm *pDrm = nullptr;
MockSysmanKmdInterfacePrelim *pSysmanKmdInterface = nullptr;
void SetUp() override {
SysmanDeviceFixture::SetUp();
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
std::string str = "../../devices/pci0000:37/0000:37:01.0/0000:38:00.0/0000:39:01.0/0000:3a:00.0/drm/renderD128";
std::memcpy(buf, str.c_str(), str.size());
return static_cast<int>(str.size());
});
pFsAccess = new MockVfFsAccessInterface();
pSysfsAccess = new MockVfSysfsAccessInterface();
pSysmanKmdInterface = new MockSysmanKmdInterfacePrelim(pLinuxSysmanImp->getSysmanProductHelper());
pSysmanKmdInterface->pFsAccess.reset(pFsAccess);
pSysmanKmdInterface->pSysfsAccess.reset(pSysfsAccess);
pLinuxSysmanImp->pSysmanKmdInterface.reset(pSysmanKmdInterface);
pLinuxSysmanImp->pFsAccess = pLinuxSysmanImp->getSysmanKmdInterface()->getFsAccess();
pLinuxSysmanImp->pSysfsAccess = pLinuxSysmanImp->getSysmanKmdInterface()->getSysFsAccess();
pDrm = new MockVfNeoDrm(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()));
pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterface->setDriverModel(std::unique_ptr<MockVfNeoDrm>(pDrm));
pSysmanDeviceImp->pVfManagementHandleContext->handleList.clear();
pPmuInterface = std::make_unique<MockVfPmuInterfaceImp>(pLinuxSysmanImp);
pOriginalPmuInterface = pLinuxSysmanImp->pPmuInterface;
pPmuInterface->pSysmanKmdInterface = pLinuxSysmanImp->pSysmanKmdInterface.get();
pLinuxSysmanImp->pPmuInterface = pPmuInterface.get();
pSysmanDeviceImp->getRootDeviceEnvironment().getMutableHardwareInfo()->capabilityTable.isIntegratedDevice = true;
device = pSysmanDevice;
}
void TearDown() override {
pLinuxSysmanImp->pPmuInterface = pOriginalPmuInterface;
SysmanDeviceFixture::TearDown();
}
std::vector<zes_vf_handle_t> getEnabledVfHandles(uint32_t count) {
std::vector<zes_vf_handle_t> handles(count, nullptr);
EXPECT_EQ(zesDeviceEnumEnabledVFExp(device, &count, handles.data()), ZE_RESULT_SUCCESS);
return handles;
}
};
TEST_F(ZesVfFixturePrelim, GivenValidDeviceHandleWhenQueryingEnabledVfHandlesThenCorrectVfHandlesAreReturned) {
auto handles = getEnabledVfHandles(mockHandleCount);
for (auto handleVf : handles) {
ASSERT_NE(nullptr, handleVf);
}
}
TEST_F(ZesVfFixturePrelim, GivenValidVfHandleWhenCallingZesVFManagementGetVFEngineUtilizationExp2AndOpenCallFailsThenErrorIsReturned) {
MockVfNeoDrm *pDrm = nullptr;
int mockFd = -1;
pDrm = new MockVfNeoDrm(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()), mockFd);
pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterface->setDriverModel(std::unique_ptr<MockVfNeoDrm>(pDrm));
auto handles = getEnabledVfHandles(mockHandleCount);
for (auto handleVf : handles) {
ASSERT_NE(nullptr, handleVf);
uint32_t count = 0;
auto result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
}
}
TEST_F(ZesVfFixturePrelim, GivenValidVfHandleWhenCallingZesVFManagementGetVFEngineUtilizationExp2AndSysmanQueryEngineInfoFailsThenErrorIsReturned) {
pDrm->mockReadSysmanQueryEngineInfo = false;
auto handles = getEnabledVfHandles(mockHandleCount);
for (auto handleVf : handles) {
ASSERT_NE(nullptr, handleVf);
uint32_t count = 0;
auto result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
}
}
TEST_F(ZesVfFixturePrelim, GivenValidVfHandleWhenCallingZesVFManagementGetVFEngineUtilizationExp2WithEngineStatsCountThenCorrectEngineStatsCountIsReturned) {
auto handles = getEnabledVfHandles(mockHandleCount);
for (auto handleVf : handles) {
ASSERT_NE(nullptr, handleVf);
uint32_t count = 0;
auto result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
EXPECT_EQ(count, numberMockedEngines);
count = count + 5;
result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
EXPECT_EQ(count, numberMockedEngines);
}
}
TEST_F(ZesVfFixturePrelim, GivenValidVfHandleWhenQueryingEngineUtilizationMultipleTimesThenCorrectEngineStatsAreReturned) {
auto handles = getEnabledVfHandles(mockHandleCount);
for (auto handleVf : handles) {
ASSERT_NE(nullptr, handleVf);
uint32_t count = 0;
auto result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
std::vector<zes_vf_util_engine_exp2_t> engineUtils(count);
result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, engineUtils.data());
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
EXPECT_EQ(engineUtils[0].vfEngineType, ZES_ENGINE_GROUP_COMPUTE_SINGLE);
EXPECT_EQ(engineUtils[0].activeCounterValue, mockActiveTime);
EXPECT_EQ(engineUtils[0].samplingCounterValue, mockTimestamp);
EXPECT_EQ(engineUtils[1].vfEngineType, ZES_ENGINE_GROUP_COPY_SINGLE);
EXPECT_EQ(engineUtils[1].activeCounterValue, mockActiveTime);
EXPECT_EQ(engineUtils[1].samplingCounterValue, mockTimestamp);
engineUtils.clear();
engineUtils.resize(count);
result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, engineUtils.data());
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
EXPECT_EQ(engineUtils[0].vfEngineType, ZES_ENGINE_GROUP_COMPUTE_SINGLE);
EXPECT_EQ(engineUtils[0].activeCounterValue, mockActiveTime);
EXPECT_EQ(engineUtils[0].samplingCounterValue, mockTimestamp);
EXPECT_EQ(engineUtils[1].vfEngineType, ZES_ENGINE_GROUP_COPY_SINGLE);
EXPECT_EQ(engineUtils[1].activeCounterValue, mockActiveTime);
EXPECT_EQ(engineUtils[1].samplingCounterValue, mockTimestamp);
}
}
TEST_F(ZesVfFixturePrelim, GivenValidVfHandleWhenPmuInterfaceOpenFailsForBusyTicksConfigThenErrorIsReturned) {
pFsAccess->mockReadFail = true;
auto handles = getEnabledVfHandles(mockHandleCount);
for (auto handleVf : handles) {
ASSERT_NE(nullptr, handleVf);
uint32_t count = 0;
auto result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
}
}
TEST_F(ZesVfFixturePrelim, GivenValidVfHandleWhenPmuInterfaceOpenFailsForTotalTicksConfigThenErrorIsReturned) {
pPmuInterface->mockPerfEventOpenFailAtCount = 3;
pPmuInterface->mockPerfEventOpenReadFail = true;
auto handles = getEnabledVfHandles(mockHandleCount);
for (auto handleVf : handles) {
ASSERT_NE(nullptr, handleVf);
uint32_t count = 0;
auto result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
}
}
TEST_F(ZesVfFixturePrelim, GivenValidVfHandleWhenPmuReadFailsThenErrorIsReturned) {
pPmuInterface->mockPmuReadFail = true;
auto handles = getEnabledVfHandles(mockHandleCount);
for (auto handleVf : handles) {
ASSERT_NE(nullptr, handleVf);
uint32_t count = 0;
auto result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, nullptr);
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
std::vector<zes_vf_util_engine_exp2_t> engineUtils(count);
result = zesVFManagementGetVFEngineUtilizationExp2(handleVf, &count, engineUtils.data());
EXPECT_EQ(result, ZE_RESULT_ERROR_UNKNOWN);
}
}
} // namespace ult
} // namespace Sysman
} // namespace L0