Add support for global_operations in new sysman design

Related-To: LOCI-4135
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2023-03-24 07:32:22 +00:00
committed by Compute-Runtime-Automation
parent 4c7bc2ca98
commit d29ed25f8b
35 changed files with 3241 additions and 23 deletions

View File

@@ -35,3 +35,11 @@ struct _zes_sched_handle_t {
struct _zes_firmware_handle_t {
virtual ~_zes_firmware_handle_t() = default;
};
struct _zes_diag_handle_t {
virtual ~_zes_diag_handle_t() = default;
};
struct _zes_ras_handle_t {
virtual ~_zes_ras_handle_t() = default;
};

View File

@@ -35,13 +35,21 @@ ze_result_t zesDeviceGet(
ze_result_t zesDeviceGetProperties(
zes_device_handle_t hDevice,
zes_device_properties_t *pProperties) {
return L0::SysmanDevice::deviceGetProperties(hDevice, pProperties);
if (L0::sysmanInitFromCore) {
return L0::SysmanDevice::deviceGetProperties(hDevice, pProperties);
} else {
return L0::Sysman::SysmanDevice::deviceGetProperties(hDevice, pProperties);
}
}
ze_result_t zesDeviceGetState(
zes_device_handle_t hDevice,
zes_device_state_t *pState) {
return L0::SysmanDevice::deviceGetState(hDevice, pState);
if (L0::sysmanInitFromCore) {
return L0::SysmanDevice::deviceGetState(hDevice, pState);
} else {
return L0::Sysman::SysmanDevice::deviceGetState(hDevice, pState);
}
}
ze_result_t zesDeviceEnumSchedulers(
@@ -143,13 +151,21 @@ ze_result_t zesDeviceProcessesGetState(
zes_device_handle_t hDevice,
uint32_t *pCount,
zes_process_state_t *pProcesses) {
return L0::SysmanDevice::processesGetState(hDevice, pCount, pProcesses);
if (L0::sysmanInitFromCore) {
return L0::SysmanDevice::processesGetState(hDevice, pCount, pProcesses);
} else {
return L0::Sysman::SysmanDevice::processesGetState(hDevice, pCount, pProcesses);
}
}
ze_result_t zesDeviceReset(
zes_device_handle_t hDevice,
ze_bool_t force) {
return L0::SysmanDevice::deviceReset(hDevice, force);
if (L0::sysmanInitFromCore) {
return L0::SysmanDevice::deviceReset(hDevice, force);
} else {
return L0::Sysman::SysmanDevice::deviceReset(hDevice, force);
}
}
ze_result_t zesDevicePciGetProperties(

View File

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

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/diagnostics/diagnostics.h"
#include "shared/source/helpers/basic_math.h"
namespace L0 {
namespace Sysman {
DiagnosticsHandleContext::~DiagnosticsHandleContext() {
releaseDiagnosticsHandles();
}
void DiagnosticsHandleContext::releaseDiagnosticsHandles() {
for (Diagnostics *pDiagnostics : handleList) {
delete pDiagnostics;
}
handleList.clear();
}
void DiagnosticsHandleContext::init() {
}
ze_result_t DiagnosticsHandleContext::diagnosticsGet(uint32_t *pCount, zes_diag_handle_t *phDiagnostics) {
std::call_once(initDiagnosticsOnce, [this]() {
this->init();
this->diagnosticsInitDone = true;
});
uint32_t handleListSize = static_cast<uint32_t>(handleList.size());
uint32_t numToCopy = std::min(*pCount, handleListSize);
if (0 == *pCount || *pCount > handleListSize) {
*pCount = handleListSize;
}
if (nullptr != phDiagnostics) {
for (uint32_t i = 0; i < numToCopy; i++) {
phDiagnostics[i] = handleList[i]->toHandle();
}
}
return ZE_RESULT_SUCCESS;
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,56 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "level_zero/api/sysman/zes_handles_struct.h"
#include <level_zero/zes_api.h>
#include <mutex>
#include <string>
#include <vector>
namespace L0 {
namespace Sysman {
struct OsSysman;
class Diagnostics : _zes_diag_handle_t {
public:
~Diagnostics() override {}
virtual ze_result_t diagnosticsGetProperties(zes_diag_properties_t *pProperties) = 0;
virtual ze_result_t diagnosticsGetTests(uint32_t *pCount, zes_diag_test_t *pTests) = 0;
virtual ze_result_t diagnosticsRunTests(uint32_t start, uint32_t end, zes_diag_result_t *pResult) = 0;
inline zes_diag_handle_t toHandle() { return this; }
static Diagnostics *fromHandle(zes_diag_handle_t handle) {
return static_cast<Diagnostics *>(handle);
}
};
struct DiagnosticsHandleContext {
DiagnosticsHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){};
void releaseDiagnosticsHandles();
MOCKABLE_VIRTUAL ~DiagnosticsHandleContext();
MOCKABLE_VIRTUAL void init();
ze_result_t diagnosticsGet(uint32_t *pCount, zes_diag_handle_t *phDiagnostics);
std::vector<std::string> supportedDiagTests = {};
OsSysman *pOsSysman = nullptr;
std::vector<Diagnostics *> handleList = {};
bool isDiagnosticsInitDone() {
return diagnosticsInitDone;
}
private:
void createHandle(const std::string &diagTests);
std::once_flag initDiagnosticsOnce;
bool diagnosticsInitDone = false;
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,16 @@
#
# Copyright (C) 2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/global_operations.h
${CMAKE_CURRENT_SOURCE_DIR}/global_operations_imp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/global_operations_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/os_global_operations.h
)
add_subdirectories()

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include <level_zero/zes_api.h>
namespace L0 {
namespace Sysman {
class GlobalOperations {
public:
virtual ~GlobalOperations(){};
virtual ze_result_t reset(ze_bool_t force) = 0;
virtual ze_result_t deviceGetProperties(zes_device_properties_t *pProperties) = 0;
virtual ze_result_t processesGetState(uint32_t *pCount, zes_process_state_t *pProcesses) = 0;
virtual ze_result_t deviceGetState(zes_device_state_t *pState) = 0;
virtual void init() = 0;
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/global_operations/global_operations_imp.h"
#include "shared/source/helpers/debug_helpers.h"
#include "shared/source/helpers/string.h"
#include "level_zero/sysman/source/sysman_const.h"
#include <algorithm>
namespace L0 {
namespace Sysman {
ze_result_t GlobalOperationsImp::processesGetState(uint32_t *pCount, zes_process_state_t *pProcesses) {
initGlobalOperations();
std::vector<zes_process_state_t> pProcessList;
ze_result_t result = pOsGlobalOperations->scanProcessesState(pProcessList);
if (result != ZE_RESULT_SUCCESS) {
return result;
}
if ((*pCount > 0) && (*pCount < pProcessList.size())) {
result = ZE_RESULT_ERROR_INVALID_SIZE;
}
if (pProcesses != nullptr) {
uint32_t limit = std::min(*pCount, static_cast<uint32_t>(pProcessList.size()));
for (uint32_t i = 0; i < limit; i++) {
pProcesses[i].processId = pProcessList[i].processId;
pProcesses[i].engines = pProcessList[i].engines;
pProcesses[i].memSize = pProcessList[i].memSize;
pProcesses[i].sharedSize = pProcessList[i].sharedSize;
}
}
*pCount = static_cast<uint32_t>(pProcessList.size());
return result;
}
ze_result_t GlobalOperationsImp::deviceGetProperties(zes_device_properties_t *pProperties) {
initGlobalOperations();
sysmanProperties.numSubdevices = pOsSysman->getSubDeviceCount();
*pProperties = sysmanProperties;
return ZE_RESULT_SUCCESS;
}
ze_result_t GlobalOperationsImp::reset(ze_bool_t force) {
initGlobalOperations();
return pOsGlobalOperations->reset(force);
}
ze_result_t GlobalOperationsImp::deviceGetState(zes_device_state_t *pState) {
initGlobalOperations();
return pOsGlobalOperations->deviceGetState(pState);
}
void GlobalOperationsImp::init() {
if (pOsGlobalOperations == nullptr) {
pOsGlobalOperations = OsGlobalOperations::create(pOsSysman);
}
UNRECOVERABLE_IF(nullptr == pOsGlobalOperations);
pOsGlobalOperations->getVendorName(sysmanProperties.vendorName);
pOsGlobalOperations->getDriverVersion(sysmanProperties.driverVersion);
pOsGlobalOperations->getModelName(sysmanProperties.modelName);
pOsGlobalOperations->getBrandName(sysmanProperties.brandName);
memset(sysmanProperties.boardNumber, 0, ZES_STRING_PROPERTY_SIZE);
if (!pOsGlobalOperations->getBoardNumber(sysmanProperties.boardNumber)) {
memcpy_s(sysmanProperties.boardNumber, ZES_STRING_PROPERTY_SIZE, unknown.c_str(), unknown.length() + 1);
}
memset(sysmanProperties.serialNumber, 0, ZES_STRING_PROPERTY_SIZE);
if (!pOsGlobalOperations->getSerialNumber(sysmanProperties.serialNumber)) {
memcpy_s(sysmanProperties.serialNumber, ZES_STRING_PROPERTY_SIZE, unknown.c_str(), unknown.length() + 1);
}
}
void GlobalOperationsImp::initGlobalOperations() {
std::call_once(initGlobalOpOnce, [this]() {
this->init();
});
}
GlobalOperationsImp::~GlobalOperationsImp() {
if (nullptr != pOsGlobalOperations) {
delete pOsGlobalOperations;
}
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include "level_zero/sysman/source/global_operations/global_operations.h"
#include "level_zero/sysman/source/global_operations/os_global_operations.h"
#include <mutex>
namespace L0 {
namespace Sysman {
class GlobalOperationsImp : public GlobalOperations, NEO::NonCopyableOrMovableClass {
public:
void init() override;
ze_result_t reset(ze_bool_t force) override;
ze_result_t deviceGetProperties(zes_device_properties_t *pProperties) override;
ze_result_t processesGetState(uint32_t *pCount, zes_process_state_t *pProcesses) override;
ze_result_t deviceGetState(zes_device_state_t *pState) override;
OsGlobalOperations *pOsGlobalOperations = nullptr;
GlobalOperationsImp() = default;
GlobalOperationsImp(OsSysman *pOsSysman) : pOsSysman(pOsSysman){};
~GlobalOperationsImp() override;
private:
OsSysman *pOsSysman = nullptr;
zes_device_properties_t sysmanProperties = {};
std::once_flag initGlobalOpOnce;
void initGlobalOperations();
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,27 @@
#
# Copyright (C) 2023 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}/os_global_operations_imp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_global_operations_imp.h
)
if(NEO_ENABLE_i915_PRELIM_DETECTION)
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/os_global_operations_helper_prelim.cpp
)
else()
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/os_global_operations_helper.cpp
)
endif()
endif()

View File

@@ -0,0 +1,14 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/global_operations/linux/os_global_operations_imp.h"
namespace L0 {
namespace Sysman {
void LinuxGlobalOperationsImp::getRepairStatus(zes_device_state_t *pState) {}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/firmware_util/firmware_util.h"
#include "level_zero/sysman/source/global_operations/linux/os_global_operations_imp.h"
namespace L0 {
namespace Sysman {
void LinuxGlobalOperationsImp::getRepairStatus(zes_device_state_t *pState) {
bool ifrStatus = false;
if (IGFX_PVC == pLinuxSysmanImp->getParentSysmanDeviceImp()->getProductFamily()) {
auto pFwInterface = pLinuxSysmanImp->getFwUtilInterface();
if (pFwInterface != nullptr) {
auto result = pFwInterface->fwIfrApplied(ifrStatus);
if (result == ZE_RESULT_SUCCESS) {
pState->repaired = ZES_REPAIR_STATUS_NOT_PERFORMED;
if (ifrStatus) {
pState->reset |= ZES_RESET_REASON_FLAG_REPAIR;
pState->repaired = ZES_REPAIR_STATUS_PERFORMED;
}
}
}
}
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,491 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/global_operations/linux/os_global_operations_imp.h"
#include "shared/source/execution_environment/root_device_environment.h"
#include "shared/source/helpers/ptr_math.h"
#include "shared/source/helpers/string.h"
#include "shared/source/os_interface/device_factory.h"
#include "shared/source/os_interface/linux/drm_neo.h"
#include "shared/source/os_interface/linux/ioctl_helper.h"
#include "shared/source/os_interface/linux/pci_path.h"
#include "level_zero/sysman/source/global_operations/global_operations_imp.h"
#include "level_zero/sysman/source/linux/fs_access.h"
#include "level_zero/sysman/source/linux/pmt/pmt.h"
#include "level_zero/sysman/source/sysman_const.h"
#include <chrono>
#include <cstring>
#include <iomanip>
#include <time.h>
namespace L0 {
namespace Sysman {
const std::string LinuxGlobalOperationsImp::deviceDir("device");
const std::string LinuxGlobalOperationsImp::vendorFile("device/vendor");
const std::string LinuxGlobalOperationsImp::subsystemVendorFile("device/subsystem_vendor");
const std::string LinuxGlobalOperationsImp::driverFile("device/driver");
const std::string LinuxGlobalOperationsImp::functionLevelReset("device/reset");
const std::string LinuxGlobalOperationsImp::clientsDir("clients");
const std::string LinuxGlobalOperationsImp::srcVersionFile("/sys/module/i915/srcversion");
const std::string LinuxGlobalOperationsImp::agamaVersionFile("/sys/module/i915/agama_version");
const std::string LinuxGlobalOperationsImp::ueventWedgedFile("/var/lib/libze_intel_gpu/wedged_file");
// Map engine entries(numeric values) present in /sys/class/drm/card<n>/clients/<client_n>/busy,
// with engine enum defined in leve-zero spec
// Note that entries with int 2 and 3(represented by i915 as CLASS_VIDEO and CLASS_VIDEO_ENHANCE)
// are both mapped to MEDIA, as CLASS_VIDEO represents any media fixed-function hardware.
static const std::map<int, zes_engine_type_flags_t> engineMap = {
{0, ZES_ENGINE_TYPE_FLAG_3D},
{1, ZES_ENGINE_TYPE_FLAG_DMA},
{2, ZES_ENGINE_TYPE_FLAG_MEDIA},
{3, ZES_ENGINE_TYPE_FLAG_MEDIA},
{4, ZES_ENGINE_TYPE_FLAG_COMPUTE}};
bool LinuxGlobalOperationsImp::getTelemOffsetAndTelemDir(uint64_t &telemOffset, const std::string &key, std::string &telemDir) {
std::string &rootPath = pLinuxSysmanImp->getPciRootPath();
if (rootPath.empty()) {
return false;
}
std::map<uint32_t, std::string> telemPciPath;
NEO::PmtUtil::getTelemNodesInPciPath(std::string_view(rootPath), telemPciPath);
if (telemPciPath.size() < pLinuxSysmanImp->getSubDeviceCount() + 1) {
return false;
}
auto iterator = telemPciPath.begin();
telemDir = iterator->second;
std::array<char, NEO::PmtUtil::guidStringSize> guidString = {};
if (!NEO::PmtUtil::readGuid(telemDir, guidString)) {
return false;
}
uint64_t offset = ULONG_MAX;
if (!NEO::PmtUtil::readOffset(telemDir, offset)) {
return false;
}
std::map<std::string, uint64_t> keyOffsetMap;
if (ZE_RESULT_SUCCESS == PlatformMonitoringTech::getKeyOffsetMap(guidString.data(), keyOffsetMap)) {
auto keyOffset = keyOffsetMap.find(key.c_str());
if (keyOffset != keyOffsetMap.end()) {
telemOffset = keyOffset->second + offset;
return true;
}
}
return false;
}
bool LinuxGlobalOperationsImp::getSerialNumber(char (&serialNumber)[ZES_STRING_PROPERTY_SIZE]) {
uint64_t offset = 0;
std::string telemDir = {};
if (!LinuxGlobalOperationsImp::getTelemOffsetAndTelemDir(offset, "PPIN", telemDir)) {
return false;
}
uint64_t value;
ssize_t bytesRead = NEO::PmtUtil::readTelem(telemDir.data(), sizeof(uint64_t), offset, &value);
if (bytesRead == sizeof(uint64_t)) {
std::ostringstream telemDataString;
telemDataString << std::hex << std::showbase << value;
memcpy_s(serialNumber, ZES_STRING_PROPERTY_SIZE, telemDataString.str().c_str(), telemDataString.str().size());
return true;
}
return false;
}
bool LinuxGlobalOperationsImp::getBoardNumber(char (&boardNumber)[ZES_STRING_PROPERTY_SIZE]) {
uint64_t offset = 0;
std::string telemDir = {};
constexpr uint32_t boardNumberSize = 32;
if (!LinuxGlobalOperationsImp::getTelemOffsetAndTelemDir(offset, "BoardNumber", telemDir)) {
return false;
}
std::array<uint8_t, boardNumberSize> value;
ssize_t bytesRead = NEO::PmtUtil::readTelem(telemDir.data(), boardNumberSize, offset, value.data());
if (bytesRead == boardNumberSize) {
memcpy_s(boardNumber, ZES_STRING_PROPERTY_SIZE, value.data(), bytesRead);
return true;
}
return false;
}
void LinuxGlobalOperationsImp::getBrandName(char (&brandName)[ZES_STRING_PROPERTY_SIZE]) {
std::string strVal;
ze_result_t result = pSysfsAccess->read(subsystemVendorFile, strVal);
if (ZE_RESULT_SUCCESS != result) {
std::strncpy(brandName, unknown.c_str(), ZES_STRING_PROPERTY_SIZE);
return;
}
if (strVal.compare(intelPciId) == 0) {
std::strncpy(brandName, vendorIntel.c_str(), ZES_STRING_PROPERTY_SIZE);
} else {
std::strncpy(brandName, unknown.c_str(), ZES_STRING_PROPERTY_SIZE);
}
}
void LinuxGlobalOperationsImp::getModelName(char (&modelName)[ZES_STRING_PROPERTY_SIZE]) {
auto &hwInfo = pLinuxSysmanImp->getParentSysmanDeviceImp()->getHardwareInfo();
std::string deviceName = hwInfo.capabilityTable.deviceName;
if (!deviceName.empty()) {
std::strncpy(modelName, deviceName.c_str(), ZES_STRING_PROPERTY_SIZE);
return;
}
std::stringstream deviceNameDefault;
deviceNameDefault << "Intel(R) Graphics";
deviceNameDefault << " [0x" << std::hex << std::setw(4) << std::setfill('0') << hwInfo.platform.usDeviceID << "]";
std::strncpy(modelName, deviceNameDefault.str().c_str(), ZES_STRING_PROPERTY_SIZE);
}
void LinuxGlobalOperationsImp::getVendorName(char (&vendorName)[ZES_STRING_PROPERTY_SIZE]) {
std::string strVal;
ze_result_t result = pSysfsAccess->read(vendorFile, strVal);
if (ZE_RESULT_SUCCESS != result) {
std::strncpy(vendorName, unknown.c_str(), ZES_STRING_PROPERTY_SIZE);
return;
}
if (strVal.compare(intelPciId) == 0) {
std::strncpy(vendorName, vendorIntel.c_str(), ZES_STRING_PROPERTY_SIZE);
} else {
std::strncpy(vendorName, unknown.c_str(), ZES_STRING_PROPERTY_SIZE);
}
}
void LinuxGlobalOperationsImp::getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) {
std::string strVal;
std::strncpy(driverVersion, unknown.c_str(), ZES_STRING_PROPERTY_SIZE);
ze_result_t result = pFsAccess->read(agamaVersionFile, strVal);
if (ZE_RESULT_SUCCESS != result) {
if (ZE_RESULT_ERROR_NOT_AVAILABLE != result) {
return;
}
result = pFsAccess->read(srcVersionFile, strVal);
if (ZE_RESULT_SUCCESS != result) {
return;
}
}
std::strncpy(driverVersion, strVal.c_str(), ZES_STRING_PROPERTY_SIZE);
return;
}
ze_result_t LinuxGlobalOperationsImp::reset(ze_bool_t force) {
if (!pSysfsAccess->isRootUser()) {
return ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS;
}
pLinuxSysmanImp->releaseSysmanDeviceResources();
std::string resetPath;
std::string resetName;
ze_result_t result = ZE_RESULT_SUCCESS;
::pid_t myPid = pProcfsAccess->myProcessId();
std::vector<int> myPidFds;
std::vector<::pid_t> processes;
result = pProcfsAccess->listProcesses(processes);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
for (auto &&pid : processes) {
std::vector<int> fds;
pLinuxSysmanImp->getPidFdsForOpenDevice(pProcfsAccess, pSysfsAccess, pid, fds);
if (pid == myPid) {
// L0 is expected to have this file open.
// Keep list of fds. Close before unbind.
myPidFds = fds;
} else if (!fds.empty()) {
if (force) {
pProcfsAccess->kill(pid);
} else {
// Device is in use by another process.
// Don't reset while in use.
return ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE;
}
}
}
pSysfsAccess->getRealPath(deviceDir, resetName);
resetName = pFsAccess->getBaseName(resetName);
for (auto &&fd : myPidFds) {
// Close open filedescriptors to the device
// before unbinding device.
// From this point forward, there is no
// graceful way to fail the reset call.
// All future ze calls by this process for this
// device will fail.
::close(fd);
}
// Unbind the device from the kernel driver.
result = pSysfsAccess->unbindDevice(resetName);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
// If someone opened the device
// after we check, kill them here.
result = pProcfsAccess->listProcesses(processes);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
std::vector<::pid_t> deviceUsingPids;
deviceUsingPids.clear();
for (auto &&pid : processes) {
std::vector<int> fds;
pLinuxSysmanImp->getPidFdsForOpenDevice(pProcfsAccess, pSysfsAccess, pid, fds);
if (!fds.empty()) {
// Kill all processes that have the device open.
pProcfsAccess->kill(pid);
deviceUsingPids.push_back(pid);
}
}
// Wait for all the processes to exit
// If they don't all exit within resetTimeout
// just fail reset.
auto start = std::chrono::steady_clock::now();
auto end = start;
for (auto &&pid : deviceUsingPids) {
while (pProcfsAccess->isAlive(pid)) {
if (std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() > resetTimeout) {
return ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE;
}
struct ::timespec timeout = {.tv_sec = 0, .tv_nsec = 1000};
::nanosleep(&timeout, NULL);
end = std::chrono::steady_clock::now();
}
}
if (!pLinuxSysmanImp->getParentSysmanDeviceImp()->getHardwareInfo().capabilityTable.isIntegratedDevice) {
result = pLinuxSysmanImp->osWarmReset();
if (ZE_RESULT_SUCCESS == result) {
return pLinuxSysmanImp->reInitSysmanDeviceResources();
}
return result;
}
pSysfsAccess->getRealPath(functionLevelReset, resetPath);
// Reset the device.
result = pFsAccess->write(resetPath, "1");
if (ZE_RESULT_SUCCESS != result) {
return result;
}
// Rebind the device to the kernel driver.
result = pSysfsAccess->bindDevice(resetName);
if (ZE_RESULT_SUCCESS != result) {
return result;
}
return pLinuxSysmanImp->reInitSysmanDeviceResources();
}
// Processes in the form of clients are present in sysfs like this:
// # /sys/class/drm/card0/clients$ ls
// 4 5
// # /sys/class/drm/card0/clients/4$ ls
// busy name pid
// # /sys/class/drm/card0/clients/4/busy$ ls
// 0 1 2 3
//
// Number of processes(If one process opened drm device multiple times, then multiple entries will be
// present for same process in clients directory) will be the number of clients
// (For example from above example, processes dirs are 4,5)
// Thus total number of times drm connection opened with this device will be 2.
// process.pid = pid (from above example)
// process.engines -> For each client's busy dir, numbers 0,1,2,3 represent engines and they contain
// accumulated nanoseconds each client spent on engines.
// Thus we traverse each file in busy dir for non-zero time and if we find that file say 0,then we could say that
// this engine 0 is used by process.
ze_result_t LinuxGlobalOperationsImp::scanProcessesState(std::vector<zes_process_state_t> &pProcessList) {
std::vector<std::string> clientIds;
struct deviceMemStruct {
uint64_t deviceMemorySize;
uint64_t deviceSharedMemorySize;
};
struct engineMemoryPairType {
int64_t engineTypeField;
deviceMemStruct deviceMemStructField;
};
ze_result_t result = pSysfsAccess->scanDirEntries(clientsDir, clientIds);
if (ZE_RESULT_SUCCESS != result) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
// Create a map with unique pid as key and engineType as value
std::map<uint64_t, engineMemoryPairType> pidClientMap;
for (const auto &clientId : clientIds) {
// realClientPidPath will be something like: clients/<clientId>/pid
std::string realClientPidPath = clientsDir + "/" + clientId + "/" + "pid";
uint64_t pid;
result = pSysfsAccess->read(realClientPidPath, pid);
if (ZE_RESULT_SUCCESS != result) {
std::string bPidString;
result = pSysfsAccess->read(realClientPidPath, bPidString);
if (result == ZE_RESULT_SUCCESS) {
size_t start = bPidString.find("<");
size_t end = bPidString.find(">");
std::string bPid = bPidString.substr(start + 1, end - start - 1);
pid = std::stoull(bPid, nullptr, 10);
}
}
if (ZE_RESULT_SUCCESS != result) {
if (ZE_RESULT_ERROR_NOT_AVAILABLE == result) {
// update the result as Success as ZE_RESULT_ERROR_NOT_AVAILABLE is expected if the "realClientPidPath" folder is empty
// this condition(when encountered) must not prevent the information accumulated for other clientIds
// this situation occurs when there is no call modifying result,
result = ZE_RESULT_SUCCESS;
continue;
} else {
return result;
}
}
// Traverse the clients/<clientId>/busy directory to get accelerator engines used by process
std::vector<std::string> engineNums = {};
int64_t engineType = 0;
std::string busyDirForEngines = clientsDir + "/" + clientId + "/" + "busy";
result = pSysfsAccess->scanDirEntries(busyDirForEngines, engineNums);
if (ZE_RESULT_SUCCESS != result) {
if (ZE_RESULT_ERROR_NOT_AVAILABLE == result) {
// update the result as Success as ZE_RESULT_ERROR_NOT_AVAILABLE is expected if the "realClientPidPath" folder is empty
// this condition(when encountered) must not prevent the information accumulated for other clientIds
// this situation occurs when there is no call modifying result,
// Here its seen when the last element of clientIds returns ZE_RESULT_ERROR_NOT_AVAILABLE for some reason.
engineType = ZES_ENGINE_TYPE_FLAG_OTHER; // When busy node is absent assign engine type with ZES_ENGINE_TYPE_FLAG_OTHER
} else {
return result;
}
}
// Scan all engine files present in /sys/class/drm/card0/clients/<ClientId>/busy and check
// whether that engine is used by process
for (const auto &engineNum : engineNums) {
uint64_t timeSpent = 0;
std::string engine = busyDirForEngines + "/" + engineNum;
result = pSysfsAccess->read(engine, timeSpent);
if (ZE_RESULT_SUCCESS != result) {
if (ZE_RESULT_ERROR_NOT_AVAILABLE == result) {
continue;
} else {
return result;
}
}
if (timeSpent > 0) {
int i915EnginNumber = stoi(engineNum);
auto i915MapToL0EngineType = engineMap.find(i915EnginNumber);
zes_engine_type_flags_t val = ZES_ENGINE_TYPE_FLAG_OTHER;
if (i915MapToL0EngineType != engineMap.end()) {
// Found a valid map
val = i915MapToL0EngineType->second;
}
// In this for loop we want to retrieve the overall engines used by process
engineType = engineType | val;
}
}
uint64_t memSize = 0;
std::string realClientTotalMemoryPath = clientsDir + "/" + clientId + "/" + "total_device_memory_buffer_objects" + "/" + "created_bytes";
result = pSysfsAccess->read(realClientTotalMemoryPath, memSize);
if (ZE_RESULT_SUCCESS != result) {
if (ZE_RESULT_ERROR_NOT_AVAILABLE != result) {
return result;
}
}
uint64_t sharedMemSize = 0;
std::string realClientTotalSharedMemoryPath = clientsDir + "/" + clientId + "/" + "total_device_memory_buffer_objects" + "/" + "imported_bytes";
result = pSysfsAccess->read(realClientTotalSharedMemoryPath, sharedMemSize);
if (ZE_RESULT_SUCCESS != result) {
if (ZE_RESULT_ERROR_NOT_AVAILABLE != result) {
return result;
}
}
deviceMemStruct totalDeviceMem = {memSize, sharedMemSize};
engineMemoryPairType engineMemoryPair = {engineType, totalDeviceMem};
auto ret = pidClientMap.insert(std::make_pair(pid, engineMemoryPair));
if (ret.second == false) {
// insertion failed as entry with same pid already exists in map
// Now update the engineMemoryPairType field for the existing pid entry
engineMemoryPairType updateEngineMemoryPair;
auto pidEntryFromMap = pidClientMap.find(pid);
auto existingEngineType = pidEntryFromMap->second.engineTypeField;
auto existingdeviceMemorySize = pidEntryFromMap->second.deviceMemStructField.deviceMemorySize;
auto existingdeviceSharedMemorySize = pidEntryFromMap->second.deviceMemStructField.deviceSharedMemorySize;
updateEngineMemoryPair.engineTypeField = existingEngineType | engineMemoryPair.engineTypeField;
updateEngineMemoryPair.deviceMemStructField.deviceMemorySize = existingdeviceMemorySize + engineMemoryPair.deviceMemStructField.deviceMemorySize;
updateEngineMemoryPair.deviceMemStructField.deviceSharedMemorySize = existingdeviceSharedMemorySize + engineMemoryPair.deviceMemStructField.deviceSharedMemorySize;
pidClientMap[pid] = updateEngineMemoryPair;
}
result = ZE_RESULT_SUCCESS;
}
// iterate through all elements of pidClientMap
for (auto itr = pidClientMap.begin(); itr != pidClientMap.end(); ++itr) {
zes_process_state_t process;
process.processId = static_cast<uint32_t>(itr->first);
process.memSize = itr->second.deviceMemStructField.deviceMemorySize;
process.sharedSize = itr->second.deviceMemStructField.deviceSharedMemorySize;
process.engines = static_cast<uint32_t>(itr->second.engineTypeField);
pProcessList.push_back(process);
}
return result;
}
void LinuxGlobalOperationsImp::getWedgedStatus(zes_device_state_t *pState) {
NEO::GemContextCreateExt gcc{};
auto hwDeviceId = pLinuxSysmanImp->getSysmanHwDeviceId();
hwDeviceId->openFileDescriptor();
auto pDrm = pLinuxSysmanImp->getDrm();
// Device is said to be in wedged if context creation returns EIO.
auto ret = pDrm->getIoctlHelper()->ioctl(NEO::DrmIoctl::GemContextCreateExt, &gcc);
if (ret == 0) {
pDrm->destroyDrmContext(gcc.contextId);
return;
}
hwDeviceId->closeFileDescriptor();
if (pDrm->getErrno() == EIO) {
pState->reset |= ZES_RESET_REASON_FLAG_WEDGED;
}
}
ze_result_t LinuxGlobalOperationsImp::deviceGetState(zes_device_state_t *pState) {
memset(pState, 0, sizeof(zes_device_state_t));
pState->repaired = ZES_REPAIR_STATUS_UNSUPPORTED;
getWedgedStatus(pState);
getRepairStatus(pState);
return ZE_RESULT_SUCCESS;
}
LinuxGlobalOperationsImp::LinuxGlobalOperationsImp(OsSysman *pOsSysman) {
pLinuxSysmanImp = static_cast<LinuxSysmanImp *>(pOsSysman);
pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess();
pProcfsAccess = &pLinuxSysmanImp->getProcfsAccess();
pFsAccess = &pLinuxSysmanImp->getFsAccess();
devicePciBdf = pLinuxSysmanImp->getParentSysmanDeviceImp()->getRootDeviceEnvironment().osInterface->getDriverModel()->as<NEO::Drm>()->getPciPath();
rootDeviceIndex = pLinuxSysmanImp->getParentSysmanDeviceImp()->getRootDeviceIndex();
}
OsGlobalOperations *OsGlobalOperations::create(OsSysman *pOsSysman) {
LinuxGlobalOperationsImp *pLinuxGlobalOperationsImp = new LinuxGlobalOperationsImp(pOsSysman);
return static_cast<OsGlobalOperations *>(pLinuxGlobalOperationsImp);
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/os_interface/linux/pmt_util.h"
#include "level_zero/sysman/source/global_operations/os_global_operations.h"
#include "level_zero/sysman/source/linux/os_sysman_imp.h"
namespace L0 {
namespace Sysman {
class SysfsAccess;
class LinuxGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMovableClass {
public:
bool getSerialNumber(char (&serialNumber)[ZES_STRING_PROPERTY_SIZE]) override;
bool getBoardNumber(char (&boardNumber)[ZES_STRING_PROPERTY_SIZE]) override;
void getBrandName(char (&brandName)[ZES_STRING_PROPERTY_SIZE]) override;
void getModelName(char (&modelName)[ZES_STRING_PROPERTY_SIZE]) override;
void getVendorName(char (&vendorName)[ZES_STRING_PROPERTY_SIZE]) override;
void getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) override;
void getWedgedStatus(zes_device_state_t *pState) override;
void getRepairStatus(zes_device_state_t *pState) override;
ze_result_t reset(ze_bool_t force) override;
ze_result_t scanProcessesState(std::vector<zes_process_state_t> &pProcessList) override;
ze_result_t deviceGetState(zes_device_state_t *pState) override;
LinuxGlobalOperationsImp() = default;
LinuxGlobalOperationsImp(OsSysman *pOsSysman);
~LinuxGlobalOperationsImp() override = default;
protected:
FsAccess *pFsAccess = nullptr;
ProcfsAccess *pProcfsAccess = nullptr;
SysfsAccess *pSysfsAccess = nullptr;
LinuxSysmanImp *pLinuxSysmanImp = nullptr;
int resetTimeout = 10000; // in milliseconds
void releaseSysmanDeviceResources();
void releaseDeviceResources();
ze_result_t initDevice();
void reInitSysmanDeviceResources();
private:
static const std::string deviceDir;
static const std::string vendorFile;
static const std::string subsystemVendorFile;
static const std::string driverFile;
static const std::string functionLevelReset;
static const std::string clientsDir;
static const std::string srcVersionFile;
static const std::string agamaVersionFile;
static const std::string ueventWedgedFile;
bool getTelemOffsetAndTelemDir(uint64_t &telemOffset, const std::string &key, std::string &telemDir);
std::string devicePciBdf = "";
NEO::ExecutionEnvironment *executionEnvironment = nullptr;
uint32_t rootDeviceIndex = 0u;
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "level_zero/sysman/source/os_sysman.h"
#include <level_zero/zes_api.h>
#include <vector>
namespace L0 {
namespace Sysman {
class OsGlobalOperations {
public:
virtual bool getSerialNumber(char (&serialNumber)[ZES_STRING_PROPERTY_SIZE]) = 0;
virtual bool getBoardNumber(char (&boardNumber)[ZES_STRING_PROPERTY_SIZE]) = 0;
virtual void getBrandName(char (&brandName)[ZES_STRING_PROPERTY_SIZE]) = 0;
virtual void getModelName(char (&modelName)[ZES_STRING_PROPERTY_SIZE]) = 0;
virtual void getVendorName(char (&vendorName)[ZES_STRING_PROPERTY_SIZE]) = 0;
virtual void getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) = 0;
virtual void getWedgedStatus(zes_device_state_t *pState) = 0;
virtual void getRepairStatus(zes_device_state_t *pState) = 0;
virtual ze_result_t reset(ze_bool_t force) = 0;
virtual ze_result_t scanProcessesState(std::vector<zes_process_state_t> &pProcessList) = 0;
virtual ze_result_t deviceGetState(zes_device_state_t *pState) = 0;
static OsGlobalOperations *create(OsSysman *pOsSysman);
virtual ~OsGlobalOperations() {}
};
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,14 @@
#
# Copyright (C) 2023 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}/os_global_operations_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/os_global_operations_imp.cpp
)
endif()

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/global_operations/windows/os_global_operations_imp.h"
namespace L0 {
namespace Sysman {
bool WddmGlobalOperationsImp::getSerialNumber(char (&serialNumber)[ZES_STRING_PROPERTY_SIZE]) {
return false;
}
bool WddmGlobalOperationsImp::getBoardNumber(char (&boardNumber)[ZES_STRING_PROPERTY_SIZE]) {
return false;
}
void WddmGlobalOperationsImp::getBrandName(char (&brandName)[ZES_STRING_PROPERTY_SIZE]) {
}
void WddmGlobalOperationsImp::getModelName(char (&modelName)[ZES_STRING_PROPERTY_SIZE]) {
}
void WddmGlobalOperationsImp::getVendorName(char (&vendorName)[ZES_STRING_PROPERTY_SIZE]) {
}
void WddmGlobalOperationsImp::getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) {
}
void WddmGlobalOperationsImp::getWedgedStatus(zes_device_state_t *pState) {
}
void WddmGlobalOperationsImp::getRepairStatus(zes_device_state_t *pState) {
}
ze_result_t WddmGlobalOperationsImp::reset(ze_bool_t force) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmGlobalOperationsImp::scanProcessesState(std::vector<zes_process_state_t> &pProcessList) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t WddmGlobalOperationsImp::deviceGetState(zes_device_state_t *pState) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
WddmGlobalOperationsImp::WddmGlobalOperationsImp(OsSysman *pOsSysman) {
}
OsGlobalOperations *OsGlobalOperations::create(OsSysman *pOsSysman) {
WddmGlobalOperationsImp *pWddmGlobalOperationsImp = new WddmGlobalOperationsImp(pOsSysman);
return static_cast<OsGlobalOperations *>(pWddmGlobalOperationsImp);
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include "level_zero/sysman/source/global_operations/os_global_operations.h"
#include "level_zero/sysman/source/windows/os_sysman_imp.h"
namespace L0 {
namespace Sysman {
class WddmGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMovableClass {
public:
bool getSerialNumber(char (&serialNumber)[ZES_STRING_PROPERTY_SIZE]) override;
bool getBoardNumber(char (&boardNumber)[ZES_STRING_PROPERTY_SIZE]) override;
void getBrandName(char (&brandName)[ZES_STRING_PROPERTY_SIZE]) override;
void getModelName(char (&modelName)[ZES_STRING_PROPERTY_SIZE]) override;
void getVendorName(char (&vendorName)[ZES_STRING_PROPERTY_SIZE]) override;
void getDriverVersion(char (&driverVersion)[ZES_STRING_PROPERTY_SIZE]) override;
void getWedgedStatus(zes_device_state_t *pState) override;
void getRepairStatus(zes_device_state_t *pState) override;
ze_result_t reset(ze_bool_t force) override;
ze_result_t scanProcessesState(std::vector<zes_process_state_t> &pProcessList) override;
ze_result_t deviceGetState(zes_device_state_t *pState) override;
WddmGlobalOperationsImp(OsSysman *pOsSysman);
WddmGlobalOperationsImp() = default;
~WddmGlobalOperationsImp() override = default;
};
} // namespace Sysman
} // namespace L0

View File

@@ -7,9 +7,12 @@
#include "level_zero/sysman/source/linux/os_sysman_imp.h"
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/helpers/gfx_core_helper.h"
#include "shared/source/helpers/sleep.h"
#include "shared/source/os_interface/driver_info.h"
#include "shared/source/os_interface/linux/drm_neo.h"
#include "shared/source/os_interface/linux/pci_path.h"
#include "shared/source/os_interface/os_interface.h"
#include "level_zero/sysman/source/firmware_util/firmware_util.h"
@@ -17,6 +20,8 @@
#include "level_zero/sysman/source/linux/pmt/pmt.h"
#include "level_zero/sysman/source/linux/pmu/pmu.h"
#include <linux/pci_regs.h>
namespace L0 {
namespace Sysman {
@@ -55,6 +60,9 @@ ze_result_t LinuxSysmanImp::init() {
subDeviceCount = 0;
}
rootPath = NEO::getPciRootPath(myDeviceFd).value_or("");
pSysfsAccess->getRealPath(deviceDir, gtDevicePath);
osInterface.getDriverModel()->as<NEO::Drm>()->cleanup();
// Close Drm handles
sysmanHwDeviceId->closeFileDescriptor();
@@ -62,6 +70,10 @@ ze_result_t LinuxSysmanImp::init() {
return createPmtHandles();
}
std::string &LinuxSysmanImp::getPciRootPath() {
return rootPath;
}
SysmanHwDeviceIdDrm *LinuxSysmanImp::getSysmanHwDeviceId() {
return static_cast<SysmanHwDeviceIdDrm *>(getDrm()->getHwDeviceId().get());
}
@@ -95,6 +107,21 @@ static std::string modifyPathOnLevel(std::string realPciPath, uint8_t nLevel) {
}
return realPciPath;
}
std::string LinuxSysmanImp::getPciRootPortDirectoryPath(std::string realPciPath) {
// the rootport is always the first pci folder after the pcie slot.
// +-[0000:89]-+-00.0
// | +-00.1
// | +-00.2
// | +-00.4
// | \-02.0-[8a-8e]----00.0-[8b-8e]--+-01.0-[8c-8d]----00.0
// | \-02.0-[8e]--+-00.0
// | +-00.1
// | \-00.2
// /sys/devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0
// '/sys/devices/pci0000:89/0000:89:02.0/' will always be the same distance.
// from 0000:8c:00.0 i.e the 3rd PCI address from the gt tile
return modifyPathOnLevel(realPciPath, 3);
}
std::string LinuxSysmanImp::getPciCardBusDirectoryPath(std::string realPciPath) {
// the cardbus is always the second pci folder after the pcie slot.
@@ -204,6 +231,214 @@ LinuxSysmanImp::~LinuxSysmanImp() {
releasePmtObject();
}
void LinuxSysmanImp::getPidFdsForOpenDevice(ProcfsAccess *pProcfsAccess, SysfsAccess *pSysfsAccess, const ::pid_t pid, std::vector<int> &deviceFds) {
// Return a list of all the file descriptors of this process that point to this device
std::vector<int> fds;
deviceFds.clear();
if (ZE_RESULT_SUCCESS != pProcfsAccess->getFileDescriptors(pid, fds)) {
// Process exited. Not an error. Just ignore.
return;
}
for (auto &&fd : fds) {
std::string file;
if (pProcfsAccess->getFileName(pid, fd, file) != ZE_RESULT_SUCCESS) {
// Process closed this file. Not an error. Just ignore.
continue;
}
if (pSysfsAccess->isMyDeviceFile(file)) {
deviceFds.push_back(fd);
}
}
}
ze_result_t LinuxSysmanImp::gpuProcessCleanup() {
::pid_t myPid = pProcfsAccess->myProcessId();
std::vector<::pid_t> processes;
std::vector<int> myPidFds;
ze_result_t result = pProcfsAccess->listProcesses(processes);
if (ZE_RESULT_SUCCESS != result) {
NEO::printDebugString(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr,
"gpuProcessCleanup: listProcesses() failed with error code: %ld\n", result);
return result;
}
for (auto &&pid : processes) {
std::vector<int> fds;
getPidFdsForOpenDevice(pProcfsAccess, pSysfsAccess, pid, fds);
if (pid == myPid) {
// L0 is expected to have this file open.
// Keep list of fds. Close before unbind.
myPidFds = fds;
continue;
}
if (!fds.empty()) {
pProcfsAccess->kill(pid);
}
}
for (auto &&fd : myPidFds) {
// Close open filedescriptors to the device
// before unbinding device.
// From this point forward, there is no
// graceful way to fail the reset call.
// All future ze calls by this process for this
// device will fail.
NEO::SysCalls::close(fd);
}
return ZE_RESULT_SUCCESS;
}
void LinuxSysmanImp::releaseSysmanDeviceResources() {
getSysmanDeviceImp()->pEngineHandleContext->releaseEngines();
getSysmanDeviceImp()->pRasHandleContext->releaseRasHandles();
if (!diagnosticsReset) {
getSysmanDeviceImp()->pDiagnosticsHandleContext->releaseDiagnosticsHandles();
}
getSysmanDeviceImp()->pFirmwareHandleContext->releaseFwHandles();
releasePmtObject();
if (!diagnosticsReset) {
releaseFwUtilInterface();
}
}
ze_result_t LinuxSysmanImp::reInitSysmanDeviceResources() {
createPmtHandles();
if (!diagnosticsReset) {
createFwUtilInterface();
}
if (getSysmanDeviceImp()->pRasHandleContext->isRasInitDone()) {
getSysmanDeviceImp()->pRasHandleContext->init(getSubDeviceCount());
}
if (getSysmanDeviceImp()->pEngineHandleContext->isEngineInitDone()) {
getSysmanDeviceImp()->pEngineHandleContext->init(getSubDeviceCount());
}
if (!diagnosticsReset) {
if (getSysmanDeviceImp()->pDiagnosticsHandleContext->isDiagnosticsInitDone()) {
getSysmanDeviceImp()->pDiagnosticsHandleContext->init();
}
}
this->diagnosticsReset = false;
if (getSysmanDeviceImp()->pFirmwareHandleContext->isFirmwareInitDone()) {
getSysmanDeviceImp()->pFirmwareHandleContext->init();
}
return ZE_RESULT_SUCCESS;
}
// function to clear Hot-Plug interrupt enable bit in the slot control register
// this is required to prevent interrupts from being raised in the warm reset path.
void LinuxSysmanImp::clearHPIE(int fd) {
uint8_t value = 0x00;
uint8_t resetValue = 0x00;
uint8_t offset = 0x0;
this->preadFunction(fd, &offset, 0x01, PCI_CAPABILITY_LIST);
// Bottom two bits of capability pointer register are reserved and
// software should mask these bits to get pointer to capability list.
// PCI_EXP_SLTCTL - offset for slot control register.
offset = (offset & 0xfc) + PCI_EXP_SLTCTL;
this->preadFunction(fd, &value, 0x01, offset);
resetValue = value & (~PCI_EXP_SLTCTL_HPIE);
this->pwriteFunction(fd, &resetValue, 0x01, offset);
NEO::sleep(std::chrono::seconds(10)); // Sleep for 10seconds just to make sure the change is propagated.
}
// A 'warm reset' is a conventional reset that is triggered across a PCI express link.
// A warm reset is triggered either when a link is forced into electrical idle or
// by sending TS1 and TS2 ordered sets with the hot reset bit set.
// Software can initiate a warm reset by setting and then clearing the secondary bus reset bit
// in the bridge control register in the PCI configuration space of the bridge port upstream of the device.
ze_result_t LinuxSysmanImp::osWarmReset() {
std::string rootPortPath;
rootPortPath = getPciRootPortDirectoryPath(gtDevicePath);
int fd = 0;
std::string configFilePath = rootPortPath + '/' + "config";
fd = this->openFunction(configFilePath.c_str(), O_RDWR);
if (fd < 0) {
return ZE_RESULT_ERROR_UNKNOWN;
}
std::string cardBusPath = getPciCardBusDirectoryPath(gtDevicePath);
ze_result_t result = pFsAccess->write(cardBusPath + '/' + "remove", "1");
if (ZE_RESULT_SUCCESS != result) {
return result;
}
if (diagnosticsReset) {
NEO::sleep(std::chrono::seconds(30)); // Sleep for 30seconds to make sure that the config spaces of all devices are saved correctly after IFR
} else {
NEO::sleep(std::chrono::seconds(10)); // Sleep for 10seconds to make sure that the config spaces of all devices are saved correctly
}
clearHPIE(fd);
uint8_t offset = PCI_BRIDGE_CONTROL; // Bridge control offset in Header of PCI config space
uint8_t value = 0x00;
uint8_t resetValue = 0x00;
this->preadFunction(fd, &value, 0x01, offset);
resetValue = value | PCI_BRIDGE_CTL_BUS_RESET;
this->pwriteFunction(fd, &resetValue, 0x01, offset);
NEO::sleep(std::chrono::seconds(10)); // Sleep for 10seconds just to make sure the change is propagated.
this->pwriteFunction(fd, &value, 0x01, offset);
NEO::sleep(std::chrono::seconds(10)); // Sleep for 10seconds to make sure the change is propagated. before rescan is done.
result = pFsAccess->write(rootPortPath + '/' + "rescan", "1");
if (ZE_RESULT_SUCCESS != result) {
return result;
}
if (diagnosticsReset) {
NEO::sleep(std::chrono::seconds(30)); // Sleep for 30seconds to make sure that the config spaces of all devices are saved correctly after IFR
} else {
NEO::sleep(std::chrono::seconds(10)); // Sleep for 10seconds, allows the rescan to complete on all devices attached to the root port.
}
int ret = this->closeFunction(fd);
if (ret < 0) {
return ZE_RESULT_ERROR_UNKNOWN;
}
return result;
}
std::string LinuxSysmanImp::getAddressFromPath(std::string &rootPortPath) {
size_t loc;
loc = rootPortPath.find_last_of('/'); // we get the pci address of the root port from rootPortPath
return rootPortPath.substr(loc + 1, std::string::npos);
}
ze_result_t LinuxSysmanImp::osColdReset() {
const std::string slotPath("/sys/bus/pci/slots/"); // holds the directories matching to the number of slots in the PC
std::string cardBusPath; // will hold the PCIe Root port directory path (the address of the PCIe slot).
// will hold the absolute real path (not symlink) to the selected Device
cardBusPath = getPciCardBusDirectoryPath(gtDevicePath); // e.g cardBusPath=/sys/devices/pci0000:89/0000:89:02.0/
std::string rootAddress = getAddressFromPath(cardBusPath); // e.g rootAddress = 0000:8a:00.0
std::vector<std::string> dir;
ze_result_t result = pFsAccess->listDirectory(slotPath, dir); // get list of slot directories from /sys/bus/pci/slots/
if (ZE_RESULT_SUCCESS != result) {
return result;
}
for (auto &slot : dir) {
std::string slotAddress;
result = pFsAccess->read((slotPath + slot + "/address"), slotAddress); // extract slot address from the slot directory /sys/bus/pci/slots/<slot num>/address
if (ZE_RESULT_SUCCESS != result) {
return result;
}
if (slotAddress.compare(rootAddress) == 0) { // compare slot address to root port address
result = pFsAccess->write((slotPath + slot + "/power"), "0"); // turn off power
if (ZE_RESULT_SUCCESS != result) {
return result;
}
NEO::sleep(std::chrono::milliseconds(100)); // Sleep for 100 milliseconds just to make sure, 1 ms is defined as part of spec
result = pFsAccess->write((slotPath + slot + "/power"), "1"); // turn on power
if (ZE_RESULT_SUCCESS != result) {
return result;
}
return ZE_RESULT_SUCCESS;
}
}
return ZE_RESULT_ERROR_DEVICE_LOST; // incase the reset fails inform upper layers.
}
OsSysman *OsSysman::create(SysmanDeviceImp *pParentSysmanDeviceImp) {
LinuxSysmanImp *pLinuxSysmanImp = new LinuxSysmanImp(pParentSysmanDeviceImp);
return static_cast<OsSysman *>(pLinuxSysmanImp);

View File

@@ -8,6 +8,7 @@
#pragma once
#include "shared/source/execution_environment/execution_environment.h"
#include "shared/source/helpers/non_copyable_or_moveable.h"
#include "shared/source/os_interface/linux/sys_calls.h"
#include "level_zero/sysman/source/linux/hw_device_id_linux.h"
#include "level_zero/sysman/source/os_sysman.h"
@@ -43,16 +44,31 @@ class LinuxSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass {
SysmanDeviceImp *getSysmanDeviceImp();
uint32_t getSubDeviceCount() override;
std::string getPciCardBusDirectoryPath(std::string realPciPath);
static std::string getPciRootPortDirectoryPath(std::string realPciPath);
PlatformMonitoringTech *getPlatformMonitoringTechAccess(uint32_t subDeviceId);
PRODUCT_FAMILY getProductFamily() const { return pParentSysmanDeviceImp->getProductFamily(); }
SysmanHwDeviceIdDrm *getSysmanHwDeviceId();
NEO::Drm *getDrm();
void releasePmtObject();
void releaseSysmanDeviceResources();
ze_result_t reInitSysmanDeviceResources();
MOCKABLE_VIRTUAL void getPidFdsForOpenDevice(ProcfsAccess *, SysfsAccess *, const ::pid_t, std::vector<int> &);
MOCKABLE_VIRTUAL ze_result_t osWarmReset();
MOCKABLE_VIRTUAL ze_result_t osColdReset();
ze_result_t gpuProcessCleanup();
std::string getAddressFromPath(std::string &rootPortPath);
decltype(&NEO::SysCalls::open) openFunction = NEO::SysCalls::open;
decltype(&NEO::SysCalls::close) closeFunction = NEO::SysCalls::close;
decltype(&NEO::SysCalls::pread) preadFunction = NEO::SysCalls::pread;
decltype(&NEO::SysCalls::pwrite) pwriteFunction = NEO::SysCalls::pwrite;
ze_result_t createPmtHandles();
SysmanDeviceImp *getParentSysmanDeviceImp() { return pParentSysmanDeviceImp; }
std::string &getPciRootPath();
std::string devicePciBdf = "";
NEO::ExecutionEnvironment *executionEnvironment = nullptr;
uint32_t rootDeviceIndex;
bool diagnosticsReset = false;
std::string gtDevicePath;
protected:
FsAccess *pFsAccess = nullptr;
@@ -62,6 +78,7 @@ class LinuxSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass {
uint32_t subDeviceCount = 0;
FirmwareUtil *pFwUtilInterface = nullptr;
PmuInterface *pPmuInterface = nullptr;
std::string rootPath;
void releaseFwUtilInterface();
private:
@@ -69,6 +86,7 @@ class LinuxSysmanImp : public OsSysman, NEO::NonCopyableOrMovableClass {
SysmanDeviceImp *pParentSysmanDeviceImp = nullptr;
static const std::string deviceDir;
void createFwUtilInterface();
void clearHPIE(int fd);
};
} // namespace Sysman

View File

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

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/ras/ras.h"
#include "shared/source/helpers/basic_math.h"
#include "level_zero/sysman/source/os_sysman.h"
namespace L0 {
namespace Sysman {
void RasHandleContext::releaseRasHandles() {
for (Ras *pRas : handleList) {
delete pRas;
}
handleList.clear();
}
RasHandleContext::~RasHandleContext() {
releaseRasHandles();
}
void RasHandleContext::init(uint32_t subDeviceCount) {
}
ze_result_t RasHandleContext::rasGet(uint32_t *pCount,
zes_ras_handle_t *phRas) {
std::call_once(initRasOnce, [this]() {
this->init(pOsSysman->getSubDeviceCount());
this->rasInitDone = true;
});
uint32_t handleListSize = static_cast<uint32_t>(handleList.size());
uint32_t numToCopy = std::min(*pCount, handleListSize);
if (0 == *pCount || *pCount > handleListSize) {
*pCount = handleListSize;
}
if (nullptr != phRas) {
for (uint32_t i = 0; i < numToCopy; i++) {
phRas[i] = handleList[i]->toHandle();
}
}
return ZE_RESULT_SUCCESS;
}
} // namespace Sysman
} // namespace L0

View File

@@ -0,0 +1,58 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "level_zero/api/sysman/zes_handles_struct.h"
#include "level_zero/sysman/source/sysman_device.h"
#include <level_zero/zes_api.h>
#include <mutex>
#include <vector>
namespace L0 {
namespace Sysman {
struct OsSysman;
class Ras : _zes_ras_handle_t {
public:
virtual ze_result_t rasGetProperties(zes_ras_properties_t *pProperties) = 0;
virtual ze_result_t rasGetConfig(zes_ras_config_t *pConfig) = 0;
virtual ze_result_t rasSetConfig(const zes_ras_config_t *pConfig) = 0;
virtual ze_result_t rasGetState(zes_ras_state_t *pState, ze_bool_t clear) = 0;
static Ras *fromHandle(zes_ras_handle_t handle) {
return static_cast<Ras *>(handle);
}
inline zes_ras_handle_t toHandle() { return this; }
bool isRasErrorSupported = false;
zes_ras_error_type_t rasErrorType{};
};
struct RasHandleContext {
RasHandleContext(OsSysman *pOsSysman) : pOsSysman(pOsSysman){};
MOCKABLE_VIRTUAL ~RasHandleContext();
MOCKABLE_VIRTUAL void init(uint32_t subDeviceCount);
void releaseRasHandles();
ze_result_t rasGet(uint32_t *pCount, zes_ras_handle_t *phRas);
OsSysman *pOsSysman = nullptr;
std::vector<Ras *> handleList = {};
bool isRasInitDone() {
return rasInitDone;
}
private:
void createHandle(zes_ras_error_type_t type, ze_device_handle_t deviceHandle);
std::once_flag initRasOnce;
bool rasInitDone = false;
};
} // namespace Sysman
} // namespace L0

View File

@@ -60,10 +60,39 @@ ze_result_t SysmanDevice::schedulerGet(zes_device_handle_t hDevice, uint32_t *pC
return pSysmanDevice->schedulerGet(pCount, phScheduler);
}
ze_result_t SysmanDevice::rasGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_ras_handle_t *phRas) {
auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice);
return pSysmanDevice->rasGet(pCount, phRas);
}
ze_result_t SysmanDevice::diagnosticsGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_diag_handle_t *phDiagnostics) {
auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice);
return pSysmanDevice->diagnosticsGet(pCount, phDiagnostics);
}
ze_result_t SysmanDevice::firmwareGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_firmware_handle_t *phFirmware) {
auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice);
return pSysmanDevice->firmwareGet(pCount, phFirmware);
}
ze_result_t SysmanDevice::deviceGetProperties(zes_device_handle_t hDevice, zes_device_properties_t *pProperties) {
auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice);
return pSysmanDevice->deviceGetProperties(pProperties);
}
ze_result_t SysmanDevice::processesGetState(zes_device_handle_t hDevice, uint32_t *pCount, zes_process_state_t *pProcesses) {
auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice);
return pSysmanDevice->processesGetState(pCount, pProcesses);
}
ze_result_t SysmanDevice::deviceReset(zes_device_handle_t hDevice, ze_bool_t force) {
auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice);
return pSysmanDevice->deviceReset(force);
}
ze_result_t SysmanDevice::deviceGetState(zes_device_handle_t hDevice, zes_device_state_t *pState) {
auto pSysmanDevice = L0::Sysman::SysmanDevice::fromHandle(hDevice);
return pSysmanDevice->deviceGetState(pState);
}
} // namespace Sysman
} // namespace L0

View File

@@ -9,12 +9,15 @@
#include "shared/source/execution_environment/execution_environment.h"
#include "level_zero/core/source/device/device.h"
#include "level_zero/sysman/source/diagnostics/diagnostics.h"
#include "level_zero/sysman/source/engine/engine.h"
#include "level_zero/sysman/source/fabric_port/fabric_port.h"
#include "level_zero/sysman/source/firmware/firmware.h"
#include "level_zero/sysman/source/frequency/frequency.h"
#include "level_zero/sysman/source/global_operations/global_operations.h"
#include "level_zero/sysman/source/memory/memory.h"
#include "level_zero/sysman/source/power/power.h"
#include "level_zero/sysman/source/ras/ras.h"
#include "level_zero/sysman/source/scheduler/scheduler.h"
#include <level_zero/ze_api.h>
#include <level_zero/zes_api.h>
@@ -35,6 +38,7 @@ struct SysmanDevice : _ze_device_handle_t {
virtual ze_result_t powerGetCardDomain(zes_pwr_handle_t *phPower) = 0;
static ze_result_t fabricPortGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_fabric_port_handle_t *phPort);
virtual ze_result_t fabricPortGet(uint32_t *pCount, zes_fabric_port_handle_t *phPort) = 0;
static ze_result_t memoryGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_mem_handle_t *phMemory);
virtual ze_result_t memoryGet(uint32_t *pCount, zes_mem_handle_t *phMemory) = 0;
@@ -49,6 +53,24 @@ struct SysmanDevice : _ze_device_handle_t {
static ze_result_t firmwareGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_firmware_handle_t *phFirmware);
virtual ze_result_t firmwareGet(uint32_t *pCount, zes_firmware_handle_t *phFirmware) = 0;
static ze_result_t diagnosticsGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_diag_handle_t *phDiagnostics);
virtual ze_result_t diagnosticsGet(uint32_t *pCount, zes_diag_handle_t *phDiagnostics) = 0;
static ze_result_t rasGet(zes_device_handle_t hDevice, uint32_t *pCount, zes_ras_handle_t *phRas);
virtual ze_result_t rasGet(uint32_t *pCount, zes_ras_handle_t *phRas) = 0;
static ze_result_t deviceReset(zes_device_handle_t hDevice, ze_bool_t force);
virtual ze_result_t deviceReset(ze_bool_t force) = 0;
static ze_result_t deviceGetProperties(zes_device_handle_t hDevice, zes_device_properties_t *pProperties);
virtual ze_result_t deviceGetProperties(zes_device_properties_t *pProperties) = 0;
static ze_result_t deviceGetState(zes_device_handle_t hDevice, zes_device_state_t *pState);
virtual ze_result_t deviceGetState(zes_device_state_t *pState) = 0;
static ze_result_t processesGetState(zes_device_handle_t hDevice, uint32_t *pCount, zes_process_state_t *pProcesses);
virtual ze_result_t processesGetState(uint32_t *pCount, zes_process_state_t *pProcesses) = 0;
};
} // namespace Sysman

View File

@@ -9,6 +9,7 @@
#include "shared/source/helpers/debug_helpers.h"
#include "level_zero/sysman/source/global_operations/global_operations_imp.h"
#include "level_zero/sysman/source/os_sysman.h"
#include <vector>
@@ -28,18 +29,24 @@ SysmanDeviceImp::SysmanDeviceImp(NEO::ExecutionEnvironment *executionEnvironment
pFrequencyHandleContext = new FrequencyHandleContext(pOsSysman);
pSchedulerHandleContext = new SchedulerHandleContext(pOsSysman);
pFirmwareHandleContext = new FirmwareHandleContext(pOsSysman);
pRasHandleContext = new RasHandleContext(pOsSysman);
pDiagnosticsHandleContext = new DiagnosticsHandleContext(pOsSysman);
pGlobalOperations = new GlobalOperationsImp(pOsSysman);
}
SysmanDeviceImp::~SysmanDeviceImp() {
executionEnvironment->decRefInternal();
freeResource(pSchedulerHandleContext);
freeResource(pPowerHandleContext);
freeResource(pEngineHandleContext);
freeResource(pFabricPortHandleContext);
freeResource(pMemoryHandleContext);
freeResource(pFrequencyHandleContext);
freeResource(pGlobalOperations);
freeResource(pDiagnosticsHandleContext);
freeResource(pRasHandleContext);
freeResource(pFirmwareHandleContext);
freeResource(pSchedulerHandleContext);
freeResource(pFrequencyHandleContext);
freeResource(pEngineHandleContext);
freeResource(pPowerHandleContext);
freeResource(pMemoryHandleContext);
freeResource(pFabricPortHandleContext);
freeResource(pOsSysman);
executionEnvironment->decRefInternal();
}
ze_result_t SysmanDeviceImp::init() {
@@ -50,6 +57,22 @@ ze_result_t SysmanDeviceImp::init() {
return result;
}
ze_result_t SysmanDeviceImp::deviceGetProperties(zes_device_properties_t *pProperties) {
return pGlobalOperations->deviceGetProperties(pProperties);
}
ze_result_t SysmanDeviceImp::processesGetState(uint32_t *pCount, zes_process_state_t *pProcesses) {
return pGlobalOperations->processesGetState(pCount, pProcesses);
}
ze_result_t SysmanDeviceImp::deviceReset(ze_bool_t force) {
return pGlobalOperations->reset(force);
}
ze_result_t SysmanDeviceImp::deviceGetState(zes_device_state_t *pState) {
return pGlobalOperations->deviceGetState(pState);
}
ze_result_t SysmanDeviceImp::fabricPortGet(uint32_t *pCount, zes_fabric_port_handle_t *phPort) {
return pFabricPortHandleContext->fabricPortGet(pCount, phPort);
}
@@ -78,9 +101,17 @@ ze_result_t SysmanDeviceImp::schedulerGet(uint32_t *pCount, zes_sched_handle_t *
return pSchedulerHandleContext->schedulerGet(pCount, phScheduler);
}
ze_result_t SysmanDeviceImp::rasGet(uint32_t *pCount, zes_ras_handle_t *phRas) {
return pRasHandleContext->rasGet(pCount, phRas);
}
ze_result_t SysmanDeviceImp::firmwareGet(uint32_t *pCount, zes_firmware_handle_t *phFirmware) {
return pFirmwareHandleContext->firmwareGet(pCount, phFirmware);
}
ze_result_t SysmanDeviceImp::diagnosticsGet(uint32_t *pCount, zes_diag_handle_t *phDiagnostics) {
return pDiagnosticsHandleContext->diagnosticsGet(pCount, phDiagnostics);
}
} // namespace Sysman
} // namespace L0

View File

@@ -41,20 +41,28 @@ struct SysmanDeviceImp : SysmanDevice, NEO::NonCopyableOrMovableClass {
NEO::ExecutionEnvironment *getExecutionEnvironment() const { return executionEnvironment; }
uint32_t getRootDeviceIndex() const { return rootDeviceIndex; }
GlobalOperations *pGlobalOperations = nullptr;
FabricPortHandleContext *pFabricPortHandleContext = nullptr;
MemoryHandleContext *pMemoryHandleContext = nullptr;
EngineHandleContext *pEngineHandleContext = nullptr;
SchedulerHandleContext *pSchedulerHandleContext = nullptr;
FirmwareHandleContext *pFirmwareHandleContext = nullptr;
RasHandleContext *pRasHandleContext = nullptr;
DiagnosticsHandleContext *pDiagnosticsHandleContext = nullptr;
FrequencyHandleContext *pFrequencyHandleContext = nullptr;
ze_result_t memoryGet(uint32_t *pCount, zes_mem_handle_t *phMemory) override;
ze_result_t fabricPortGet(uint32_t *pCount, zes_fabric_port_handle_t *phPort) override;
ze_result_t engineGet(uint32_t *pCount, zes_engine_handle_t *phEngine) override;
ze_result_t schedulerGet(uint32_t *pCount, zes_sched_handle_t *phScheduler) override;
FrequencyHandleContext *pFrequencyHandleContext = nullptr;
ze_result_t frequencyGet(uint32_t *pCount, zes_freq_handle_t *phFrequency) override;
ze_result_t firmwareGet(uint32_t *pCount, zes_firmware_handle_t *phFirmware) override;
ze_result_t rasGet(uint32_t *pCount, zes_ras_handle_t *phRas) override;
ze_result_t diagnosticsGet(uint32_t *pCount, zes_diag_handle_t *phFirmware) override;
ze_result_t deviceGetProperties(zes_device_properties_t *pProperties) override;
ze_result_t processesGetState(uint32_t *pCount, zes_process_state_t *pProcesses) override;
ze_result_t deviceReset(ze_bool_t force) override;
ze_result_t deviceGetState(zes_device_state_t *pState) override;
private:
NEO::ExecutionEnvironment *executionEnvironment = nullptr;

View File

@@ -0,0 +1,10 @@
#
# Copyright (C) 2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
target_sources(${TARGET_NAME} PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
)
add_subdirectories()

View File

@@ -0,0 +1,24 @@
#
# Copyright (C) 2023 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
set(L0_TESTS_SYSMAN_GLOBAL_OPERATIONS_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_global_operations.cpp
${CMAKE_CURRENT_SOURCE_DIR}/mock_global_operations.h
)
if(NEO_ENABLE_i915_PRELIM_DETECTION)
list(APPEND L0_TESTS_SYSMAN_GLOBAL_OPERATIONS_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/test_zes_global_operations_prelim.cpp
)
endif()
if(UNIX)
target_sources(${TARGET_NAME}
PRIVATE
${L0_TESTS_SYSMAN_GLOBAL_OPERATIONS_LINUX}
)
endif()

View File

@@ -0,0 +1,579 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "shared/test/common/libult/linux/drm_mock.h"
#include "shared/test/common/mocks/mock_execution_environment.h"
#include "shared/test/common/test_macros/mock_method_macros.h"
#include "level_zero/sysman/source/firmware_util/firmware_util.h"
#include "level_zero/sysman/source/global_operations/global_operations_imp.h"
#include "level_zero/sysman/source/global_operations/linux/os_global_operations_imp.h"
#include "level_zero/sysman/source/linux/fs_access.h"
#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_hw_device_id.h"
namespace L0 {
namespace ult {
const std::string vendorIntel("Intel(R) Corporation");
const std::string unknown("unknown");
const std::string intelPciId("0x8086");
const std::string deviceDir("device");
const std::string vendorFile("device/vendor");
const std::string deviceFile("device/device");
const std::string subsystemVendorFile("device/subsystem_vendor");
const std::string driverFile("device/driver");
const std::string agamaVersionFile("/sys/module/i915/agama_version");
const std::string srcVersionFile("/sys/module/i915/srcversion");
const std::string functionLevelReset("device/reset");
const std::string clientsDir("clients");
constexpr uint64_t pid1 = 1711u;
constexpr uint64_t pid2 = 1722u;
constexpr uint64_t pid3 = 1723u;
constexpr uint64_t pid4 = 1733u;
constexpr uint64_t pid6 = 1744u;
constexpr uint64_t pid7 = 1755u;
const std::string bPid4 = "<1733>";
constexpr uint64_t engineTimeSpent = 123456u;
const std::string clientId1("4");
const std::string clientId2("5");
const std::string clientId3("6");
const std::string clientId4("7");
const std::string clientId5("8");
const std::string clientId6("10");
const std::string clientId7("11");
const std::string clientId8("12");
const std::string clientId9("13");
const std::string engine0("0");
const std::string engine1("1");
const std::string engine2("2");
const std::string engine3("3");
const std::string engine6("6");
const std::string driverVersion("5.0.0-37-generic SMP mod_unload");
const std::string srcVersion("5.0.0-37");
const std::string ueventWedgedFile("/var/lib/libze_intel_gpu/wedged_file");
const std::string mockFunctionResetPath("/MOCK_FUNCTION_LEVEL_RESET_PATH");
const std::string mockDeviceDir("devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0");
const std::string mockDeviceName("/MOCK_DEVICE_NAME");
enum mockEnumListProcessCall {
DEVICE_IN_USE = 0,
DEVICE_UNUSED = 1,
RETURN_ERROR = 2
};
struct MockGlobalOperationsEngineHandleContext : public L0::Sysman::EngineHandleContext {
MockGlobalOperationsEngineHandleContext(L0::Sysman::OsSysman *pOsSysman) : EngineHandleContext(pOsSysman) {}
ADDMETHOD_NOBASE_VOIDRETURN(init, (uint32_t subDeviceCount));
};
struct MockGlobalOperationsRasHandleContext : public L0::Sysman::RasHandleContext {
MockGlobalOperationsRasHandleContext(L0::Sysman::OsSysman *pOsSysman) : RasHandleContext(pOsSysman) {}
ADDMETHOD_NOBASE_VOIDRETURN(init, (uint32_t subDeviceCount));
};
struct MockGlobalOperationsDiagnosticsHandleContext : public L0::Sysman::DiagnosticsHandleContext {
MockGlobalOperationsDiagnosticsHandleContext(L0::Sysman::OsSysman *pOsSysman) : DiagnosticsHandleContext(pOsSysman) {}
ADDMETHOD_NOBASE_VOIDRETURN(init, ());
};
struct MockGlobalOperationsFirmwareHandleContext : public L0::Sysman::FirmwareHandleContext {
MockGlobalOperationsFirmwareHandleContext(L0::Sysman::OsSysman *pOsSysman) : FirmwareHandleContext(pOsSysman) {}
ADDMETHOD_NOBASE_VOIDRETURN(init, ());
};
struct MockGlobalOperationsSysfsAccess : public L0::Sysman::SysfsAccess {
ze_result_t mockScanDirEntriesError = ZE_RESULT_SUCCESS;
ze_result_t mockReadError = ZE_RESULT_SUCCESS;
ze_result_t mockBindDeviceError = ZE_RESULT_SUCCESS;
ze_result_t mockUnbindDeviceError = ZE_RESULT_SUCCESS;
uint32_t mockCount = 0;
bool isRootSet = true;
bool mockGetScannedDir4EntriesStatus = false;
bool mockGetScannedDirPidEntriesStatus = false;
bool mockGetScannedDirPidEntriesForClientsStatus = false;
bool mockReadStatus = false;
bool mockGetValUnsignedLongStatus = false;
ze_result_t getRealPath(const std::string file, std::string &val) override {
if (file.compare(functionLevelReset) == 0) {
val = mockFunctionResetPath;
} else if (file.compare(deviceDir) == 0) {
val = mockDeviceDir;
} else {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
enum class Index {
MockSubsystemVendor,
MockDevice,
MockVendor,
MockCount
};
ze_result_t readResult = ZE_RESULT_SUCCESS;
std::string mockReadVal[static_cast<int>(Index::MockCount)] = {"0x8086", "0x3ea5", "0x8086"};
ze_result_t read(const std::string file, std::string &val) override {
if (mockReadError != ZE_RESULT_SUCCESS) {
return mockReadError;
}
if (file.compare(subsystemVendorFile) == 0) {
val = mockReadVal[static_cast<int>(Index::MockSubsystemVendor)];
} else if (file.compare(deviceFile) == 0) {
val = mockReadVal[static_cast<int>(Index::MockDevice)];
} else if (file.compare(vendorFile) == 0) {
val = mockReadVal[static_cast<int>(Index::MockVendor)];
} else if (file.compare("clients/8/pid") == 0) {
val = bPid4;
} else {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return readResult;
}
ze_result_t read(const std::string file, uint64_t &val) override {
if (mockReadStatus == true) {
if (mockCount == 0) {
mockCount++;
return getValUnsignedLongCreatedBytesSuccess(file, val);
}
else {
return ZE_RESULT_ERROR_UNKNOWN;
}
}
if (mockReadError != ZE_RESULT_SUCCESS) {
return mockReadError;
}
if (mockGetValUnsignedLongStatus == true) {
return getValUnsignedLongCreatedBytesSuccess(file, val);
}
if ((file.compare("clients/4/pid") == 0) || (file.compare("clients/5/pid") == 0)) {
val = pid1;
} else if (file.compare("clients/6/pid") == 0) {
val = pid2;
} else if (file.compare("clients/7/pid") == 0) {
val = pid3;
} else if (file.compare("clients/10/pid") == 0) {
val = pid6;
} else if (file.compare("clients/11/pid") == 0) {
val = pid7;
} else if (file.compare("clients/12/pid") == 0) {
val = pid7;
} else if (file.compare("clients/13/pid") == 0) {
val = pid7;
} else if ((file.compare("clients/4/busy/0") == 0) || (file.compare("clients/4/busy/3") == 0) ||
(file.compare("clients/5/busy/1") == 0) || (file.compare("clients/6/busy/0") == 0) ||
(file.compare("clients/8/busy/1") == 0) || (file.compare("clients/8/busy/0") == 0) ||
(file.compare("clients/13/busy/6") == 0)) {
val = engineTimeSpent;
} else if ((file.compare("clients/4/busy/1") == 0) || (file.compare("clients/4/busy/2") == 0) ||
(file.compare("clients/5/busy/0") == 0) || (file.compare("clients/5/busy/2") == 0) ||
(file.compare("clients/7/busy/0") == 0) || (file.compare("clients/7/busy/2") == 0) ||
(file.compare("clients/5/busy/3") == 0) || (file.compare("clients/6/busy/1") == 0) ||
(file.compare("clients/6/busy/2") == 0) || (file.compare("clients/6/busy/3") == 0) ||
(file.compare("clients/8/busy/2") == 0) || (file.compare("clients/8/busy/3") == 0)) {
val = 0;
} else if ((file.compare("clients/4/total_device_memory_buffer_objects/created_bytes") == 0) ||
(file.compare("clients/5/total_device_memory_buffer_objects/created_bytes") == 0) ||
(file.compare("clients/6/total_device_memory_buffer_objects/created_bytes") == 0) ||
(file.compare("clients/8/total_device_memory_buffer_objects/created_bytes") == 0) ||
(file.compare("clients/10/total_device_memory_buffer_objects/created_bytes") == 0)) {
val = 1024;
} else if ((file.compare("clients/4/total_device_memory_buffer_objects/imported_bytes") == 0) ||
(file.compare("clients/5/total_device_memory_buffer_objects/imported_bytes") == 0) ||
(file.compare("clients/6/total_device_memory_buffer_objects/imported_bytes") == 0) ||
(file.compare("clients/8/total_device_memory_buffer_objects/imported_bytes") == 0) ||
(file.compare("clients/10/total_device_memory_buffer_objects/imported_bytes") == 0)) {
val = 512;
} else if (file.compare("clients/7/total_device_memory_buffer_objects/created_bytes") == 0) {
return ZE_RESULT_ERROR_UNKNOWN;
} else if (file.compare("clients/7/total_device_memory_buffer_objects/imported_bytes") == 0) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
} else if (file.compare("clients/13/total_device_memory_buffer_objects/imported_bytes") == 0) {
return ZE_RESULT_ERROR_UNKNOWN;
} else {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getValUnsignedLongCreatedBytesSuccess(const std::string file, uint64_t &val) {
if ((file.compare("clients/4/pid") == 0) || (file.compare("clients/5/pid") == 0)) {
val = pid1;
} else if (file.compare("clients/6/pid") == 0) {
val = pid2;
} else if ((file.compare("clients/4/busy/0") == 0) || (file.compare("clients/4/busy/3") == 0) ||
(file.compare("clients/5/busy/1") == 0) || (file.compare("clients/6/busy/0") == 0) ||
(file.compare("clients/8/busy/1") == 0) || (file.compare("clients/8/busy/0") == 0)) {
val = engineTimeSpent;
} else if ((file.compare("clients/4/busy/1") == 0) || (file.compare("clients/4/busy/2") == 0) ||
(file.compare("clients/5/busy/0") == 0) || (file.compare("clients/5/busy/2") == 0) ||
(file.compare("clients/7/busy/0") == 0) || (file.compare("clients/7/busy/2") == 0) ||
(file.compare("clients/5/busy/3") == 0) || (file.compare("clients/6/busy/1") == 0) ||
(file.compare("clients/6/busy/2") == 0) || (file.compare("clients/6/busy/3") == 0) ||
(file.compare("clients/8/busy/2") == 0) || (file.compare("clients/8/busy/3") == 0)) {
val = 0;
} else if ((file.compare("clients/4/total_device_memory_buffer_objects/created_bytes") == 0) ||
(file.compare("clients/5/total_device_memory_buffer_objects/created_bytes") == 0) ||
(file.compare("clients/6/total_device_memory_buffer_objects/created_bytes") == 0) ||
(file.compare("clients/8/total_device_memory_buffer_objects/created_bytes") == 0) ||
(file.compare("clients/7/total_device_memory_buffer_objects/created_bytes") == 0)) {
val = 1024;
} else if ((file.compare("clients/4/total_device_memory_buffer_objects/imported_bytes") == 0) ||
(file.compare("clients/5/total_device_memory_buffer_objects/imported_bytes") == 0) ||
(file.compare("clients/6/total_device_memory_buffer_objects/imported_bytes") == 0) ||
(file.compare("clients/8/total_device_memory_buffer_objects/imported_bytes") == 0)) {
val = 512;
} else if (file.compare("clients/7/total_device_memory_buffer_objects/imported_bytes") == 0) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
} else {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getScannedDir4Entries(const std::string path, std::vector<std::string> &list) {
if (path.compare(clientsDir) == 0) {
list.push_back(clientId1);
list.push_back(clientId2);
list.push_back(clientId3);
list.push_back(clientId4);
list.push_back(clientId5);
list.push_back(clientId6);
} else if ((path.compare("clients/4/busy") == 0) || (path.compare("clients/5/busy") == 0) ||
(path.compare("clients/6/busy") == 0) || (path.compare("clients/7/busy") == 0) ||
(path.compare("clients/8/busy") == 0)) {
list.push_back(engine0);
list.push_back(engine1);
list.push_back(engine2);
list.push_back(engine3);
} else {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t scanDirEntries(const std::string path, std::vector<std::string> &list) override {
if (mockScanDirEntriesError != ZE_RESULT_SUCCESS) {
return mockScanDirEntriesError;
}
if (mockGetScannedDir4EntriesStatus == true) {
return getScannedDir4Entries(path, list);
}
if (mockGetScannedDirPidEntriesStatus == true) {
return getScannedDirPidEntries(path, list);
}
if (mockGetScannedDirPidEntriesForClientsStatus == true) {
return getScannedDirPidEntiresForClients(path, list);
}
if (path.compare(clientsDir) == 0) {
list.push_back(clientId1);
list.push_back(clientId2);
list.push_back(clientId3);
list.push_back(clientId5);
list.push_back(clientId6);
list.push_back(clientId7);
} else if ((path.compare("clients/4/busy") == 0) || (path.compare("clients/5/busy") == 0) ||
(path.compare("clients/6/busy") == 0) || (path.compare("clients/8/busy") == 0)) {
list.push_back(engine0);
list.push_back(engine1);
list.push_back(engine2);
list.push_back(engine3);
} else {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getScannedDirPidEntries(const std::string path, std::vector<std::string> &list) {
if (path.compare(clientsDir) == 0) {
list.push_back(clientId8);
} else if (path.compare("clients/12/busy") == 0) {
return ZE_RESULT_ERROR_UNKNOWN;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t getScannedDirPidEntiresForClients(const std::string path, std::vector<std::string> &list) {
if (path.compare(clientsDir) == 0) {
list.push_back(clientId9);
} else if (path.compare("clients/13/busy") == 0) {
list.push_back(engine6);
}
return ZE_RESULT_SUCCESS;
}
bool isMyDeviceFile(const std::string dev) override {
if (dev.compare(mockDeviceName) == 0) {
return true;
}
return false;
}
bool isRootUser() override {
if (isRootSet == true) {
return true;
} else {
return false;
}
}
ze_result_t unbindDevice(const std::string device) override {
if (mockUnbindDeviceError != ZE_RESULT_SUCCESS) {
return mockUnbindDeviceError;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t bindDevice(const std::string device) override {
if (mockBindDeviceError != ZE_RESULT_SUCCESS) {
return mockBindDeviceError;
}
return ZE_RESULT_SUCCESS;
}
MockGlobalOperationsSysfsAccess() = default;
ADDMETHOD_NOBASE(fileExists, bool, true, (const std::string file));
};
struct MockGlobalOperationsProcfsAccess : public L0::Sysman::ProcfsAccess {
const ::pid_t extraPid = 4;
const int extraFd = 5;
std::vector<::pid_t> pidList = {1, 2, 3};
std::vector<int> fdList = {0, 1, 2};
::pid_t ourDevicePid = 0;
int ourDeviceFd = 0;
std::vector<mockEnumListProcessCall> mockListProcessCall{};
std::vector<bool> isRepeated{};
ze_result_t listProcessesResult = ZE_RESULT_SUCCESS;
uint32_t listProcessCalled = 0u;
ze_result_t listProcesses(std::vector<::pid_t> &list) override {
listProcessCalled++;
list = pidList;
if (!mockListProcessCall.empty()) {
mockEnumListProcessCall mockListProcessCallValue = mockListProcessCall.front();
if (mockListProcessCallValue == mockEnumListProcessCall::DEVICE_IN_USE) {
if (ourDevicePid) {
list.push_back(ourDevicePid);
}
}
else if (mockListProcessCallValue == mockEnumListProcessCall::DEVICE_UNUSED) {
}
else if (mockListProcessCallValue == mockEnumListProcessCall::RETURN_ERROR) {
listProcessesResult = ZE_RESULT_ERROR_NOT_AVAILABLE;
}
if (!isRepeated.empty()) {
if (isRepeated.front() == false) {
mockListProcessCall.erase(mockListProcessCall.begin());
isRepeated.erase(isRepeated.begin());
}
}
}
return listProcessesResult;
}
::pid_t myProcessId() override {
return ::getpid();
}
ze_result_t mockGetFileDescriptorsError = ZE_RESULT_SUCCESS;
ze_result_t getFileDescriptorsResult = ZE_RESULT_SUCCESS;
ze_result_t getFileDescriptors(const ::pid_t pid, std::vector<int> &list) override {
list.clear();
if (mockGetFileDescriptorsError != ZE_RESULT_SUCCESS) {
getFileDescriptorsResult = mockGetFileDescriptorsError;
mockGetFileDescriptorsError = ZE_RESULT_SUCCESS;
return getFileDescriptorsResult;
}
list = fdList;
if (ourDevicePid == pid) {
list.push_back(ourDeviceFd);
}
return getFileDescriptorsResult;
}
ze_result_t mockGetFileNameError = ZE_RESULT_SUCCESS;
ze_result_t getFileNameResult = ZE_RESULT_SUCCESS;
ze_result_t getFileName(const ::pid_t pid, const int fd, std::string &val) override {
if (mockGetFileNameError != ZE_RESULT_SUCCESS) {
return mockGetFileNameError;
}
if (pid == ourDevicePid && fd == ourDeviceFd) {
val = mockDeviceName;
} else {
// return fake filenames for other file descriptors
val = std::string("/FILENAME") + std::to_string(fd);
}
return getFileNameResult;
}
bool isAlive(const ::pid_t pid) override {
if (pid == ourDevicePid) {
return true;
}
return false;
}
bool mockNoKill = false;
void kill(const ::pid_t pid) override {
if (mockNoKill == true) {
return;
}
ourDevicePid = 0;
}
MockGlobalOperationsProcfsAccess() = default;
};
struct MockGlobalOperationsFsAccess : public L0::Sysman::FsAccess {
ze_result_t mockReadError = ZE_RESULT_SUCCESS;
ze_result_t readResult = ZE_RESULT_ERROR_NOT_AVAILABLE;
std::string mockReadVal = "";
ze_result_t read(const std::string file, std::string &val) override {
if (mockReadError != ZE_RESULT_SUCCESS) {
return mockReadError;
}
if (mockReadVal == srcVersion) {
if (file.compare(srcVersionFile) == 0) {
val = mockReadVal;
readResult = ZE_RESULT_SUCCESS;
return readResult;
}
} else if (mockReadVal == driverVersion) {
if (file.compare(agamaVersionFile) == 0) {
val = mockReadVal;
readResult = ZE_RESULT_SUCCESS;
return readResult;
}
} else {
readResult = ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return readResult;
}
ze_result_t mockWriteError = ZE_RESULT_SUCCESS;
ze_result_t writeResult = ZE_RESULT_SUCCESS;
ze_result_t write(const std::string file, const std::string val) override {
if (mockWriteError != ZE_RESULT_SUCCESS) {
return mockWriteError;
}
return writeResult;
}
ADDMETHOD_NOBASE(canWrite, ze_result_t, ZE_RESULT_SUCCESS, (const std::string file));
MockGlobalOperationsFsAccess() = default;
};
struct MockGlobalOpsFwInterface : public L0::Sysman::FirmwareUtil {
ze_result_t mockIfrError = ZE_RESULT_SUCCESS;
ze_result_t mockIfrResult = ZE_RESULT_SUCCESS;
bool mockIfrStatus = true;
ze_result_t fwIfrApplied(bool &ifrStatus) override {
if (mockIfrError != ZE_RESULT_SUCCESS) {
return mockIfrError;
}
ifrStatus = mockIfrStatus;
return mockIfrResult;
}
MockGlobalOpsFwInterface() = default;
ADDMETHOD_NOBASE(fwDeviceInit, ze_result_t, ZE_RESULT_SUCCESS, (void));
ADDMETHOD_NOBASE(getFirstDevice, ze_result_t, ZE_RESULT_SUCCESS, (igsc_device_info * info));
ADDMETHOD_NOBASE(getFwVersion, ze_result_t, ZE_RESULT_SUCCESS, (std::string fwType, std::string &firmwareVersion));
ADDMETHOD_NOBASE(flashFirmware, ze_result_t, ZE_RESULT_SUCCESS, (std::string fwType, void *pImage, uint32_t size));
ADDMETHOD_NOBASE(fwSupportedDiagTests, ze_result_t, ZE_RESULT_SUCCESS, (std::vector<std::string> & supportedDiagTests));
ADDMETHOD_NOBASE(fwRunDiagTests, ze_result_t, ZE_RESULT_SUCCESS, (std::string & osDiagType, zes_diag_result_t *pResult));
ADDMETHOD_NOBASE(fwGetMemoryErrorCount, ze_result_t, ZE_RESULT_SUCCESS, (zes_ras_error_type_t category, uint32_t subDeviceCount, uint32_t subDeviceId, uint64_t &count));
ADDMETHOD_NOBASE(fwGetEccConfig, ze_result_t, ZE_RESULT_SUCCESS, (uint8_t * currentState, uint8_t *pendingState));
ADDMETHOD_NOBASE(fwSetEccConfig, ze_result_t, ZE_RESULT_SUCCESS, (uint8_t newState, uint8_t *currentState, uint8_t *pendingState));
ADDMETHOD_NOBASE_VOIDRETURN(getDeviceSupportedFwTypes, (std::vector<std::string> & fwTypes));
ADDMETHOD_NOBASE_VOIDRETURN(fwGetMemoryHealthIndicator, (zes_mem_health_t * health));
};
struct MockGlobalOpsLinuxSysmanImp : public L0::Sysman::LinuxSysmanImp {
using LinuxSysmanImp::pFsAccess;
using LinuxSysmanImp::pProcfsAccess;
using LinuxSysmanImp::pSysfsAccess;
MockGlobalOpsLinuxSysmanImp(L0::Sysman::SysmanDeviceImp *pParentSysmanDeviceImp) : LinuxSysmanImp(pParentSysmanDeviceImp) {}
std::vector<int> fdList = {0, 1, 2};
::pid_t ourDevicePid = 0;
int ourDeviceFd = 0;
ze_result_t mockError = ZE_RESULT_SUCCESS;
ze_result_t mockInitDeviceError = ZE_RESULT_SUCCESS;
void getPidFdsForOpenDevice(L0::Sysman::ProcfsAccess *pProcfsAccess, L0::Sysman::SysfsAccess *pSysfsAccess, const ::pid_t pid, std::vector<int> &deviceFds) override {
if (ourDevicePid) {
deviceFds.push_back(ourDeviceFd);
}
}
ze_result_t osWarmReset() override {
if (mockError != ZE_RESULT_SUCCESS) {
return mockError;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t osColdReset() override {
if (mockError != ZE_RESULT_SUCCESS) {
return mockError;
}
return ZE_RESULT_SUCCESS;
}
void setMockError(ze_result_t result) {
mockError = result;
}
void setMockInitDeviceError(ze_result_t result) {
mockInitDeviceError = result;
}
};
constexpr int mockFdGlobalOperations = 33;
class DrmGlobalOpsMock : public Drm {
public:
DrmGlobalOpsMock(RootDeviceEnvironment &rootDeviceEnvironment) : Drm(std::make_unique<MockSysmanHwDeviceIdDrm>(mockFdGlobalOperations, ""), rootDeviceEnvironment) {}
using Drm::setupIoctlHelper;
int ioctlRetVal = 0;
int ioctlErrno = 0;
int ioctl(DrmIoctl request, void *arg) override {
return ioctlRetVal;
}
int getErrno() override { return ioctlErrno; }
};
class PublicLinuxGlobalOperationsImp : public L0::Sysman::LinuxGlobalOperationsImp {
public:
using LinuxGlobalOperationsImp::pLinuxSysmanImp;
using LinuxGlobalOperationsImp::resetTimeout;
};
} // namespace ult
} // namespace L0

View File

@@ -0,0 +1,942 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/os_interface/linux/pci_path.h"
#include "shared/test/common/helpers/ult_hw_config.h"
#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h"
#include "level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h"
#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h"
#include <fcntl.h>
#include <sys/stat.h>
namespace L0 {
namespace ult {
constexpr uint64_t memSize1 = 2048;
constexpr uint64_t memSize2 = 1024;
constexpr uint64_t memSize4 = 1024;
constexpr uint64_t memSize6 = 1024;
constexpr uint64_t memSize7 = 0;
constexpr uint64_t sharedMemSize1 = 1024;
constexpr uint64_t sharedMemSize2 = 512;
constexpr uint64_t sharedMemSize4 = 512;
constexpr uint64_t sharedMemSize6 = 512;
constexpr uint64_t sharedMemSize7 = 0;
// In mock function getValUnsignedLong, we have set the engines used as 0, 3 and 1.
// Hence, expecting 28 as engine field because 28 in binary would be 00011100
// This indicates bit number 2, 3 and 4 are set, thus this indicates, this process
// used ZES_ENGINE_TYPE_FLAG_3D, ZES_ENGINE_TYPE_FLAG_MEDIA and ZES_ENGINE_TYPE_FLAG_DMA
// Their corresponding mapping with i915 engine numbers are 0, 3 and 1 respectively.
constexpr int64_t engines1 = 28u;
// 4 in binary 0100, as 2nd bit is set, hence it indicates, process used ZES_ENGINE_TYPE_FLAG_3D
// Corresponding i915 mapped value in mocked getValUnsignedLong() is 0.
constexpr int64_t engines2 = 4u;
constexpr int64_t engines4 = 20u;
constexpr int64_t engines6 = 1u;
constexpr int64_t engines7 = 1u;
constexpr uint32_t totalProcessStates = 5u; // Three process States for three pids
constexpr uint32_t totalProcessStatesForFaultyClients = 3u;
class SysmanGlobalOperationsFixture : public SysmanDeviceFixture {
protected:
std::unique_ptr<MockGlobalOperationsEngineHandleContext> pEngineHandleContext;
std::unique_ptr<MockGlobalOperationsDiagnosticsHandleContext> pDiagnosticsHandleContext;
std::unique_ptr<MockGlobalOperationsFirmwareHandleContext> pFirmwareHandleContext;
std::unique_ptr<MockGlobalOperationsRasHandleContext> pRasHandleContext;
std::unique_ptr<MockGlobalOperationsSysfsAccess> pSysfsAccess;
std::unique_ptr<MockGlobalOperationsProcfsAccess> pProcfsAccess;
std::unique_ptr<MockGlobalOperationsFsAccess> pFsAccess;
L0::Sysman::EngineHandleContext *pEngineHandleContextOld = nullptr;
L0::Sysman::DiagnosticsHandleContext *pDiagnosticsHandleContextOld = nullptr;
L0::Sysman::FirmwareHandleContext *pFirmwareHandleContextOld = nullptr;
L0::Sysman::RasHandleContext *pRasHandleContextOld = nullptr;
L0::Sysman::SysfsAccess *pSysfsAccessOld = nullptr;
L0::Sysman::ProcfsAccess *pProcfsAccessOld = nullptr;
L0::Sysman::FsAccess *pFsAccessOld = nullptr;
L0::Sysman::LinuxSysmanImp *pLinuxSysmanImpOld = nullptr;
L0::Sysman::OsGlobalOperations *pOsGlobalOperationsPrev = nullptr;
L0::Sysman::GlobalOperations *pGlobalOperationsPrev = nullptr;
L0::Sysman::GlobalOperationsImp *pGlobalOperationsImp;
L0::Sysman::SysmanDeviceImp *device = nullptr;
void SetUp() override {
SysmanDeviceFixture::SetUp();
pEngineHandleContextOld = pSysmanDeviceImp->pEngineHandleContext;
pDiagnosticsHandleContextOld = pSysmanDeviceImp->pDiagnosticsHandleContext;
pFirmwareHandleContextOld = pSysmanDeviceImp->pFirmwareHandleContext;
pRasHandleContextOld = pSysmanDeviceImp->pRasHandleContext;
pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess;
pProcfsAccessOld = pLinuxSysmanImp->pProcfsAccess;
pFsAccessOld = pLinuxSysmanImp->pFsAccess;
pLinuxSysmanImpOld = pLinuxSysmanImp;
pEngineHandleContext = std::make_unique<MockGlobalOperationsEngineHandleContext>(pOsSysman);
pSysfsAccess = std::make_unique<MockGlobalOperationsSysfsAccess>();
pProcfsAccess = std::make_unique<MockGlobalOperationsProcfsAccess>();
pFsAccess = std::make_unique<MockGlobalOperationsFsAccess>();
pDiagnosticsHandleContext = std::make_unique<MockGlobalOperationsDiagnosticsHandleContext>(pOsSysman);
pFirmwareHandleContext = std::make_unique<MockGlobalOperationsFirmwareHandleContext>(pOsSysman);
pRasHandleContext = std::make_unique<MockGlobalOperationsRasHandleContext>(pOsSysman);
auto pDrmLocal = new DrmGlobalOpsMock(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()));
pDrmLocal->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterfaceLocal = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterfaceLocal->setDriverModel(std::unique_ptr<DrmGlobalOpsMock>(pDrmLocal));
pSysmanDeviceImp->pEngineHandleContext = pEngineHandleContext.get();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
pLinuxSysmanImp->pProcfsAccess = pProcfsAccess.get();
pLinuxSysmanImp->pFsAccess = pFsAccess.get();
pSysmanDeviceImp->pDiagnosticsHandleContext = pDiagnosticsHandleContext.get();
pSysmanDeviceImp->pFirmwareHandleContext = pFirmwareHandleContext.get();
pSysmanDeviceImp->pRasHandleContext = pRasHandleContext.get();
pFsAccess->mockReadVal = driverVersion;
pGlobalOperationsImp = static_cast<L0::Sysman::GlobalOperationsImp *>(pSysmanDeviceImp->pGlobalOperations);
pOsGlobalOperationsPrev = pGlobalOperationsImp->pOsGlobalOperations;
pGlobalOperationsImp->pOsGlobalOperations = nullptr;
device = pSysmanDeviceImp;
}
void TearDown() override {
if (nullptr != pGlobalOperationsImp->pOsGlobalOperations) {
delete pGlobalOperationsImp->pOsGlobalOperations;
}
pGlobalOperationsImp->pOsGlobalOperations = pOsGlobalOperationsPrev;
pGlobalOperationsImp = nullptr;
pSysmanDeviceImp->pEngineHandleContext = pEngineHandleContextOld;
pSysmanDeviceImp->pDiagnosticsHandleContext = pDiagnosticsHandleContextOld;
pSysmanDeviceImp->pFirmwareHandleContext = pFirmwareHandleContextOld;
pSysmanDeviceImp->pRasHandleContext = pRasHandleContextOld;
pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld;
pLinuxSysmanImp->pProcfsAccess = pProcfsAccessOld;
pLinuxSysmanImp->pFsAccess = pFsAccessOld;
SysmanDeviceFixture::TearDown();
}
void initGlobalOps() {
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
}
};
class SysmanGlobalOperationsIntegratedFixture : public SysmanGlobalOperationsFixture {
void SetUp() override {
SysmanGlobalOperationsFixture::SetUp();
auto mockHardwareInfo = device->getHardwareInfo();
// auto mockHardwareInfo = neoDevice->getHardwareInfo();
mockHardwareInfo.capabilityTable.isIntegratedDevice = true;
device->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->setHwInfoAndInitHelpers(&mockHardwareInfo);
}
void TearDown() override {
SysmanGlobalOperationsFixture::TearDown();
}
};
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhenCallingzesGlobalOperationsGetPropertiesThenVerifyValidPropertiesAreReturned) {
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
std::map<std::string, std::string> fileNameLinkMap = {
{"/sys/dev/char/226:128", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8a:00.0/drm/renderD128"},
{"/sys/class/intel_pmt/telem1", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem1/"},
{"/sys/class/intel_pmt/telem2", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem2/"},
};
auto it = fileNameLinkMap.find(std::string(path));
if (it != fileNameLinkMap.end()) {
std::memcpy(buf, it->second.c_str(), it->second.size());
return static_cast<int>(it->second.size());
}
return -1;
});
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int {
std::vector<std::string> supportedFiles = {
"/sys/class/intel_pmt/telem1/guid",
"/sys/class/intel_pmt/telem1/offset",
"/sys/class/intel_pmt/telem1/telem",
};
auto itr = std::find(supportedFiles.begin(), supportedFiles.end(), std::string(pathname));
if (itr != supportedFiles.end()) {
// skipping "0"
return static_cast<int>(std::distance(supportedFiles.begin(), itr)) + 1;
}
return 0;
});
VariableBackup<decltype(SysCalls::sysCallsPread)> mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
std::vector<std::pair<std::string, std::string>> supportedFiles = {
{"/sys/class/intel_pmt/telem1/guid", "0x41fe79a5\n"},
{"/sys/class/intel_pmt/telem1/offset", "0\n"},
{"/sys/class/intel_pmt/telem1/telem", "dummy"},
};
if ((--fd >= 0) && (fd < static_cast<int>(supportedFiles.size()))) {
if (supportedFiles[fd].second == "dummy") {
if (count == sizeof(uint64_t)) {
uint64_t data = 0x3e8c9dfe1c2e4d5c;
memcpy(buf, &data, sizeof(data));
return count;
} else {
// Board number will be in ASCII format, Expected board number should be decoded value
// i.e 0821VPTW910091000821VPTW91009100 for data provided below.
uint64_t data[] = {0x5754505631323830, 0x3030313930303139, 0x5754505631323830, 0x3030313930303139};
memcpy(buf, &data, sizeof(data));
return count;
}
}
memcpy(buf, supportedFiles[fd].second.c_str(), supportedFiles[fd].second.size());
return count;
}
return -1;
});
pLinuxSysmanImp->rootPath = NEO::getPciRootPath(pLinuxSysmanImp->getDrm()->getFileDescriptor()).value_or("");
zes_device_properties_t properties;
const std::string expectedSerialNumber("0x3e8c9dfe1c2e4d5c");
const std::string expectedBoardNumber("0821VPTW910091000821VPTW91009100");
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(properties.numSubdevices, 0u);
EXPECT_TRUE(0 == expectedBoardNumber.compare(properties.boardNumber));
EXPECT_TRUE(0 == vendorIntel.compare(properties.brandName));
EXPECT_TRUE(0 == driverVersion.compare(properties.driverVersion));
std::stringstream expectedModelName;
expectedModelName << "Intel(R) Graphics";
expectedModelName << " [0x" << std::hex << std::setw(4) << std::setfill('0') << device->getHardwareInfo().platform.usDeviceID << "]";
EXPECT_TRUE(0 == expectedModelName.str().compare(properties.modelName));
EXPECT_TRUE(0 == expectedSerialNumber.compare(properties.serialNumber));
EXPECT_TRUE(0 == vendorIntel.compare(properties.vendorName));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleAndReadTelemOffsetFailsWhenCallingzesGlobalOperationsGetPropertiesThenInvalidSerialNumberAndBoardNumberAreReturned) {
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
std::map<std::string, std::string> fileNameLinkMap = {
{"/sys/dev/char/226:128", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8a:00.0/drm/renderD128"},
{"/sys/class/intel_pmt/telem1", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem1/"},
{"/sys/class/intel_pmt/telem2", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem2/"},
};
auto it = fileNameLinkMap.find(std::string(path));
if (it != fileNameLinkMap.end()) {
std::memcpy(buf, it->second.c_str(), it->second.size());
return static_cast<int>(it->second.size());
}
return -1;
});
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int {
std::vector<std::string> supportedFiles = {
"/sys/class/intel_pmt/telem1/guid",
"/sys/class/intel_pmt/telem1/offset",
"/sys/class/intel_pmt/telem1/telem",
};
auto itr = std::find(supportedFiles.begin(), supportedFiles.end(), std::string(pathname));
if (itr != supportedFiles.end()) {
if (std::string(pathname) == "/sys/class/intel_pmt/telem1/offset") {
return 0;
}
return static_cast<int>(std::distance(supportedFiles.begin(), itr)) + 1;
}
return 0;
});
VariableBackup<decltype(SysCalls::sysCallsPread)> mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
std::vector<std::pair<std::string, std::string>> supportedFiles = {
{"/sys/class/intel_pmt/telem1/guid", "0x41fe79a5\n"},
{"/sys/class/intel_pmt/telem1/offset", "0\n"},
{"/sys/class/intel_pmt/telem1/telem", "dummy"},
};
if ((--fd >= 0) && (fd < static_cast<int>(supportedFiles.size()))) {
if (supportedFiles[fd].second == "dummy") {
uint64_t data = 0x3e8c9dfe1c2e4d5c;
memcpy(buf, &data, sizeof(data));
return count;
}
memcpy(buf, supportedFiles[fd].second.c_str(), supportedFiles[fd].second.size());
return count;
}
return -1;
});
zes_device_properties_t properties;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.serialNumber));
EXPECT_TRUE(0 == unknown.compare(properties.boardNumber));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleAndInvalidGuidWhenCallingzesGlobalOperationsGetPropertiesThenInvalidSerialNumberAndBoardNumberAreReturned) {
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
std::map<std::string, std::string> fileNameLinkMap = {
{"/sys/dev/char/226:128", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8a:00.0/drm/renderD128"},
{"/sys/class/intel_pmt/telem1", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem1/"},
{"/sys/class/intel_pmt/telem2", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem2/"},
};
auto it = fileNameLinkMap.find(std::string(path));
if (it != fileNameLinkMap.end()) {
std::memcpy(buf, it->second.c_str(), it->second.size());
return static_cast<int>(it->second.size());
}
return -1;
});
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int {
std::vector<std::string> supportedFiles = {
"/sys/class/intel_pmt/telem1/guid",
"/sys/class/intel_pmt/telem1/offset",
"/sys/class/intel_pmt/telem1/telem",
};
auto itr = std::find(supportedFiles.begin(), supportedFiles.end(), std::string(pathname));
if (itr != supportedFiles.end()) {
return static_cast<int>(std::distance(supportedFiles.begin(), itr)) + 1;
}
return 0;
});
VariableBackup<decltype(SysCalls::sysCallsPread)> mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
std::vector<std::pair<std::string, std::string>> supportedFiles = {
{"/sys/class/intel_pmt/telem1/guid", "Invalidguid\n"},
{"/sys/class/intel_pmt/telem1/offset", "0\n"},
{"/sys/class/intel_pmt/telem1/telem", "dummy"},
};
if ((--fd >= 0) && (fd < static_cast<int>(supportedFiles.size()))) {
if (supportedFiles[fd].second == "dummy") {
uint64_t data = 0x3e8c9dfe1c2e4d5c;
memcpy(buf, &data, sizeof(data));
return count;
}
memcpy(buf, supportedFiles[fd].second.c_str(), supportedFiles[fd].second.size());
return count;
}
return -1;
});
zes_device_properties_t properties;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.serialNumber));
EXPECT_TRUE(0 == unknown.compare(properties.boardNumber));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleAndPpinandBoardNumberOffsetAreAbsentWhenCallingzesGlobalOperationsGetPropertiesThenInvalidSerialNumberAndBoardNumberAreReturned) {
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
std::map<std::string, std::string> fileNameLinkMap = {
{"/sys/dev/char/226:128", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8a:00.0/drm/renderD128"},
{"/sys/class/intel_pmt/telem1", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem1/"},
{"/sys/class/intel_pmt/telem2", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem2/"},
};
auto it = fileNameLinkMap.find(std::string(path));
if (it != fileNameLinkMap.end()) {
std::memcpy(buf, it->second.c_str(), it->second.size());
return static_cast<int>(it->second.size());
}
return -1;
});
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int {
std::vector<std::string> supportedFiles = {
"/sys/class/intel_pmt/telem1/guid",
"/sys/class/intel_pmt/telem1/offset",
"/sys/class/intel_pmt/telem1/telem",
};
auto itr = std::find(supportedFiles.begin(), supportedFiles.end(), std::string(pathname));
if (itr != supportedFiles.end()) {
return static_cast<int>(std::distance(supportedFiles.begin(), itr)) + 1;
}
return 0;
});
VariableBackup<decltype(SysCalls::sysCallsPread)> mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
std::vector<std::pair<std::string, std::string>> supportedFiles = {
{"/sys/class/intel_pmt/telem1/guid", "0xb15a0edd\n"},
{"/sys/class/intel_pmt/telem1/offset", "0\n"},
{"/sys/class/intel_pmt/telem1/telem", "dummy"},
};
if ((--fd >= 0) && (fd < static_cast<int>(supportedFiles.size()))) {
if (supportedFiles[fd].second == "dummy") {
uint64_t data = 0x3e8c9dfe1c2e4d5c;
memcpy(buf, &data, sizeof(data));
return count;
}
memcpy(buf, supportedFiles[fd].second.c_str(), supportedFiles[fd].second.size());
return count;
}
return -1;
});
zes_device_properties_t properties;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.serialNumber));
EXPECT_TRUE(0 == unknown.compare(properties.boardNumber));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleAndReadTelemDataFailsWhenCallingzesGlobalOperationsGetPropertiesThenInvalidSerialNumberAndBoardNumberAreReturned) {
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
std::map<std::string, std::string> fileNameLinkMap = {
{"/sys/dev/char/226:128", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8a:00.0/drm/renderD128"},
{"/sys/class/intel_pmt/telem1", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem1/"},
{"/sys/class/intel_pmt/telem2", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem2/"},
};
auto it = fileNameLinkMap.find(std::string(path));
if (it != fileNameLinkMap.end()) {
std::memcpy(buf, it->second.c_str(), it->second.size());
return static_cast<int>(it->second.size());
}
return -1;
});
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int {
std::vector<std::string> supportedFiles = {
"/sys/class/intel_pmt/telem1/guid",
"/sys/class/intel_pmt/telem1/offset",
"/sys/class/intel_pmt/telem1/telem",
};
auto itr = std::find(supportedFiles.begin(), supportedFiles.end(), std::string(pathname));
if (itr != supportedFiles.end()) {
return static_cast<int>(std::distance(supportedFiles.begin(), itr)) + 1;
}
return 0;
});
VariableBackup<decltype(SysCalls::sysCallsPread)> mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
std::vector<std::pair<std::string, std::string>> supportedFiles = {
{"/sys/class/intel_pmt/telem1/guid", "0x41fe79a5\n"},
{"/sys/class/intel_pmt/telem1/offset", "0\n"},
{"/sys/class/intel_pmt/telem1/telem", "dummy"},
};
if ((--fd >= 0) && (fd < static_cast<int>(supportedFiles.size()))) {
if (supportedFiles[fd].first == "/sys/class/intel_pmt/telem1/telem") {
return 0;
}
memcpy(buf, supportedFiles[fd].second.c_str(), supportedFiles[fd].second.size());
return count;
}
return -1;
});
zes_device_properties_t properties;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.serialNumber));
EXPECT_TRUE(0 == unknown.compare(properties.boardNumber));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleAndOpenSysCallFailsWhenCallingzesGlobalOperationsGetPropertiesThenInvalidSerialNumberAndBoardNumberAreReturned) {
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
std::map<std::string, std::string> fileNameLinkMap = {
{"/sys/dev/char/226:128", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8a:00.0/drm/renderD128"},
{"/sys/class/intel_pmt/telem1", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem1/"},
{"/sys/class/intel_pmt/telem2", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:01.0/0000:8c:00.0/intel-dvsec-2.1.auto/intel_pmt/telem2/"},
};
auto it = fileNameLinkMap.find(std::string(path));
if (it != fileNameLinkMap.end()) {
std::memcpy(buf, it->second.c_str(), it->second.size());
return static_cast<int>(it->second.size());
}
return -1;
});
VariableBackup<decltype(NEO::SysCalls::sysCallsOpen)> mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int {
return 0;
});
zes_device_properties_t properties;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.serialNumber));
EXPECT_TRUE(0 == unknown.compare(properties.boardNumber));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleAndTelemNodeReadLinkFailsWhenCallingzesGlobalOperationsGetPropertiesThenVerifyInvalidSerialNumberAndBoardNumberAreReturned) {
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
std::map<std::string, std::string> fileNameLinkMap = {
{"/sys/dev/char/226:128", "../../devices/pci0000:89/0000:89:02.0/0000:8a:00.0/0000:8b:02.0/0000:8a:00.0/drm/renderD128"},
};
auto it = fileNameLinkMap.find(std::string(path));
if (it != fileNameLinkMap.end()) {
std::memcpy(buf, it->second.c_str(), it->second.size());
return static_cast<int>(it->second.size());
}
return -1;
});
zes_device_properties_t properties;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.serialNumber));
EXPECT_TRUE(0 == unknown.compare(properties.boardNumber));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleAndReadLinkFailsWhenCallingzesGlobalOperationsGetPropertiesThenVerifyInvalidSerialNumberAndBoardNumberAreReturned) {
VariableBackup<decltype(NEO::SysCalls::sysCallsReadlink)> mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int {
return -1;
});
zes_device_properties_t properties;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.serialNumber));
EXPECT_TRUE(0 == unknown.compare(properties.boardNumber));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhenCallingzesDeviceGetPropertiesForCheckingDriverVersionWhenAgmaFileIsAbsentThenVerifyzesDeviceGetPropertiesCallSucceeds) {
zes_device_properties_t properties;
std::string test;
test = srcVersion;
pFsAccess->mockReadVal = srcVersion;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == test.compare(properties.driverVersion));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhenCallingzesDeviceGetPropertiesForCheckingDriverVersionWhenAgmaFileAndSrcFileIsAbsentThenVerifyzesDeviceGetPropertiesCallSucceeds) {
zes_device_properties_t properties;
pFsAccess->mockReadError = ZE_RESULT_ERROR_NOT_AVAILABLE;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.driverVersion));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhenCallingzesDeviceGetPropertiesForCheckingDriverVersionWhenDriverVersionFileIsNotAvaliableThenVerifyzesDeviceGetPropertiesCallSucceeds) {
zes_device_properties_t properties;
pFsAccess->mockReadError = ZE_RESULT_ERROR_NOT_AVAILABLE;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.driverVersion));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhenCallingzesDeviceGetPropertiesForCheckingDriverVersionWhenDriverVersionFileReadFailsThenVerifyzesDeviceGetPropertiesCallSucceeds) {
zes_device_properties_t properties;
pFsAccess->mockReadError = ZE_RESULT_ERROR_UNKNOWN;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.driverVersion));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhenCallingzesDeviceGetPropertiesForCheckingDevicePropertiesWhenVendorIsUnKnownThenVerifyzesDeviceGetPropertiesCallSucceeds) {
pSysfsAccess->mockReadVal[static_cast<int>(MockGlobalOperationsSysfsAccess::Index::MockSubsystemVendor)] = "0xa086";
pSysfsAccess->mockReadVal[static_cast<int>(MockGlobalOperationsSysfsAccess::Index::MockVendor)] = "0x1806"; // Unknown Vendor id
zes_device_properties_t properties;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.vendorName));
EXPECT_TRUE(0 == unknown.compare(properties.brandName));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhenCallingzesDeviceGetPropertiesForCheckingDriverVersionWhenAccessingAgamaFileOrSrcFileGotPermissionDeniedThenVerifyzesDeviceGetPropertiesCallSucceeds) {
zes_device_properties_t properties;
pFsAccess->mockReadError = ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS;
ze_result_t result = zesDeviceGetProperties(device, &properties);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(0 == unknown.compare(properties.driverVersion));
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileRetrievingInformationAboutHostProcessesUsingDeviceThenSuccessIsReturned) {
uint32_t count = 0;
ASSERT_EQ(ZE_RESULT_SUCCESS, zesDeviceProcessesGetState(device, &count, nullptr));
EXPECT_EQ(count, totalProcessStates);
std::vector<zes_process_state_t> processes(count);
ASSERT_EQ(ZE_RESULT_SUCCESS, zesDeviceProcessesGetState(device, &count, processes.data()));
EXPECT_EQ(processes[0].processId, pid1);
EXPECT_EQ(processes[0].engines, engines1);
EXPECT_EQ(processes[0].memSize, memSize1);
EXPECT_EQ(processes[0].sharedSize, sharedMemSize1);
EXPECT_EQ(processes[1].processId, pid2);
EXPECT_EQ(processes[1].engines, engines2);
EXPECT_EQ(processes[1].memSize, memSize2);
EXPECT_EQ(processes[1].sharedSize, sharedMemSize2);
EXPECT_EQ(processes[2].processId, pid4);
EXPECT_EQ(processes[2].engines, engines4);
EXPECT_EQ(processes[2].memSize, memSize4);
EXPECT_EQ(processes[2].sharedSize, sharedMemSize4);
EXPECT_EQ(processes[3].processId, pid6);
EXPECT_EQ(processes[3].engines, engines6);
EXPECT_EQ(processes[3].memSize, memSize6);
EXPECT_EQ(processes[3].sharedSize, sharedMemSize6);
EXPECT_EQ(processes[4].processId, pid7);
EXPECT_EQ(processes[4].engines, engines7);
EXPECT_EQ(processes[4].memSize, memSize7);
EXPECT_EQ(processes[4].sharedSize, sharedMemSize7);
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhileRetrievingInformationAboutHostProcessesUsingDeviceThenSuccessIsReturnedEvenwithFaultyClient) {
uint32_t count = 0;
pSysfsAccess->mockGetScannedDir4EntriesStatus = true;
pSysfsAccess->mockGetValUnsignedLongStatus = true;
ASSERT_EQ(ZE_RESULT_SUCCESS, zesDeviceProcessesGetState(device, &count, nullptr));
EXPECT_EQ(count, totalProcessStatesForFaultyClients);
std::vector<zes_process_state_t> processes(count);
ASSERT_EQ(ZE_RESULT_SUCCESS, zesDeviceProcessesGetState(device, &count, processes.data()));
EXPECT_EQ(processes[0].processId, pid1);
EXPECT_EQ(processes[0].engines, engines1);
EXPECT_EQ(processes[0].memSize, memSize1);
EXPECT_EQ(processes[0].sharedSize, sharedMemSize1);
EXPECT_EQ(processes[1].processId, pid2);
EXPECT_EQ(processes[1].engines, engines2);
EXPECT_EQ(processes[1].memSize, memSize2);
EXPECT_EQ(processes[1].sharedSize, sharedMemSize2);
EXPECT_EQ(processes[2].processId, pid4);
EXPECT_EQ(processes[2].engines, engines4);
EXPECT_EQ(processes[2].memSize, memSize4);
EXPECT_EQ(processes[2].sharedSize, sharedMemSize4);
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileCountValueIsProvidedThenFailureIsReturned) {
uint32_t count = 2;
ASSERT_EQ(ZE_RESULT_ERROR_INVALID_SIZE, zesDeviceProcessesGetState(device, &count, nullptr));
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileRetrievingInformationAboutHostProcessesUsingFaultyClientFileThenFailureIsReturned) {
uint32_t count = 0;
pSysfsAccess->mockGetScannedDir4EntriesStatus = true;
ASSERT_EQ(ZE_RESULT_ERROR_UNKNOWN, zesDeviceProcessesGetState(device, &count, nullptr));
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileRetrievingInformationAboutHostProcessesUsingNullDirThenFailureIsReturned) {
uint32_t count = 0;
pSysfsAccess->mockScanDirEntriesError = ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, zesDeviceProcessesGetState(device, &count, nullptr));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhileRetrievingInformationAboutHostProcessesUsingDeviceThenFailureIsReturnedEvenwithFaultyClient) {
uint32_t count = 0;
pSysfsAccess->mockGetScannedDirPidEntriesStatus = true;
pSysfsAccess->mockReadError = ZE_RESULT_ERROR_UNKNOWN;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, zesDeviceProcessesGetState(device, &count, nullptr));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhileRetrievingInformationAboutHostProcessesUsingBusyDirForEnginesReadThenFailureIsReturnedEvenwithFaultyClient) {
uint32_t count = 0;
pSysfsAccess->mockGetScannedDirPidEntriesStatus = true;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, zesDeviceProcessesGetState(device, &count, nullptr));
}
TEST_F(SysmanGlobalOperationsFixture,
GivenValidDeviceHandleWhileRetrievingInformationAboutHostProcessesUsingBusyDirForEnginesThenFailureIsReturnedEvenwithFaultyClient) {
uint32_t count = 0;
pSysfsAccess->mockGetScannedDir4EntriesStatus = true;
pSysfsAccess->mockReadStatus = true;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, zesDeviceProcessesGetState(device, &count, nullptr));
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileReadingInvalidBufferObjectsThenErrorIsReturned) {
uint32_t count = 0;
pSysfsAccess->mockGetScannedDirPidEntriesForClientsStatus = true;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, zesDeviceProcessesGetState(device, &count, nullptr));
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileReadingExistingMemoryFileThenCorrectValueIsReturned) {
uint64_t memSize = 0;
EXPECT_EQ(ZE_RESULT_SUCCESS, pSysfsAccess->read("clients/6/total_device_memory_buffer_objects/created_bytes", memSize));
EXPECT_EQ(memSize2, memSize);
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileReadingInvalidMemoryFileThenErrorIsReturned) {
uint64_t memSize = 0;
pSysfsAccess->mockGetScannedDir4EntriesStatus = true;
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pSysfsAccess->read("clients/7/total_device_memory_buffer_objects/imported_bytes", memSize));
}
TEST_F(SysmanGlobalOperationsFixture, GivenValidDeviceHandleWhileReadingNonExistingFileThenErrorIsReturned) {
std::vector<std::string> engineEntries;
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pSysfsAccess->scanDirEntries("clients/7/busy", engineEntries));
}
TEST_F(SysmanGlobalOperationsFixture, GivenDeviceIsWedgedWhenCallingGetDeviceStateThenZesResetReasonFlagWedgedIsReturned) {
auto pDrm = new DrmGlobalOpsMock(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()));
pDrm->ioctlRetVal = -1;
pDrm->ioctlErrno = EIO;
pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterface->setDriverModel(std::unique_ptr<DrmGlobalOpsMock>(pDrm));
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
EXPECT_EQ(ZES_RESET_REASON_FLAG_WEDGED, deviceState.reset);
}
TEST_F(SysmanGlobalOperationsFixture, GivenDeviceIsNotWedgedWhenCallingGetDeviceStateThenZeroIsReturned) {
auto pDrm = new DrmGlobalOpsMock(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()));
pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterface->setDriverModel(std::unique_ptr<DrmGlobalOpsMock>(pDrm));
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
EXPECT_EQ(0u, deviceState.reset);
}
TEST_F(SysmanGlobalOperationsFixture, GivenGemCreateIoctlFailsWithEINVALWhenCallingGetDeviceStateThenVerifyResetIsNotNeeded) {
auto pDrm = new DrmGlobalOpsMock(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()));
pDrm->ioctlRetVal = -1;
pDrm->ioctlErrno = EINVAL;
pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterface->setDriverModel(std::unique_ptr<DrmGlobalOpsMock>(pDrm));
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
EXPECT_EQ(0u, deviceState.reset);
}
TEST_F(SysmanGlobalOperationsFixture, GivenForceTrueWhenCallingResetThenSuccessIsReturned) {
ze_result_t result = zesDeviceReset(device, true);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture,
GivenPermissionDeniedWhenCallingGetDeviceStateThenZeResultErrorInsufficientPermissionsIsReturned) {
pSysfsAccess->isRootSet = false;
ze_result_t result = zesDeviceReset(device, true);
EXPECT_EQ(ZE_RESULT_ERROR_INSUFFICIENT_PERMISSIONS, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture, GivenDeviceInUseWhenCallingResetThenZeResultErrorHandleObjectInUseIsReturned) {
pProcfsAccess->ourDevicePid = pProcfsAccess->extraPid;
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(true);
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture, GivenDeviceNotInUseWhenCallingResetThenSuccessIsReturned) {
// Pretend we have the device open
pProcfsAccess->ourDevicePid = getpid();
pProcfsAccess->ourDeviceFd = ::open("/dev/null", 0);
// The first time we get the process list, include our own process, that has the file open
// Reset should close the file (we verify after reset). On subsequent calls, return
// the process list without our process
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(false);
pProcfsAccess->mockListProcessCall.push_back(DEVICE_UNUSED);
pProcfsAccess->isRepeated.push_back(true);
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
// Check that reset closed the device
// If the device is already closed, then close will fail with errno of EBADF
EXPECT_NE(0, ::close(pProcfsAccess->ourDevicePid));
EXPECT_EQ(errno, EBADF);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture, GivenForceTrueAndDeviceInUseWhenCallingResetThenSuccessIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(true);
ze_result_t result = zesDeviceReset(device, true);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture, GivenProcessStartsMidResetWhenCallingResetThenSuccessIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
// Return process list without open fd on first call, but with open fd on subsequent calls
pProcfsAccess->mockListProcessCall.push_back(DEVICE_UNUSED);
pProcfsAccess->isRepeated.push_back(false);
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(true);
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture, GivenProcessStartsMidResetWhenCallingResetAndBindFailsThenFailureIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
// Return process list without open fd on first call, but with open fd on subsequent calls
pProcfsAccess->mockListProcessCall.push_back(DEVICE_UNUSED);
pProcfsAccess->isRepeated.push_back(false);
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(true);
pSysfsAccess->mockBindDeviceError = ZE_RESULT_ERROR_UNKNOWN;
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture,
GivenDeviceInUseWhenCallingResetAndListProcessesFailsThenZeResultErrorIsReturned) {
pProcfsAccess->ourDevicePid = pProcfsAccess->extraPid;
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
pProcfsAccess->mockListProcessCall.push_back(RETURN_ERROR);
pProcfsAccess->isRepeated.push_back(false);
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture,
GivenProcessStartsMidResetWhenListProcessesFailsAfterUnbindThenFailureIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
// Return process list without open fd on first call
pProcfsAccess->mockListProcessCall.push_back(DEVICE_UNUSED);
pProcfsAccess->isRepeated.push_back(false);
pProcfsAccess->mockListProcessCall.push_back(RETURN_ERROR);
pProcfsAccess->isRepeated.push_back(false);
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture,
GivenProcessStartsMidResetWhenCallingResetAndWriteFailsAfterUnbindThenFailureIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
// Return process list without open fd on first call, but with open fd on subsequent calls
pProcfsAccess->mockListProcessCall.push_back(DEVICE_UNUSED);
pProcfsAccess->isRepeated.push_back(false);
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(true);
pFsAccess->mockWriteError = ZE_RESULT_ERROR_UNKNOWN;
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture,
GivenProcessStartsMidResetWhenCallingResetAndUnbindFailsThenFailureIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
// Return process list without open fd on first call, but with open fd on subsequent calls
pProcfsAccess->mockListProcessCall.push_back(DEVICE_UNUSED);
pProcfsAccess->isRepeated.push_back(true);
pSysfsAccess->mockUnbindDeviceError = ZE_RESULT_ERROR_UNKNOWN;
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture,
GivenProcessStartsMidResetWhenCallingResetAndGetFileNameFailsThenSuccessIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
// Return process list without open fd on first call, but with open fd on subsequent calls
pProcfsAccess->mockListProcessCall.push_back(DEVICE_UNUSED);
pProcfsAccess->isRepeated.push_back(false);
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(true);
pProcfsAccess->mockGetFileNameError = ZE_RESULT_ERROR_UNKNOWN;
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture,
GivenProcessWontDieWhenCallingResetThenZeResultErrorHandleObjectInUseErrorIsReturned) {
initGlobalOps();
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
static_cast<PublicLinuxGlobalOperationsImp *>(pGlobalOperationsImp->pOsGlobalOperations)->resetTimeout = 0; // timeout immediate
// Return process list without open fd on first call, but with open fd on subsequent calls
pProcfsAccess->mockListProcessCall.push_back(DEVICE_UNUSED);
pProcfsAccess->isRepeated.push_back(false);
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(true);
pProcfsAccess->mockNoKill = true;
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_ERROR_HANDLE_OBJECT_IN_USE, result);
}
TEST_F(SysmanGlobalOperationsIntegratedFixture, GivenProcessStartsMidResetWhenCallingResetAndGetFileDescriptorsFailsThenSuccessIsReturned) {
// Pretend another process has the device open
pProcfsAccess->ourDevicePid = getpid() + 1; // make sure it isn't our process id
pProcfsAccess->ourDeviceFd = pProcfsAccess->extraFd;
// Return process list without open fd on first call, but with open fd on subsequent calls
pProcfsAccess->mockListProcessCall.push_back(DEVICE_IN_USE);
pProcfsAccess->isRepeated.push_back(true);
pProcfsAccess->mockGetFileDescriptorsError = ZE_RESULT_ERROR_UNKNOWN;
pProcfsAccess->mockGetFileNameError = ZE_RESULT_ERROR_UNKNOWN;
ze_result_t result = zesDeviceReset(device, false);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(SysmanDeviceFixture, GivenValidDeviceHandleWhenCallingDeviceGetStateThenSuccessResultIsReturned) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
auto pDrm = new DrmGlobalOpsMock(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()));
pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterface->setDriverModel(std::unique_ptr<DrmGlobalOpsMock>(pDrm));
zes_device_state_t deviceState;
ze_result_t result = zesDeviceGetState(pSysmanDevice, &deviceState);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
} // namespace ult
} // namespace L0

View File

@@ -0,0 +1,115 @@
/*
* Copyright (C) 2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h"
#include "level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h"
namespace L0 {
namespace ult {
class SysmanGlobalOperationsHelperFixture : public SysmanDeviceFixture {
protected:
std::unique_ptr<MockGlobalOperationsSysfsAccess> pSysfsAccess;
std::unique_ptr<MockGlobalOperationsProcfsAccess> pProcfsAccess;
std::unique_ptr<MockGlobalOperationsFsAccess> pFsAccess;
std::unique_ptr<MockGlobalOpsFwInterface> pMockFwInterface;
L0::Sysman::FirmwareUtil *pFwUtilInterfaceOld = nullptr;
L0::Sysman::SysfsAccess *pSysfsAccessOld = nullptr;
L0::Sysman::ProcfsAccess *pProcfsAccessOld = nullptr;
L0::Sysman::FsAccess *pFsAccessOld = nullptr;
L0::Sysman::OsGlobalOperations *pOsGlobalOperationsPrev = nullptr;
L0::Sysman::GlobalOperations *pGlobalOperationsPrev = nullptr;
L0::Sysman::GlobalOperationsImp *pGlobalOperationsImp;
L0::Sysman::SysmanDeviceImp *device = nullptr;
void SetUp() override {
SysmanDeviceFixture::SetUp();
pSysfsAccessOld = pLinuxSysmanImp->pSysfsAccess;
pProcfsAccessOld = pLinuxSysmanImp->pProcfsAccess;
pFsAccessOld = pLinuxSysmanImp->pFsAccess;
pFwUtilInterfaceOld = pLinuxSysmanImp->pFwUtilInterface;
pSysfsAccess = std::make_unique<MockGlobalOperationsSysfsAccess>();
pProcfsAccess = std::make_unique<MockGlobalOperationsProcfsAccess>();
pFsAccess = std::make_unique<MockGlobalOperationsFsAccess>();
pMockFwInterface = std::make_unique<MockGlobalOpsFwInterface>();
pLinuxSysmanImp->pFwUtilInterface = pMockFwInterface.get();
pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get();
pLinuxSysmanImp->pProcfsAccess = pProcfsAccess.get();
pLinuxSysmanImp->pFsAccess = pFsAccess.get();
auto pDrmLocal = new DrmGlobalOpsMock(const_cast<NEO::RootDeviceEnvironment &>(pSysmanDeviceImp->getRootDeviceEnvironment()));
pDrmLocal->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily);
auto &osInterfaceLocal = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface;
osInterfaceLocal->setDriverModel(std::unique_ptr<DrmGlobalOpsMock>(pDrmLocal));
pFsAccess->mockReadVal = driverVersion;
pGlobalOperationsImp = static_cast<L0::Sysman::GlobalOperationsImp *>(pSysmanDeviceImp->pGlobalOperations);
pOsGlobalOperationsPrev = pGlobalOperationsImp->pOsGlobalOperations;
pGlobalOperationsImp->pOsGlobalOperations = nullptr;
device = pSysmanDeviceImp;
}
void TearDown() override {
if (nullptr != pGlobalOperationsImp->pOsGlobalOperations) {
delete pGlobalOperationsImp->pOsGlobalOperations;
}
pGlobalOperationsImp->pOsGlobalOperations = pOsGlobalOperationsPrev;
pGlobalOperationsImp = nullptr;
pLinuxSysmanImp->pSysfsAccess = pSysfsAccessOld;
pLinuxSysmanImp->pProcfsAccess = pProcfsAccessOld;
pLinuxSysmanImp->pFsAccess = pFsAccessOld;
pLinuxSysmanImp->pFwUtilInterface = pFwUtilInterfaceOld;
SysmanDeviceFixture::TearDown();
}
};
HWTEST2_F(SysmanGlobalOperationsHelperFixture, GivenDeviceIsRepairedWhenCallingGetDeviceStateThenZesResetReasonFlagRepairedIsReturned, IsPVC) {
pMockFwInterface->mockIfrStatus = true;
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
EXPECT_EQ(ZES_RESET_REASON_FLAG_REPAIR, deviceState.reset);
EXPECT_EQ(ZES_REPAIR_STATUS_PERFORMED, deviceState.repaired);
}
HWTEST2_F(SysmanGlobalOperationsHelperFixture, GivenDeviceIsRepairedWhenCallingGetDeviceStateThenZesResetReasonFlagRepairedIsReturned, IsNotPVC) {
pMockFwInterface->mockIfrStatus = true;
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
EXPECT_EQ(ZES_REPAIR_STATUS_UNSUPPORTED, deviceState.repaired);
}
HWTEST2_F(SysmanGlobalOperationsHelperFixture, GivenDeviceIsRepairedWhenCallingGetDeviceStateAndFirmwareRepairStatusIsFalseThenZesResetReasonFlagRepairedIsNotReturned, IsPVC) {
pMockFwInterface->mockIfrStatus = false;
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
EXPECT_EQ(0u, deviceState.reset);
EXPECT_EQ(ZES_REPAIR_STATUS_NOT_PERFORMED, deviceState.repaired);
}
HWTEST2_F(SysmanGlobalOperationsHelperFixture, GivenDeviceIsRepairedWhenCallingGetDeviceStateAndFirmwareRepairStatusIsFalseThenZesResetReasonFlagRepairedIsNotReturned, IsNotPVC) {
pMockFwInterface->mockIfrStatus = false;
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
EXPECT_EQ(0u, deviceState.reset);
EXPECT_EQ(ZES_REPAIR_STATUS_UNSUPPORTED, deviceState.repaired);
}
TEST_F(SysmanGlobalOperationsHelperFixture, GivenDeviceIsRepairedWhenCallingGetDeviceStateAndFirmwareRepairStatusFailsThenZesResetReasonFlagRepairedIsNotReturned) {
pMockFwInterface->mockIfrError = ZE_RESULT_ERROR_UNKNOWN;
zes_device_state_t deviceState;
EXPECT_EQ(ZE_RESULT_SUCCESS, zesDeviceGetState(device, &deviceState));
EXPECT_EQ(0u, deviceState.reset);
EXPECT_EQ(ZES_REPAIR_STATUS_UNSUPPORTED, deviceState.repaired);
}
} // namespace ult
} // namespace L0

View File

@@ -36,6 +36,7 @@ class PublicLinuxSysmanImp : public L0::Sysman::LinuxSysmanImp {
using LinuxSysmanImp::pPmuInterface;
using LinuxSysmanImp::pProcfsAccess;
using LinuxSysmanImp::pSysfsAccess;
using LinuxSysmanImp::rootPath;
};
class SysmanDeviceFixture : public ::testing::Test {

View File

@@ -6,16 +6,13 @@
*/
#pragma once
#include "level_zero/api/sysman/zes_handles_struct.h"
#include <level_zero/zes_api.h>
#include <mutex>
#include <string>
#include <vector>
struct _zes_diag_handle_t {
virtual ~_zes_diag_handle_t() = default;
};
namespace L0 {
struct OsSysman;

View File

@@ -1,21 +1,18 @@
/*
* Copyright (C) 2020-2022 Intel Corporation
* Copyright (C) 2020-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#pragma once
#include "level_zero/api/sysman/zes_handles_struct.h"
#include "level_zero/core/source/device/device.h"
#include <level_zero/zes_api.h>
#include <mutex>
#include <vector>
struct _zes_ras_handle_t {
virtual ~_zes_ras_handle_t() = default;
};
namespace L0 {
struct OsSysman;