From d29ed25f8bf205a16f5936a5863f60a174b0ee0c Mon Sep 17 00:00:00 2001 From: Jitendra Sharma Date: Fri, 24 Mar 2023 07:32:22 +0000 Subject: [PATCH] Add support for global_operations in new sysman design Related-To: LOCI-4135 Signed-off-by: Jitendra Sharma --- level_zero/api/sysman/zes_handles_struct.h | 8 + .../api/sysman/zes_sysman_api_entrypoints.h | 24 +- .../sysman/source/diagnostics/CMakeLists.txt | 15 + .../sysman/source/diagnostics/diagnostics.cpp | 48 + .../sysman/source/diagnostics/diagnostics.h | 56 ++ .../source/global_operations/CMakeLists.txt | 16 + .../global_operations/global_operations.h | 26 + .../global_operations_imp.cpp | 92 ++ .../global_operations/global_operations_imp.h | 40 + .../global_operations/linux/CMakeLists.txt | 27 + .../linux/os_global_operations_helper.cpp | 14 + .../os_global_operations_helper_prelim.cpp | 30 + .../linux/os_global_operations_imp.cpp | 491 +++++++++ .../linux/os_global_operations_imp.h | 63 ++ .../global_operations/os_global_operations.h | 36 + .../global_operations/windows/CMakeLists.txt | 14 + .../windows/os_global_operations_imp.cpp | 58 ++ .../windows/os_global_operations_imp.h | 37 + .../sysman/source/linux/os_sysman_imp.cpp | 235 +++++ .../sysman/source/linux/os_sysman_imp.h | 20 +- level_zero/sysman/source/ras/CMakeLists.txt | 14 + level_zero/sysman/source/ras/ras.cpp | 51 + level_zero/sysman/source/ras/ras.h | 58 ++ level_zero/sysman/source/sysman_device.cpp | 29 + level_zero/sysman/source/sysman_device.h | 22 + .../sysman/source/sysman_device_imp.cpp | 45 +- level_zero/sysman/source/sysman_device_imp.h | 12 +- .../sources/global_operations/CMakeLists.txt | 10 + .../global_operations/linux/CMakeLists.txt | 24 + .../linux/mock_global_operations.h | 579 +++++++++++ .../linux/test_zes_global_operations.cpp | 942 ++++++++++++++++++ .../test_zes_global_operations_prelim.cpp | 115 +++ .../sources/linux/mock_sysman_fixture.h | 1 + .../source/sysman/diagnostics/diagnostics.h | 5 +- level_zero/tools/source/sysman/ras/ras.h | 7 +- 35 files changed, 3241 insertions(+), 23 deletions(-) create mode 100644 level_zero/sysman/source/diagnostics/CMakeLists.txt create mode 100644 level_zero/sysman/source/diagnostics/diagnostics.cpp create mode 100644 level_zero/sysman/source/diagnostics/diagnostics.h create mode 100644 level_zero/sysman/source/global_operations/CMakeLists.txt create mode 100644 level_zero/sysman/source/global_operations/global_operations.h create mode 100644 level_zero/sysman/source/global_operations/global_operations_imp.cpp create mode 100644 level_zero/sysman/source/global_operations/global_operations_imp.h create mode 100644 level_zero/sysman/source/global_operations/linux/CMakeLists.txt create mode 100644 level_zero/sysman/source/global_operations/linux/os_global_operations_helper.cpp create mode 100644 level_zero/sysman/source/global_operations/linux/os_global_operations_helper_prelim.cpp create mode 100644 level_zero/sysman/source/global_operations/linux/os_global_operations_imp.cpp create mode 100644 level_zero/sysman/source/global_operations/linux/os_global_operations_imp.h create mode 100644 level_zero/sysman/source/global_operations/os_global_operations.h create mode 100644 level_zero/sysman/source/global_operations/windows/CMakeLists.txt create mode 100644 level_zero/sysman/source/global_operations/windows/os_global_operations_imp.cpp create mode 100644 level_zero/sysman/source/global_operations/windows/os_global_operations_imp.h create mode 100644 level_zero/sysman/source/ras/CMakeLists.txt create mode 100644 level_zero/sysman/source/ras/ras.cpp create mode 100644 level_zero/sysman/source/ras/ras.h create mode 100644 level_zero/sysman/test/unit_tests/sources/global_operations/CMakeLists.txt create mode 100644 level_zero/sysman/test/unit_tests/sources/global_operations/linux/CMakeLists.txt create mode 100644 level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h create mode 100644 level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations.cpp create mode 100644 level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations_prelim.cpp diff --git a/level_zero/api/sysman/zes_handles_struct.h b/level_zero/api/sysman/zes_handles_struct.h index 460093d09c..adf60280bf 100644 --- a/level_zero/api/sysman/zes_handles_struct.h +++ b/level_zero/api/sysman/zes_handles_struct.h @@ -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; +}; diff --git a/level_zero/api/sysman/zes_sysman_api_entrypoints.h b/level_zero/api/sysman/zes_sysman_api_entrypoints.h index 0ed4f2778e..a81d9f368e 100644 --- a/level_zero/api/sysman/zes_sysman_api_entrypoints.h +++ b/level_zero/api/sysman/zes_sysman_api_entrypoints.h @@ -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( diff --git a/level_zero/sysman/source/diagnostics/CMakeLists.txt b/level_zero/sysman/source/diagnostics/CMakeLists.txt new file mode 100644 index 0000000000..657dcdb80f --- /dev/null +++ b/level_zero/sysman/source/diagnostics/CMakeLists.txt @@ -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() + diff --git a/level_zero/sysman/source/diagnostics/diagnostics.cpp b/level_zero/sysman/source/diagnostics/diagnostics.cpp new file mode 100644 index 0000000000..9fd3ed8924 --- /dev/null +++ b/level_zero/sysman/source/diagnostics/diagnostics.cpp @@ -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(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 diff --git a/level_zero/sysman/source/diagnostics/diagnostics.h b/level_zero/sysman/source/diagnostics/diagnostics.h new file mode 100644 index 0000000000..ddf3b5f6b1 --- /dev/null +++ b/level_zero/sysman/source/diagnostics/diagnostics.h @@ -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 + +#include +#include +#include + +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(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 supportedDiagTests = {}; + OsSysman *pOsSysman = nullptr; + std::vector handleList = {}; + bool isDiagnosticsInitDone() { + return diagnosticsInitDone; + } + + private: + void createHandle(const std::string &diagTests); + std::once_flag initDiagnosticsOnce; + bool diagnosticsInitDone = false; +}; + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/global_operations/CMakeLists.txt b/level_zero/sysman/source/global_operations/CMakeLists.txt new file mode 100644 index 0000000000..6ace244c2e --- /dev/null +++ b/level_zero/sysman/source/global_operations/CMakeLists.txt @@ -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() \ No newline at end of file diff --git a/level_zero/sysman/source/global_operations/global_operations.h b/level_zero/sysman/source/global_operations/global_operations.h new file mode 100644 index 0000000000..f09be617dc --- /dev/null +++ b/level_zero/sysman/source/global_operations/global_operations.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include + +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 diff --git a/level_zero/sysman/source/global_operations/global_operations_imp.cpp b/level_zero/sysman/source/global_operations/global_operations_imp.cpp new file mode 100644 index 0000000000..68b5ec5f5f --- /dev/null +++ b/level_zero/sysman/source/global_operations/global_operations_imp.cpp @@ -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 + +namespace L0 { +namespace Sysman { + +ze_result_t GlobalOperationsImp::processesGetState(uint32_t *pCount, zes_process_state_t *pProcesses) { + initGlobalOperations(); + std::vector 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(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(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 diff --git a/level_zero/sysman/source/global_operations/global_operations_imp.h b/level_zero/sysman/source/global_operations/global_operations_imp.h new file mode 100644 index 0000000000..f34cb796ed --- /dev/null +++ b/level_zero/sysman/source/global_operations/global_operations_imp.h @@ -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 + +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 diff --git a/level_zero/sysman/source/global_operations/linux/CMakeLists.txt b/level_zero/sysman/source/global_operations/linux/CMakeLists.txt new file mode 100644 index 0000000000..7eb1e6327e --- /dev/null +++ b/level_zero/sysman/source/global_operations/linux/CMakeLists.txt @@ -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() \ No newline at end of file diff --git a/level_zero/sysman/source/global_operations/linux/os_global_operations_helper.cpp b/level_zero/sysman/source/global_operations/linux/os_global_operations_helper.cpp new file mode 100644 index 0000000000..998a69c3f7 --- /dev/null +++ b/level_zero/sysman/source/global_operations/linux/os_global_operations_helper.cpp @@ -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 \ No newline at end of file diff --git a/level_zero/sysman/source/global_operations/linux/os_global_operations_helper_prelim.cpp b/level_zero/sysman/source/global_operations/linux/os_global_operations_helper_prelim.cpp new file mode 100644 index 0000000000..dd2cf00f36 --- /dev/null +++ b/level_zero/sysman/source/global_operations/linux/os_global_operations_helper_prelim.cpp @@ -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 diff --git a/level_zero/sysman/source/global_operations/linux/os_global_operations_imp.cpp b/level_zero/sysman/source/global_operations/linux/os_global_operations_imp.cpp new file mode 100644 index 0000000000..229801ff6c --- /dev/null +++ b/level_zero/sysman/source/global_operations/linux/os_global_operations_imp.cpp @@ -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 +#include +#include +#include + +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/clients//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 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 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 guidString = {}; + if (!NEO::PmtUtil::readGuid(telemDir, guidString)) { + return false; + } + + uint64_t offset = ULONG_MAX; + if (!NEO::PmtUtil::readOffset(telemDir, offset)) { + return false; + } + + std::map 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 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 myPidFds; + std::vector<::pid_t> processes; + + result = pProcfsAccess->listProcesses(processes); + if (ZE_RESULT_SUCCESS != result) { + return result; + } + for (auto &&pid : processes) { + std::vector 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 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(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 &pProcessList) { + std::vector 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 pidClientMap; + for (const auto &clientId : clientIds) { + // realClientPidPath will be something like: clients//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//busy directory to get accelerator engines used by process + std::vector 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//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(itr->first); + process.memSize = itr->second.deviceMemStructField.deviceMemorySize; + process.sharedSize = itr->second.deviceMemStructField.deviceSharedMemorySize; + process.engines = static_cast(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(pOsSysman); + + pSysfsAccess = &pLinuxSysmanImp->getSysfsAccess(); + pProcfsAccess = &pLinuxSysmanImp->getProcfsAccess(); + pFsAccess = &pLinuxSysmanImp->getFsAccess(); + devicePciBdf = pLinuxSysmanImp->getParentSysmanDeviceImp()->getRootDeviceEnvironment().osInterface->getDriverModel()->as()->getPciPath(); + rootDeviceIndex = pLinuxSysmanImp->getParentSysmanDeviceImp()->getRootDeviceIndex(); +} + +OsGlobalOperations *OsGlobalOperations::create(OsSysman *pOsSysman) { + LinuxGlobalOperationsImp *pLinuxGlobalOperationsImp = new LinuxGlobalOperationsImp(pOsSysman); + return static_cast(pLinuxGlobalOperationsImp); +} + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/global_operations/linux/os_global_operations_imp.h b/level_zero/sysman/source/global_operations/linux/os_global_operations_imp.h new file mode 100644 index 0000000000..185f34b934 --- /dev/null +++ b/level_zero/sysman/source/global_operations/linux/os_global_operations_imp.h @@ -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 &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 diff --git a/level_zero/sysman/source/global_operations/os_global_operations.h b/level_zero/sysman/source/global_operations/os_global_operations.h new file mode 100644 index 0000000000..4fdcba8b88 --- /dev/null +++ b/level_zero/sysman/source/global_operations/os_global_operations.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +#include "level_zero/sysman/source/os_sysman.h" +#include + +#include + +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 &pProcessList) = 0; + virtual ze_result_t deviceGetState(zes_device_state_t *pState) = 0; + static OsGlobalOperations *create(OsSysman *pOsSysman); + virtual ~OsGlobalOperations() {} +}; + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/global_operations/windows/CMakeLists.txt b/level_zero/sysman/source/global_operations/windows/CMakeLists.txt new file mode 100644 index 0000000000..953f986b70 --- /dev/null +++ b/level_zero/sysman/source/global_operations/windows/CMakeLists.txt @@ -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() \ No newline at end of file diff --git a/level_zero/sysman/source/global_operations/windows/os_global_operations_imp.cpp b/level_zero/sysman/source/global_operations/windows/os_global_operations_imp.cpp new file mode 100644 index 0000000000..aa12e7be4d --- /dev/null +++ b/level_zero/sysman/source/global_operations/windows/os_global_operations_imp.cpp @@ -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 &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(pWddmGlobalOperationsImp); +} + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/global_operations/windows/os_global_operations_imp.h b/level_zero/sysman/source/global_operations/windows/os_global_operations_imp.h new file mode 100644 index 0000000000..ea03a1fa07 --- /dev/null +++ b/level_zero/sysman/source/global_operations/windows/os_global_operations_imp.h @@ -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 &pProcessList) override; + ze_result_t deviceGetState(zes_device_state_t *pState) override; + + WddmGlobalOperationsImp(OsSysman *pOsSysman); + WddmGlobalOperationsImp() = default; + ~WddmGlobalOperationsImp() override = default; +}; + +} // namespace Sysman +} // namespace L0 diff --git a/level_zero/sysman/source/linux/os_sysman_imp.cpp b/level_zero/sysman/source/linux/os_sysman_imp.cpp index 8f78d71e70..e7be90b749 100644 --- a/level_zero/sysman/source/linux/os_sysman_imp.cpp +++ b/level_zero/sysman/source/linux/os_sysman_imp.cpp @@ -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 + 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()->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(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 &deviceFds) { + // Return a list of all the file descriptors of this process that point to this device + std::vector 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 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 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 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//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(pLinuxSysmanImp); diff --git a/level_zero/sysman/source/linux/os_sysman_imp.h b/level_zero/sysman/source/linux/os_sysman_imp.h index 6c25b89a9a..f5c60d95f2 100644 --- a/level_zero/sysman/source/linux/os_sysman_imp.h +++ b/level_zero/sysman/source/linux/os_sysman_imp.h @@ -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 &); + 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 diff --git a/level_zero/sysman/source/ras/CMakeLists.txt b/level_zero/sysman/source/ras/CMakeLists.txt new file mode 100644 index 0000000000..12a56935df --- /dev/null +++ b/level_zero/sysman/source/ras/CMakeLists.txt @@ -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() diff --git a/level_zero/sysman/source/ras/ras.cpp b/level_zero/sysman/source/ras/ras.cpp new file mode 100644 index 0000000000..364e30322c --- /dev/null +++ b/level_zero/sysman/source/ras/ras.cpp @@ -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(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 diff --git a/level_zero/sysman/source/ras/ras.h b/level_zero/sysman/source/ras/ras.h new file mode 100644 index 0000000000..40ed7f490e --- /dev/null +++ b/level_zero/sysman/source/ras/ras.h @@ -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 + +#include +#include + +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(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 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 diff --git a/level_zero/sysman/source/sysman_device.cpp b/level_zero/sysman/source/sysman_device.cpp index 11f8e0bae8..fd794b0976 100644 --- a/level_zero/sysman/source/sysman_device.cpp +++ b/level_zero/sysman/source/sysman_device.cpp @@ -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 diff --git a/level_zero/sysman/source/sysman_device.h b/level_zero/sysman/source/sysman_device.h index 7648df2e16..792956250d 100644 --- a/level_zero/sysman/source/sysman_device.h +++ b/level_zero/sysman/source/sysman_device.h @@ -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 #include @@ -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 diff --git a/level_zero/sysman/source/sysman_device_imp.cpp b/level_zero/sysman/source/sysman_device_imp.cpp index 9aa363ba35..2f6cc5ac4d 100644 --- a/level_zero/sysman/source/sysman_device_imp.cpp +++ b/level_zero/sysman/source/sysman_device_imp.cpp @@ -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 @@ -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 diff --git a/level_zero/sysman/source/sysman_device_imp.h b/level_zero/sysman/source/sysman_device_imp.h index cc922823b1..10c80394f7 100644 --- a/level_zero/sysman/source/sysman_device_imp.h +++ b/level_zero/sysman/source/sysman_device_imp.h @@ -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; diff --git a/level_zero/sysman/test/unit_tests/sources/global_operations/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/global_operations/CMakeLists.txt new file mode 100644 index 0000000000..9704dc6ade --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/global_operations/CMakeLists.txt @@ -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() diff --git a/level_zero/sysman/test/unit_tests/sources/global_operations/linux/CMakeLists.txt b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/CMakeLists.txt new file mode 100644 index 0000000000..27930ea145 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/CMakeLists.txt @@ -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() diff --git a/level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h new file mode 100644 index 0000000000..6cc1fcd857 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/mock_global_operations.h @@ -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(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(Index::MockSubsystemVendor)]; + } else if (file.compare(deviceFile) == 0) { + val = mockReadVal[static_cast(Index::MockDevice)]; + } else if (file.compare(vendorFile) == 0) { + val = mockReadVal[static_cast(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 &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 &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 &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 &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 fdList = {0, 1, 2}; + ::pid_t ourDevicePid = 0; + int ourDeviceFd = 0; + + std::vector mockListProcessCall{}; + std::vector 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 &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 & 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 & 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 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 &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(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 diff --git a/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations.cpp b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations.cpp new file mode 100644 index 0000000000..b93b5684a1 --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations.cpp @@ -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 +#include + +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 pEngineHandleContext; + std::unique_ptr pDiagnosticsHandleContext; + std::unique_ptr pFirmwareHandleContext; + std::unique_ptr pRasHandleContext; + std::unique_ptr pSysfsAccess; + std::unique_ptr pProcfsAccess; + std::unique_ptr 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(pOsSysman); + pSysfsAccess = std::make_unique(); + pProcfsAccess = std::make_unique(); + pFsAccess = std::make_unique(); + pDiagnosticsHandleContext = std::make_unique(pOsSysman); + pFirmwareHandleContext = std::make_unique(pOsSysman); + pRasHandleContext = std::make_unique(pOsSysman); + + auto pDrmLocal = new DrmGlobalOpsMock(const_cast(pSysmanDeviceImp->getRootDeviceEnvironment())); + pDrmLocal->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily); + auto &osInterfaceLocal = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface; + osInterfaceLocal->setDriverModel(std::unique_ptr(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(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 mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int { + std::map 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(it->second.size()); + } + return -1; + }); + + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + std::vector 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(std::distance(supportedFiles.begin(), itr)) + 1; + } + return 0; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + std::vector> 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(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 mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int { + std::map 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(it->second.size()); + } + return -1; + }); + + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + std::vector 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(std::distance(supportedFiles.begin(), itr)) + 1; + } + return 0; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + std::vector> 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(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 mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int { + std::map 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(it->second.size()); + } + return -1; + }); + + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + std::vector 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(std::distance(supportedFiles.begin(), itr)) + 1; + } + return 0; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + std::vector> 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(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 mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int { + std::map 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(it->second.size()); + } + return -1; + }); + + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + std::vector 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(std::distance(supportedFiles.begin(), itr)) + 1; + } + return 0; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + std::vector> 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(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 mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int { + std::map 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(it->second.size()); + } + return -1; + }); + + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + std::vector 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(std::distance(supportedFiles.begin(), itr)) + 1; + } + return 0; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + std::vector> 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(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 mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int { + std::map 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(it->second.size()); + } + return -1; + }); + + VariableBackup 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 mockReadLink(&NEO::SysCalls::sysCallsReadlink, [](const char *path, char *buf, size_t bufsize) -> int { + std::map 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(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 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(MockGlobalOperationsSysfsAccess::Index::MockSubsystemVendor)] = "0xa086"; + pSysfsAccess->mockReadVal[static_cast(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 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 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 engineEntries; + EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, pSysfsAccess->scanDirEntries("clients/7/busy", engineEntries)); +} + +TEST_F(SysmanGlobalOperationsFixture, GivenDeviceIsWedgedWhenCallingGetDeviceStateThenZesResetReasonFlagWedgedIsReturned) { + auto pDrm = new DrmGlobalOpsMock(const_cast(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(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(pSysmanDeviceImp->getRootDeviceEnvironment())); + pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily); + auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface; + osInterface->setDriverModel(std::unique_ptr(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(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(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(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(); + auto pDrm = new DrmGlobalOpsMock(const_cast(pSysmanDeviceImp->getRootDeviceEnvironment())); + pDrm->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily); + auto &osInterface = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface; + osInterface->setDriverModel(std::unique_ptr(pDrm)); + + zes_device_state_t deviceState; + ze_result_t result = zesDeviceGetState(pSysmanDevice, &deviceState); + EXPECT_EQ(ZE_RESULT_SUCCESS, result); +} + +} // namespace ult +} // namespace L0 diff --git a/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations_prelim.cpp b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations_prelim.cpp new file mode 100644 index 0000000000..ed625041af --- /dev/null +++ b/level_zero/sysman/test/unit_tests/sources/global_operations/linux/test_zes_global_operations_prelim.cpp @@ -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 pSysfsAccess; + std::unique_ptr pProcfsAccess; + std::unique_ptr pFsAccess; + std::unique_ptr 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(); + pProcfsAccess = std::make_unique(); + pFsAccess = std::make_unique(); + pMockFwInterface = std::make_unique(); + pLinuxSysmanImp->pFwUtilInterface = pMockFwInterface.get(); + pLinuxSysmanImp->pSysfsAccess = pSysfsAccess.get(); + pLinuxSysmanImp->pProcfsAccess = pProcfsAccess.get(); + pLinuxSysmanImp->pFsAccess = pFsAccess.get(); + + auto pDrmLocal = new DrmGlobalOpsMock(const_cast(pSysmanDeviceImp->getRootDeviceEnvironment())); + pDrmLocal->setupIoctlHelper(pSysmanDeviceImp->getRootDeviceEnvironment().getHardwareInfo()->platform.eProductFamily); + auto &osInterfaceLocal = pSysmanDeviceImp->getRootDeviceEnvironment().osInterface; + osInterfaceLocal->setDriverModel(std::unique_ptr(pDrmLocal)); + + pFsAccess->mockReadVal = driverVersion; + pGlobalOperationsImp = static_cast(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 diff --git a/level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h b/level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h index b1b35a524c..87e66a1cb8 100644 --- a/level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h +++ b/level_zero/sysman/test/unit_tests/sources/linux/mock_sysman_fixture.h @@ -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 { diff --git a/level_zero/tools/source/sysman/diagnostics/diagnostics.h b/level_zero/tools/source/sysman/diagnostics/diagnostics.h index a33df4aa31..9ba5dc660f 100644 --- a/level_zero/tools/source/sysman/diagnostics/diagnostics.h +++ b/level_zero/tools/source/sysman/diagnostics/diagnostics.h @@ -6,16 +6,13 @@ */ #pragma once +#include "level_zero/api/sysman/zes_handles_struct.h" #include #include #include #include -struct _zes_diag_handle_t { - virtual ~_zes_diag_handle_t() = default; -}; - namespace L0 { struct OsSysman; diff --git a/level_zero/tools/source/sysman/ras/ras.h b/level_zero/tools/source/sysman/ras/ras.h index a802620d6c..ea6b93a529 100644 --- a/level_zero/tools/source/sysman/ras/ras.h +++ b/level_zero/tools/source/sysman/ras/ras.h @@ -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 #include #include -struct _zes_ras_handle_t { - virtual ~_zes_ras_handle_t() = default; -}; - namespace L0 { struct OsSysman;