feature(sysman): VF telemetry APIs for memory utilization

Related-To: NEO-11337

Signed-off-by: Pratik Bari <pratik.bari@intel.com>
This commit is contained in:
Pratik Bari
2024-11-14 08:16:28 +00:00
committed by Compute-Runtime-Automation
parent 917a4134fd
commit 31ca28d5bf
50 changed files with 2301 additions and 5 deletions

View File

@@ -0,0 +1,17 @@
#
# Copyright (C) 2024 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_vf.h
${CMAKE_CURRENT_SOURCE_DIR}/sysman_vf_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/sysman_vf_imp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/sysman_vf_management.h
${CMAKE_CURRENT_SOURCE_DIR}/sysman_vf_management.cpp
)
add_subdirectories()

View File

@@ -0,0 +1,14 @@
#
# Copyright (C) 2024 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
if(UNIX)
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_vf_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_vf_imp.cpp
)
endif()

View File

@@ -0,0 +1,161 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#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/utilities/directory.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"
namespace L0 {
namespace Sysman {
static const std::string pathForVfTelemetryPrefix = "iov/vf";
ze_result_t LinuxVfImp::getVfBDFAddress(uint32_t vfIdMinusOne, zes_pci_address_t *address) {
std::string pathForVfBdf = "device/virtfn";
std::string vfRealPath = "";
std::string vfPath = pathForVfBdf + std::to_string(vfIdMinusOne);
ze_result_t result = pSysfsAccess->getRealPath(vfPath, vfRealPath);
if (ZE_RESULT_SUCCESS != result) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get the real path and returning error:0x%x \n", __FUNCTION__, result);
return result;
}
std::size_t loc = vfRealPath.find_last_of("/");
if (loc == std::string::npos) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get the last occurence of '/' and returning error:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE);
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
}
std::string vfBdfString = vfRealPath.substr(loc + 1);
constexpr int vfBdfTokensNum = 4;
uint16_t domain = -1;
uint8_t bus = -1, device = -1, function = -1;
if (NEO::parseBdfString(vfBdfString, domain, bus, device, function) != vfBdfTokensNum) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to get the correct token sum and returning error:0x%x \n", __FUNCTION__, ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE);
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
}
address->domain = domain;
address->bus = bus;
address->device = device;
address->function = function;
return ZE_RESULT_SUCCESS;
}
ze_result_t LinuxVfImp::vfOsGetCapabilities(zes_vf_exp_capabilities_t *pCapability) {
ze_result_t result = getVfBDFAddress((vfId - 1), &pCapability->address);
if (result != ZE_RESULT_SUCCESS) {
pCapability->address.domain = 0;
pCapability->address.bus = 0;
pCapability->address.device = 0;
pCapability->address.function = 0;
return result;
}
uint64_t vfLmemQuota = 0;
if (!vfOsGetLocalMemoryQuota(vfLmemQuota)) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
pCapability->vfDeviceMemSize = static_cast<uint32_t>(vfLmemQuota / 1024);
pCapability->vfID = vfId;
return ZE_RESULT_SUCCESS;
}
ze_result_t LinuxVfImp::vfOsGetMemoryUtilization(uint32_t *pCount, zes_vf_util_mem_exp2_t *pMemUtil) {
uint64_t vfLmemUsed = 0;
if (*pCount == 0) {
*pCount = maxMemoryTypes;
return ZE_RESULT_SUCCESS;
}
if (*pCount > maxMemoryTypes) {
*pCount = maxMemoryTypes;
}
if (!vfOsGetLocalMemoryUsed(vfLmemUsed)) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
if (pMemUtil != nullptr) {
for (uint32_t i = 0; i < *pCount; i++) {
pMemUtil[i].vfMemLocation = ZES_MEM_LOC_DEVICE;
pMemUtil[i].vfMemUtilized = vfLmemUsed / 1024;
}
}
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;
}
bool LinuxVfImp::vfOsGetLocalMemoryUsed(uint64_t &lMemUsed) {
std::string pathForLmemUsed = "/telemetry/lmem_alloc_size";
std::string pathForDeviceMemUsed = pathForVfTelemetryPrefix + std::to_string(vfId) + pathForLmemUsed;
auto result = pSysfsAccess->read(pathForDeviceMemUsed.data(), lMemUsed);
if (result != ZE_RESULT_SUCCESS) {
lMemUsed = 0;
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to read Local Memory Used with error 0x%x \n", __FUNCTION__, result);
return false;
}
if (lMemUsed == 0) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): since the Local Memory Used is zero \n", __FUNCTION__);
return false;
}
return true;
}
bool LinuxVfImp::vfOsGetLocalMemoryQuota(uint64_t &lMemQuota) {
std::string pathForLmemQuota = "/gt/lmem_quota";
std::string pathForDeviceMemQuota = pathForVfTelemetryPrefix + std::to_string(vfId) + pathForLmemQuota;
auto result = pSysfsAccess->read(pathForDeviceMemQuota.data(), lMemQuota);
if (result != ZE_RESULT_SUCCESS) {
lMemQuota = 0;
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to read Local Memory Quota with error 0x%x \n", __FUNCTION__, result);
return false;
}
if (lMemQuota == 0) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): since the Local Memory Quota is zero \n", __FUNCTION__);
return false;
}
return true;
}
LinuxVfImp::LinuxVfImp(
OsSysman *pOsSysman, uint32_t vfId) {
pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
this->vfId = vfId;
}
std::unique_ptr<OsVf> OsVf::create(
OsSysman *pOsSysman, uint32_t vfId) {
std::unique_ptr<LinuxVfImp> pLinuxVfImp = std::make_unique<LinuxVfImp>(pOsSysman, vfId);
return pLinuxVfImp;
}
uint32_t OsVf::getNumEnabledVfs(OsSysman *pOsSysman) {
constexpr std::string_view pathForNumberOfVfs = "device/sriov_numvfs";
uint32_t numberOfVfs = 0;
LinuxSysmanImp *pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
SysFsAccessInterface *pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
auto result = pSysfsAccess->read(pathForNumberOfVfs.data(), numberOfVfs);
if (result != ZE_RESULT_SUCCESS) {
numberOfVfs = 0;
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Error@ %s(): Failed to read Number Of Vfs with error 0x%x \n", __FUNCTION__, result);
}
return numberOfVfs;
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/helpers/gfx_core_helper.h"
#include "shared/source/os_interface/linux/drm_neo.h"
#include "shared/source/os_interface/product_helper.h"
#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 <string>
namespace L0 {
namespace Sysman {
class SysFsAccessInterface;
class LinuxVfImp : public OsVf, NEO::NonCopyableOrMovableClass {
public:
LinuxVfImp() = default;
LinuxVfImp(OsSysman *pOsSysman, uint32_t vfId);
~LinuxVfImp() override = default;
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;
ze_result_t vfOsGetEngineUtilization(uint32_t *pCount, zes_vf_util_engine_exp2_t *pEngineUtil) override;
bool vfOsGetLocalMemoryQuota(uint64_t &lMemQuota) override;
bool vfOsGetLocalMemoryUsed(uint64_t &lMemUsed) override;
protected:
ze_result_t getVfBDFAddress(uint32_t vfIdMinusOne, zes_pci_address_t *address);
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
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <level_zero/zes_api.h>
#include <memory>
namespace L0 {
namespace Sysman {
struct OsSysman;
class OsVf {
public:
virtual ze_result_t vfOsGetCapabilities(zes_vf_exp_capabilities_t *pCapability) = 0;
virtual ze_result_t vfOsGetMemoryUtilization(uint32_t *pCount, zes_vf_util_mem_exp2_t *pMemUtil) = 0;
virtual ze_result_t vfOsGetEngineUtilization(uint32_t *pCount, zes_vf_util_engine_exp2_t *pEngineUtil) = 0;
virtual bool vfOsGetLocalMemoryQuota(uint64_t &lMemQuota) = 0;
virtual bool vfOsGetLocalMemoryUsed(uint64_t &lMemUsed) = 0;
static std::unique_ptr<OsVf> create(OsSysman *pOsSysman, uint32_t vfId);
static uint32_t getNumEnabledVfs(OsSysman *pOsSysman);
virtual ~OsVf() = default;
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/api/vf_management/sysman_vf_imp.h"
#include "shared/source/helpers/debug_helpers.h"
namespace L0 {
namespace Sysman {
ze_result_t VfImp::vfGetCapabilities(zes_vf_exp_capabilities_t *pCapability) {
*pCapability = capability;
return ZE_RESULT_SUCCESS;
}
ze_result_t VfImp::vfGetMemoryUtilization(uint32_t *pCount, zes_vf_util_mem_exp2_t *pMemUtil) {
return pOsVf->vfOsGetMemoryUtilization(pCount, pMemUtil);
}
ze_result_t VfImp::vfGetEngineUtilization(uint32_t *pCount, zes_vf_util_engine_exp2_t *pEngineUtil) {
return pOsVf->vfOsGetEngineUtilization(pCount, pEngineUtil);
}
void VfImp::init() {
uint64_t lmemUsed = 0;
isVfEnabled = pOsVf->vfOsGetLocalMemoryUsed(lmemUsed);
pOsVf->vfOsGetCapabilities(&capability);
}
VfImp::VfImp(OsSysman *pOsSysman, uint32_t vfId) {
pOsVf = OsVf::create(pOsSysman, vfId);
UNRECOVERABLE_IF(nullptr == pOsVf);
init();
};
VfImp::~VfImp() = default;
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include "level_zero/sysman/source/api/vf_management/sysman_os_vf.h"
#include "level_zero/sysman/source/api/vf_management/sysman_vf_management.h"
#include <level_zero/zes_api.h>
#include <memory>
namespace L0 {
namespace Sysman {
class VfImp : public VfManagement, NEO::NonCopyableOrMovableClass {
public:
void init();
ze_result_t vfGetCapabilities(zes_vf_exp_capabilities_t *pCapability) override;
ze_result_t vfGetMemoryUtilization(uint32_t *pCount, zes_vf_util_mem_exp2_t *pMemUtil) override;
ze_result_t vfGetEngineUtilization(uint32_t *pCount, zes_vf_util_engine_exp2_t *pEngineUtil) override;
VfImp() = default;
VfImp(OsSysman *pOsSysman, uint32_t vfId);
~VfImp() override;
protected:
std::unique_ptr<OsVf> pOsVf;
private:
zes_vf_exp_capabilities_t capability = {};
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,57 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/api/vf_management/sysman_vf_management.h"
#include "level_zero/sysman/source/api/vf_management/sysman_os_vf.h"
#include "level_zero/sysman/source/api/vf_management/sysman_vf_imp.h"
#include "level_zero/sysman/source/device/os_sysman.h"
#include <iostream>
namespace L0 {
namespace Sysman {
VfManagementHandleContext::~VfManagementHandleContext() {
handleList.clear();
}
void VfManagementHandleContext::createHandle(uint32_t vfId) {
std::unique_ptr<VfManagement> pVf = std::make_unique<VfImp>(pOsSysman, vfId);
if (pVf->isVfEnabled == true) {
handleList.push_back(std::move(pVf));
}
}
ze_result_t VfManagementHandleContext::init() {
uint32_t enabledVfNum = OsVf::getNumEnabledVfs(pOsSysman);
for (uint32_t vfIndex = 1; vfIndex <= enabledVfNum; vfIndex++) {
createHandle(vfIndex);
}
return ZE_RESULT_SUCCESS;
}
ze_result_t VfManagementHandleContext::vfManagementGet(uint32_t *pCount, zes_vf_handle_t *phVfManagement) {
std::call_once(initVfManagementOnce, [this]() {
this->init();
});
uint32_t handleListSize = static_cast<uint32_t>(handleList.size());
uint32_t numToCopy = std::min(*pCount, handleListSize);
if (0 == *pCount || *pCount > handleListSize) {
*pCount = handleListSize;
return ZE_RESULT_SUCCESS;
}
if (nullptr != phVfManagement) {
for (uint32_t i = 0; i < numToCopy; i++) {
phVfManagement[i] = handleList[i]->toVfManagementHandle();
}
}
return ZE_RESULT_SUCCESS;
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "level_zero/api/sysman/zes_handles_struct.h"
#include <level_zero/zes_api.h>
#include <memory>
#include <mutex>
#include <vector>
namespace L0 {
namespace Sysman {
struct OsSysman;
class VfManagement : _zes_vf_handle_t {
public:
virtual ze_result_t vfGetCapabilities(zes_vf_exp_capabilities_t *pCapability) = 0;
virtual ze_result_t vfGetMemoryUtilization(uint32_t *pCount, zes_vf_util_mem_exp2_t *pMemUtil) = 0;
virtual ze_result_t vfGetEngineUtilization(uint32_t *pCount, zes_vf_util_engine_exp2_t *pEngineUtil) = 0;
inline zes_vf_handle_t toVfManagementHandle() { return this; }
static VfManagement *fromHandle(zes_vf_handle_t handle) {
return static_cast<VfManagement *>(handle);
}
bool isVfEnabled = false;
};
struct VfManagementHandleContext {
VfManagementHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){};
~VfManagementHandleContext();
ze_result_t init();
ze_result_t vfManagementGet(uint32_t *pCount, zes_vf_handle_t *phVfManagement);
OsSysman *pOsSysman = nullptr;
std::vector<std::unique_ptr<VfManagement>> handleList = {};
private:
void createHandle(uint32_t vfId);
std::once_flag initVfManagementOnce;
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,14 @@
#
# Copyright (C) 2024 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
if(WIN32)
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_vf_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/sysman_os_vf_imp.cpp
)
endif()

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/api/vf_management/windows/sysman_os_vf_imp.h"
#include "level_zero/sysman/source/api/vf_management/sysman_vf_imp.h"
namespace L0 {
namespace Sysman {
uint32_t WddmVfImp::numEnabledVfs = 0;
bool WddmVfImp::localMemoryUsedStatus = false;
ze_result_t WddmVfImp::vfOsGetCapabilities(zes_vf_exp_capabilities_t *pCapability) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmVfImp::vfOsGetMemoryUtilization(uint32_t *pCount, zes_vf_util_mem_exp2_t *pMemUtil) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmVfImp::vfOsGetEngineUtilization(uint32_t *pCount, zes_vf_util_engine_exp2_t *pEngineUtil) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
bool WddmVfImp::vfOsGetLocalMemoryUsed(uint64_t &lMmemUsed) {
return WddmVfImp::localMemoryUsedStatus;
}
bool WddmVfImp::vfOsGetLocalMemoryQuota(uint64_t &lMemQuota) {
return false;
}
std::unique_ptr<OsVf> OsVf::create(
OsSysman *pOsSysman, uint32_t vfId) {
std::unique_ptr<WddmVfImp> pWddmVfImp = std::make_unique<WddmVfImp>();
return pWddmVfImp;
}
uint32_t OsVf::getNumEnabledVfs(OsSysman *pOsSysman) {
return WddmVfImp::numEnabledVfs;
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "level_zero/sysman/source/api/vf_management/sysman_vf_imp.h"
namespace L0 {
namespace Sysman {
class WddmVfImp : public OsVf {
public:
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;
ze_result_t vfOsGetEngineUtilization(uint32_t *pCount, zes_vf_util_engine_exp2_t *pEngineUtil) override;
bool vfOsGetLocalMemoryQuota(uint64_t &lMemQuota) override;
bool vfOsGetLocalMemoryUsed(uint64_t &lMemUsed) override;
static uint32_t numEnabledVfs;
static bool localMemoryUsedStatus;
WddmVfImp() = default;
~WddmVfImp() = default;
};
} // namespace Sysman
} // namespace L0