From 671eccc713288c07cfd1d44dd110fdc8c42b7eef Mon Sep 17 00:00:00 2001 From: Sarbojit Sarkar Date: Thu, 7 Aug 2025 07:06:04 +0000 Subject: [PATCH 1/3] (sysman):Enabled multi process power set/get test --- .../sysman/test_sysman_power/CMakeLists.txt | 11 +- .../src/test_sysman_power.cpp | 134 ++++++++++++++++++ .../src/test_sysman_power_process_helper.cpp | 108 ++++++++++++++ 3 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp diff --git a/conformance_tests/sysman/test_sysman_power/CMakeLists.txt b/conformance_tests/sysman/test_sysman_power/CMakeLists.txt index 4d0c3642e..772d4d966 100644 --- a/conformance_tests/sysman/test_sysman_power/CMakeLists.txt +++ b/conformance_tests/sysman/test_sysman_power/CMakeLists.txt @@ -22,4 +22,13 @@ add_lzt_test( level_zero_tests::utils DEFINES USE_ZESINIT ) - +add_lzt_test_executable( + NAME test_sysman_power_process_helper + GROUP "/conformance_tests/tools/sysman" + PREFIX "process" # install to prefix so it's not confused for a test + SOURCES + src/test_sysman_power_process_helper.cpp + LINK_LIBRARIES + level_zero_tests::logging + level_zero_tests::utils +) diff --git a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp index 0612cee09..ce63397a2 100644 --- a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp +++ b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp @@ -6,13 +6,22 @@ * */ +#include +#include +#include +#include + #include "gtest/gtest.h" #include #include "logging/logging.hpp" #include "utils/utils.hpp" #include "test_harness/test_harness.hpp" #include + namespace lzt = level_zero_tests; +namespace bp = boost::process; +namespace fs = boost::filesystem; +namespace bi = boost::interprocess; #include @@ -183,6 +192,131 @@ LZT_TEST_F( } } } +struct powerInfo { + uint32_t interval; + uint32_t limit; + bool limitValueLocked; +}; +struct powerDomains { + zes_uuid_t uuid; + std::vector power_info_list; +}; +LZT_TEST_F( + POWER_TEST, + MultiProcessTestSetValidPowerLimitInParentProcessAndReadInChildProcess) { + // run test for all available devices + std::vector pd(devices.size()); + for (int d = 0; d < devices.size(); ++d) { + uint32_t count = 0; + auto p_power_handles = lzt::get_power_handles(devices[d], count); + if (count == 0) { + FAIL() << "No handles found: " + << _ze_result_t(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); + } + + // loop through all power domains and set the power limit + + // preserve initial power limit descriptors for restoration later + std::vector> power_limits_descriptors_initial(p_power_handles.size()); + for (int p = 0; p < p_power_handles.size(); ++p) { + EXPECT_NE(nullptr, p_power_handles[p]); + + uint32_t count_power = 0; + std::vector power_limits_descriptors; + auto status = lzt::get_power_limits_ext( + p_power_handles[p], &count_power, + power_limits_descriptors); + if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { + continue; + } + EXPECT_ZE_RESULT_SUCCESS(status); + //set power limit + zes_power_limit_ext_desc_t power_peak_set = {}; + for (auto &power_limits_descriptor : power_limits_descriptors) { + power_limits_descriptors_initial[p].push_back(power_limits_descriptor); + if (power_limits_descriptor.level == ZES_POWER_LEVEL_PEAK) { + power_peak_set = power_limits_descriptor; + power_peak_set.limit = power_limits_descriptor.limit - 1000; + power_limits_descriptor.limit = power_peak_set.limit; + } + } + + if (power_peak_set.limitValueLocked == false) { + // store power info into the list for sharing it with child process + powerInfo p_info; + p_info.limit = power_peak_set.limit; + p_info.interval = power_peak_set.interval; + p_info.limitValueLocked = power_peak_set.limitValueLocked; + pd[d].power_info_list.push_back(p_info); + + status = lzt::set_power_limits_ext(p_power_handles[p], &count_power, + power_limits_descriptors.data()); + if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { + continue; + } + EXPECT_ZE_RESULT_SUCCESS(status); + + // Read power limits to confirm power limit is set + zes_power_limit_ext_desc_t power_peak_get = {}; + std::vector power_limits_descriptors_get; + status = lzt::get_power_limits_ext(p_power_handles[p], &count_power, + power_limits_descriptors_get); + if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { + continue; + } + EXPECT_ZE_RESULT_SUCCESS(status); + for (const auto &p_power_limits_descriptor_get : + power_limits_descriptors_get) { + if (p_power_limits_descriptor_get.level == ZES_POWER_LEVEL_PEAK) { + power_peak_get = p_power_limits_descriptor_get; + } + } + EXPECT_EQ(power_peak_get.limitValueLocked, power_peak_set.limitValueLocked); + EXPECT_EQ(power_peak_get.interval, power_peak_set.interval); + EXPECT_EQ(power_peak_get.limit, power_peak_set.limit); + } + } + + // step 2: Launch child process and share power limits set + // create named shared object and copy all power settings + zes_uuid_t uuid = lzt::get_sysman_device_uuid(devices[d]); + + bi::shared_memory_object::remove("MultiProcPowerLimitSharedMemory"); + bi::shared_memory_object power_limit_shm(bi::create_only, "MultiProcPowerLimitSharedMemory", bi::read_write); + power_limit_shm.truncate(ZES_MAX_UUID_SIZE+pd[d].power_info_list.size()*sizeof(powerInfo)); + bi::mapped_region mapped_region(power_limit_shm, bi::read_write); + std::memcpy(mapped_region.get_address(), uuid.id, ZES_MAX_UUID_SIZE); + std::memcpy(((char*)mapped_region.get_address())+ZES_MAX_UUID_SIZE, pd[d].power_info_list.data(), pd[d].power_info_list.size()*sizeof(powerInfo)); + + // launch child process with power_handle_count + // Launch a child process and find out if child process reads same power limit set by parent process. + + // create child process + auto env = boost::this_process::environment(); + fs::path helper_path(fs::current_path() / "process"); + bp::environment child_env = env; + std::vector paths; + paths.push_back(helper_path); + fs::path helper = bp::search_path("test_sysman_power_process_helper", paths); + bp::child get_power_limit_in_child_proc(helper,bp::args({std::to_string(p_power_handles.size())}), child_env); + get_power_limit_in_child_proc.wait(); + // Need to check child process return statement to decide test pass/fail. + EXPECT_EQ(get_power_limit_in_child_proc.exit_code(), 0); + + // Step 3 : Restore power limits back to origianl + for (int p=0; p < p_power_handles.size(); ++p) { + EXPECT_NE(nullptr, p_power_handles[p]); + uint32_t count_power = 0; + auto status = lzt::set_power_limits_ext( + p_power_handles[p], &count_power, + power_limits_descriptors_initial[p].data()); // restore initial limits + if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { + continue; + } + EXPECT_ZE_RESULT_SUCCESS(status); + } + } +} LZT_TEST_F( POWER_TEST, GivenValidPowerHandleWhenRequestingPowerLimitsThenExpectzesSysmanPowerGetLimitsToReturnSameValuesTwice) { diff --git a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp new file mode 100644 index 000000000..bfdc52c3a --- /dev/null +++ b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp @@ -0,0 +1,108 @@ +/* + * + * Copyright (C) 2020-2025 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include +#include + +#include "utils/utils.hpp" +#include "test_harness/test_harness.hpp" +#include "logging/logging.hpp" + +namespace lzt = level_zero_tests; +namespace bp = boost::process; +namespace bi = boost::interprocess; + +struct powerInfo { + uint32_t interval; + uint32_t limit; + bool limitValueLocked; +}; + +void GetPowerLimitsSetByParentProcess(uint32_t power_handle_size, bool &test_result) { + //1. read shared object + bi::shared_memory_object power_limit_shm(bi::open_only, "MultiProcPowerLimitSharedMemory", bi::read_only); + bi::mapped_region region(power_limit_shm, bi::read_only); + char* data = static_cast(region.get_address()); + std::vector power_limits_set; + power_limits_set.resize(power_handle_size); + zes_uuid_t uuid; + memcpy(uuid.id, data, ZES_MAX_UUID_SIZE); + memcpy(power_limits_set.data(), data+ZES_MAX_UUID_SIZE, power_handle_size*sizeof(powerInfo)); + + //2. read power limits set for the device + auto driver = lzt::get_default_zes_driver(); + auto dev_count = lzt::get_zes_device_count(driver); + auto devices = lzt::get_zes_devices(dev_count, driver); + for (auto device : devices) { + zes_uuid_t id = lzt::get_sysman_device_uuid(device); + if (lzt::is_uuid_pair_equal(id.id, uuid.id)) { + uint32_t count = 0; + auto p_power_handles = lzt::get_power_handles(device, count); + if (count == 0) { + FAIL() << "No handles found: " + << _ze_result_t(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE); + test_result = false; + } + + for (int p = 0; p < p_power_handles.size(); ++p) { + EXPECT_NE(nullptr, p_power_handles[p]); + uint32_t count_power = 0; + zes_power_limit_ext_desc_t power_peak_get = {}; + std::vector power_limits_descriptors; + auto status = lzt::get_power_limits_ext( + p_power_handles[p], &count_power, + power_limits_descriptors); // get power limits for all descriptors + if (status == ZE_RESULT_ERROR_UNSUPPORTED_FEATURE) { + continue; + } + EXPECT_ZE_RESULT_SUCCESS(status); + for (const auto &p_power_limits_descriptor : power_limits_descriptors) { + if (p_power_limits_descriptor.level == ZES_POWER_LEVEL_PEAK) { + power_peak_get = p_power_limits_descriptor; + } + } + + EXPECT_EQ(power_peak_get.limitValueLocked, + power_limits_set[p].limitValueLocked); + EXPECT_EQ(power_peak_get.interval, + power_limits_set[p].interval); + EXPECT_EQ(power_peak_get.limit, power_limits_set[p].limit); + + // Need to notify parent process about failure + if (power_peak_get.limitValueLocked != power_limits_set[p].limitValueLocked || + power_peak_get.interval != power_limits_set[p].interval || + power_peak_get.limit != (power_limits_set[p].limit)) { + test_result = false; + return; + } + } + } + } +} + +int main(int argc, char **argv) { + if (argc != 2) { + LOG_INFO << "Insufficient argument count " < Date: Thu, 7 Aug 2025 07:16:18 +0000 Subject: [PATCH 2/3] Added few comments --- .../test_sysman_power/src/test_sysman_power.cpp | 11 +++++------ .../src/test_sysman_power_process_helper.cpp | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp index ce63397a2..d4457ad37 100644 --- a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp +++ b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp @@ -216,7 +216,8 @@ LZT_TEST_F( // loop through all power domains and set the power limit - // preserve initial power limit descriptors for restoration later + //step 1: i) Preserve initial power limit descriptors for restoration later + // ii) Set the power limit and verify the setting std::vector> power_limits_descriptors_initial(p_power_handles.size()); for (int p = 0; p < p_power_handles.size(); ++p) { EXPECT_NE(nullptr, p_power_handles[p]); @@ -230,7 +231,7 @@ LZT_TEST_F( continue; } EXPECT_ZE_RESULT_SUCCESS(status); - //set power limit + // set power limit zes_power_limit_ext_desc_t power_peak_set = {}; for (auto &power_limits_descriptor : power_limits_descriptors) { power_limits_descriptors_initial[p].push_back(power_limits_descriptor); @@ -289,9 +290,6 @@ LZT_TEST_F( std::memcpy(((char*)mapped_region.get_address())+ZES_MAX_UUID_SIZE, pd[d].power_info_list.data(), pd[d].power_info_list.size()*sizeof(powerInfo)); // launch child process with power_handle_count - // Launch a child process and find out if child process reads same power limit set by parent process. - - // create child process auto env = boost::this_process::environment(); fs::path helper_path(fs::current_path() / "process"); bp::environment child_env = env; @@ -300,7 +298,8 @@ LZT_TEST_F( fs::path helper = bp::search_path("test_sysman_power_process_helper", paths); bp::child get_power_limit_in_child_proc(helper,bp::args({std::to_string(p_power_handles.size())}), child_env); get_power_limit_in_child_proc.wait(); - // Need to check child process return statement to decide test pass/fail. + + // check child process return status to decide test pass/fail. EXPECT_EQ(get_power_limit_in_child_proc.exit_code(), 0); // Step 3 : Restore power limits back to origianl diff --git a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp index bfdc52c3a..8aed51e54 100644 --- a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp +++ b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp @@ -102,7 +102,7 @@ int main(int argc, char **argv) { bool test_result = true; GetPowerLimitsSetByParentProcess(power_handle_size, test_result); if (test_result == false) { - return 1; // test failed, report the same to partent process + return 1; // test failed, report the same to parent process } return 0; -} \ No newline at end of file +} From a723aaad3e5faebfca26a680e4f1598d2a877bfc Mon Sep 17 00:00:00 2001 From: Sarbojit Sarkar Date: Thu, 7 Aug 2025 08:53:39 +0000 Subject: [PATCH 3/3] Addressed Copilot suggestions --- .../sysman/test_sysman_power/src/test_sysman_power.cpp | 8 ++++---- .../src/test_sysman_power_process_helper.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp index d4457ad37..2d13e79f7 100644 --- a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp +++ b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power.cpp @@ -206,7 +206,7 @@ LZT_TEST_F( MultiProcessTestSetValidPowerLimitInParentProcessAndReadInChildProcess) { // run test for all available devices std::vector pd(devices.size()); - for (int d = 0; d < devices.size(); ++d) { + for (size_t d = 0; d < devices.size(); ++d) { uint32_t count = 0; auto p_power_handles = lzt::get_power_handles(devices[d], count); if (count == 0) { @@ -219,7 +219,7 @@ LZT_TEST_F( //step 1: i) Preserve initial power limit descriptors for restoration later // ii) Set the power limit and verify the setting std::vector> power_limits_descriptors_initial(p_power_handles.size()); - for (int p = 0; p < p_power_handles.size(); ++p) { + for (size_t p = 0; p < p_power_handles.size(); ++p) { EXPECT_NE(nullptr, p_power_handles[p]); uint32_t count_power = 0; @@ -302,8 +302,8 @@ LZT_TEST_F( // check child process return status to decide test pass/fail. EXPECT_EQ(get_power_limit_in_child_proc.exit_code(), 0); - // Step 3 : Restore power limits back to origianl - for (int p=0; p < p_power_handles.size(); ++p) { + // Step 3 : Restore power limits back to original + for (size_t p = 0; p < p_power_handles.size(); ++p) { EXPECT_NE(nullptr, p_power_handles[p]); uint32_t count_power = 0; auto status = lzt::set_power_limits_ext( diff --git a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp index 8aed51e54..0c7759c69 100644 --- a/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp +++ b/conformance_tests/sysman/test_sysman_power/src/test_sysman_power_process_helper.cpp @@ -49,7 +49,7 @@ void GetPowerLimitsSetByParentProcess(uint32_t power_handle_size, bool &test_res test_result = false; } - for (int p = 0; p < p_power_handles.size(); ++p) { + for (size_t p = 0; p < p_power_handles.size(); ++p) { EXPECT_NE(nullptr, p_power_handles[p]); uint32_t count_power = 0; zes_power_limit_ext_desc_t power_peak_get = {};