Metrics Add Os specific implementation Structure for IP Sampling

This patch adds OS specific implementation for IP Sampling.
Implementation for linux is provided as part of this patch.

Related-To: LOCI-2787

--- master-files
level_zero/tools/source/metrics/linux/os_metric_ip_sampling_imp_linux.cpp
level_zero/tools/source/metrics/os_metric_ip_sampling.h
level_zero/tools/source/metrics/windows/os_metric_ip_sampling_imp_windows.cpp
level_zero/tools/test/unit_tests/sources/metrics/linux/test_metric_ip_sampling_linux_prelim.cpp
level_zero/tools/test/unit_tests/sources/metrics/linux/test_metric_ip_sampling_linux_upstream.cpp
level_zero/tools/test/unit_tests/sources/metrics/windows/test_metric_ip_sampling_windows.cpp
--- master-files

Signed-off-by: Joshua Santosh Ranjan <joshua.santosh.ranjan@intel.com>
This commit is contained in:
Joshua Santosh Ranjan
2022-02-03 13:26:53 +00:00
committed by Compute-Runtime-Automation
parent 3af1d3f949
commit 10f98b45db
19 changed files with 792 additions and 4 deletions

View File

@@ -1184,4 +1184,16 @@ NEO::Device *DeviceImp::getActiveDevice() const {
return this->neoDevice;
}
uint32_t DeviceImp::getPhysicalSubDeviceId() {
if (!neoDevice->isSubDevice()) {
uint32_t deviceBitField = static_cast<uint32_t>(neoDevice->getDeviceBitfield().to_ulong());
if (neoDevice->getDeviceBitfield().count() > 1) {
// Clear all set bits other than the right most bit
deviceBitField &= ~deviceBitField + 1;
}
return Math::log2(deviceBitField);
}
return static_cast<NEO::SubDevice *>(neoDevice)->getSubDeviceIndex();
}
} // namespace L0

View File

@@ -100,6 +100,7 @@ struct DeviceImp : public Device {
bool toPhysicalSliceId(const NEO::TopologyMap &topologyMap, uint32_t &slice, uint32_t &subslice, uint32_t &deviceIndex);
bool toApiSliceId(const NEO::TopologyMap &topologyMap, uint32_t &slice, uint32_t &subslice, uint32_t deviceIndex);
uint32_t getPhysicalSubDeviceId();
bool isSubdevice = false;
void *execEnvironment = nullptr;

View File

@@ -16,6 +16,7 @@ list(APPEND L0_SRCS_TOOLS_METRICS
${CMAKE_CURRENT_SOURCE_DIR}/metric_oa_query_imp.cpp
${CMAKE_CURRENT_SOURCE_DIR}/metric_oa_query_imp.h
${CMAKE_CURRENT_SOURCE_DIR}/metric_oa_source.h
${CMAKE_CURRENT_SOURCE_DIR}/os_metric_ip_sampling.h
)
if(UNIX)

View File

@@ -8,6 +8,7 @@ set(L0_SRCS_TOOLS_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/os_metric_oa_query_imp_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_metric_oa_enumeration_imp_linux.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_metric_ip_sampling_imp_linux.cpp
)
if(UNIX)

View File

@@ -0,0 +1,197 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/helpers/constants.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/sys_calls.h"
#include "shared/source/os_interface/os_interface.h"
#include "shared/source/xe_hpc_core/hw_cmds_base.h"
#include "level_zero/core/source/device/device.h"
#include "level_zero/core/source/device/device_imp.h"
#include "level_zero/tools/source/metrics/os_metric_ip_sampling.h"
#include <algorithm>
namespace L0 {
constexpr uint32_t maxDssBufferSize = 512 * KB;
constexpr uint32_t defaultPollPeriodNs = 10000000u;
constexpr uint32_t unitReportSize = 64u;
class MetricIpSamplingLinuxImp : public MetricIpSamplingOsInterface {
public:
MetricIpSamplingLinuxImp(Device &device);
~MetricIpSamplingLinuxImp() override = default;
ze_result_t startMeasurement(uint32_t &notifyEveryNReports, uint32_t &samplingPeriodNs) override;
ze_result_t stopMeasurement() override;
ze_result_t readData(uint8_t *pRawData, size_t *pRawDataSize) override;
uint32_t getRequiredBufferSize(const uint32_t maxReportCount) override;
uint32_t getUnitReportSize() override;
bool isNReportsAvailable() override;
bool isDependencyAvailable() override;
private:
int32_t stream = -1;
Device &device;
ze_result_t getNearestSupportedSamplingUnit(uint32_t &samplingPeriodNs, uint32_t &samplingRate);
};
MetricIpSamplingLinuxImp::MetricIpSamplingLinuxImp(Device &device) : device(device) {}
ze_result_t MetricIpSamplingLinuxImp::getNearestSupportedSamplingUnit(uint32_t &samplingPeriodNs, uint32_t &samplingUnit) {
static constexpr uint64_t nsecPerSec = 1000000000ull;
static constexpr uint32_t samplingClockGranularity = 251u;
static constexpr uint32_t minSamplingUnit = 1u;
static constexpr uint32_t maxSamplingUnit = 7u;
const auto drm = device.getOsInterface().getDriverModel()->as<NEO::Drm>();
int32_t gpuTimeStampfrequency = 0;
int32_t ret = drm->getTimestampFrequency(gpuTimeStampfrequency);
if (ret < 0) {
return ZE_RESULT_ERROR_UNKNOWN;
}
uint64_t gpuClockPeriodNs = nsecPerSec / static_cast<uint64_t>(gpuTimeStampfrequency);
uint64_t numberOfClocks = samplingPeriodNs / gpuClockPeriodNs;
samplingUnit = std::clamp(static_cast<uint32_t>(numberOfClocks / samplingClockGranularity), minSamplingUnit, maxSamplingUnit);
samplingPeriodNs = samplingUnit * samplingClockGranularity * static_cast<uint32_t>(gpuClockPeriodNs);
return ZE_RESULT_SUCCESS;
}
ze_result_t MetricIpSamplingLinuxImp::startMeasurement(uint32_t &notifyEveryNReports, uint32_t &samplingPeriodNs) {
const auto drm = device.getOsInterface().getDriverModel()->as<NEO::Drm>();
uint32_t samplingUnit = 0;
if (getNearestSupportedSamplingUnit(samplingPeriodNs, samplingUnit) != ZE_RESULT_SUCCESS) {
return ZE_RESULT_ERROR_UNKNOWN;
}
DeviceImp &deviceImp = static_cast<DeviceImp &>(device);
auto ioctlHelper = drm->getIoctlHelper();
uint32_t euStallFdParameter = ioctlHelper->getEuStallFdParameter();
std::array<uint64_t, 10u> properties;
if (!ioctlHelper->getEuStallProperties(properties, maxDssBufferSize, samplingUnit, defaultPollPeriodNs, deviceImp.getPhysicalSubDeviceId())) {
return ZE_RESULT_ERROR_UNKNOWN;
}
struct drm_i915_perf_open_param param = {
.flags = I915_PERF_FLAG_FD_CLOEXEC |
euStallFdParameter |
I915_PERF_FLAG_FD_NONBLOCK,
.num_properties = sizeof(properties) / 16,
.properties_ptr = reinterpret_cast<uintptr_t>(properties.data()),
};
stream = drm->ioctl(DRM_IOCTL_I915_PERF_OPEN, &param);
if (stream < 0) {
return ZE_RESULT_ERROR_UNKNOWN;
}
int32_t ret = NEO::SysCalls::ioctl(stream, I915_PERF_IOCTL_ENABLE, 0);
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get() && (ret < 0), stderr,
"PRELIM_I915_PERF_IOCTL_ENABLE failed errno = %d | ret = %d \n", errno, ret);
return (ret == 0) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t MetricIpSamplingLinuxImp::stopMeasurement() {
int32_t ret = NEO::SysCalls::close(stream);
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get() && (ret < 0), stderr, "close() failed errno = %d | ret = %d \n",
errno, ret);
stream = -1;
return (ret == 0) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t MetricIpSamplingLinuxImp::readData(uint8_t *pRawData, size_t *pRawDataSize) {
ssize_t ret = NEO::SysCalls::pread(stream, pRawData, *pRawDataSize, 0u);
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get() && (ret < 0), stderr, "pread() failed errno = %d | ret = %d \n",
errno, ret);
if (ret >= 0) {
*pRawDataSize = ret;
return ZE_RESULT_SUCCESS;
}
*pRawDataSize = 0;
return ZE_RESULT_ERROR_UNKNOWN;
}
uint32_t MetricIpSamplingLinuxImp::getRequiredBufferSize(const uint32_t maxReportCount) {
uint32_t requiredBufferSize = getUnitReportSize() * maxReportCount;
const auto hwInfo = device.getNEODevice()->getHardwareInfo();
return std::min(requiredBufferSize, maxDssBufferSize * hwInfo.gtSystemInfo.MaxDualSubSlicesSupported);
}
uint32_t MetricIpSamplingLinuxImp::getUnitReportSize() {
return unitReportSize;
}
bool MetricIpSamplingLinuxImp::isNReportsAvailable() {
struct pollfd pollParams;
memset(&pollParams, 0, sizeof(pollParams));
DEBUG_BREAK_IF(stream == -1);
pollParams.fd = stream;
pollParams.revents = 0;
pollParams.events = POLLIN;
int32_t pollResult = NEO::SysCalls::poll(&pollParams, 1, 0u);
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get() && (pollResult < 0), stderr, "poll() failed errno = %d | pollResult = %d \n",
errno, pollResult);
if (pollResult > 0) {
return true;
}
return false;
}
bool MetricIpSamplingLinuxImp::isDependencyAvailable() {
auto hwInfo = device.getNEODevice()->getHardwareInfo();
auto isSupportedDevice = false;
if (hwInfo.platform.eProductFamily == IGFX_PVC) {
if (hwInfo.platform.usDeviceID == NEO::XE_HPC_CORE::pvcXtDeviceIds[0] ||
hwInfo.platform.usDeviceID == NEO::XE_HPC_CORE::pvcXtDeviceIds[1] ||
hwInfo.platform.usDeviceID == NEO::XE_HPC_CORE::pvcXtDeviceIds[2] ||
hwInfo.platform.usDeviceID == NEO::XE_HPC_CORE::pvcXtDeviceIds[3] ||
hwInfo.platform.usDeviceID == NEO::XE_HPC_CORE::pvcXtDeviceIds[4]) {
isSupportedDevice = true;
}
}
if (!isSupportedDevice) {
return false;
}
uint32_t notifyEveryNReports = 1u;
uint32_t samplingPeriod = 100;
ze_result_t status = startMeasurement(notifyEveryNReports, samplingPeriod);
if (stream != -1) {
stopMeasurement();
}
return status == ZE_RESULT_SUCCESS ? true : false;
}
std::unique_ptr<MetricIpSamplingOsInterface> MetricIpSamplingOsInterface::create(Device &device) {
return std::make_unique<MetricIpSamplingLinuxImp>(device);
}
} // namespace L0

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include <level_zero/zet_api.h>
#include <memory>
namespace L0 {
struct Device;
class MetricIpSamplingOsInterface {
public:
virtual ~MetricIpSamplingOsInterface() = default;
virtual ze_result_t startMeasurement(uint32_t &notifyEveryNReports, uint32_t &samplingPeriodNs) = 0;
virtual ze_result_t stopMeasurement() = 0;
virtual ze_result_t readData(uint8_t *pRawData, size_t *pRawDataSize) = 0;
virtual uint32_t getRequiredBufferSize(const uint32_t maxReportCount) = 0;
virtual uint32_t getUnitReportSize() = 0;
virtual bool isNReportsAvailable() = 0;
virtual bool isDependencyAvailable() = 0;
static std::unique_ptr<MetricIpSamplingOsInterface> create(Device &device);
};
} // namespace L0

View File

@@ -8,6 +8,7 @@ set(L0_SRCS_TOOLS_WINDOWS
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/os_metric_oa_query_imp_windows.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_metric_oa_enumeration_imp_windows.cpp
${CMAKE_CURRENT_SOURCE_DIR}/os_metric_ip_sampling_imp_windows.cpp
)
if(WIN32)

View File

@@ -0,0 +1,43 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/core/source/device/device.h"
#include "level_zero/tools/source/metrics/os_metric_ip_sampling.h"
namespace L0 {
class MetricIpSamplingWindowsImp : public MetricIpSamplingOsInterface {
public:
MetricIpSamplingWindowsImp() {}
ze_result_t startMeasurement(uint32_t &notifyEveryNReports, uint32_t &samplingPeriodNs) override {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t stopMeasurement() override {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
ze_result_t readData(uint8_t *pRawData, size_t *pRawDataSize) override {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
uint32_t getRequiredBufferSize(const uint32_t maxReportCount) override {
return 0u;
}
uint32_t getUnitReportSize() override {
return 0u;
}
bool isNReportsAvailable() override {
return false;
}
bool isDependencyAvailable() override {
return false;
}
};
std::unique_ptr<MetricIpSamplingOsInterface> MetricIpSamplingOsInterface::create(Device &device) {
return std::make_unique<MetricIpSamplingWindowsImp>();
}
} // namespace L0

View File

@@ -4,8 +4,25 @@
# SPDX-License-Identifier: MIT
#
if(UNIX)
target_sources(${TARGET_NAME} PRIVATE
set(L0_TOOLS_METRICS_LINUX_TESTS_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
${CMAKE_CURRENT_SOURCE_DIR}/test_metric_oa_query_pool_linux.cpp
)
if(NEO_ENABLE_i915_PRELIM_DETECTION)
list(APPEND L0_TOOLS_METRICS_LINUX_TESTS_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/test_metric_ip_sampling_linux_prelim.cpp
)
endif()
if("${BRANCH_TYPE}" STREQUAL "")
list(APPEND L0_TOOLS_METRICS_LINUX_TESTS_LINUX
${CMAKE_CURRENT_SOURCE_DIR}/test_metric_ip_sampling_linux_upstream.cpp
)
endif()
if(UNIX)
target_sources(${TARGET_NAME} PRIVATE
${L0_TOOLS_METRICS_LINUX_TESTS_LINUX}
)
endif()

View File

@@ -0,0 +1,301 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/os_interface/linux/drm_neo.h"
#include "shared/source/os_interface/linux/ioctl_helper.h"
#include "shared/source/os_interface/linux/sys_calls.h"
#include "shared/test/common/libult/linux/drm_mock.h"
#include "shared/test/common/mocks/ult_device_factory.h"
#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h"
#include "shared/test/common/test_macros/test.h"
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
#include "level_zero/tools/source/metrics/os_metric_ip_sampling.h"
namespace NEO {
namespace SysCalls {
extern int closeFuncRetVal;
} // namespace SysCalls
} // namespace NEO
namespace L0 {
namespace ult {
class IoctlHelperPrelim20Mock : public NEO::IoctlHelperPrelim20 {
bool getEuStallProperties(std::array<uint64_t, 10u> &properties, uint64_t dssBufferSize, uint64_t samplingRate, uint64_t pollPeriod, uint64_t engineInstance) override {
return false;
}
};
class DrmPrelimMock : public DrmMock {
public:
DrmPrelimMock(RootDeviceEnvironment &rootDeviceEnvironment) : DrmPrelimMock(rootDeviceEnvironment, defaultHwInfo.get()) {}
DrmPrelimMock(RootDeviceEnvironment &rootDeviceEnvironment, HardwareInfo *inputHwInfo) : DrmMock(rootDeviceEnvironment) {
inputHwInfo->gtSystemInfo.MaxDualSubSlicesSupported = 64;
rootDeviceEnvironment.setHwInfo(inputHwInfo);
setupIoctlHelper(rootDeviceEnvironment.getHardwareInfo()->platform.eProductFamily);
recentProperties.fill(255);
}
void getPrelimVersion(std::string &prelimVersion) override {
prelimVersion = "2.0";
}
int handleRemainingRequests(unsigned long request, void *arg) override {
if (request == DRM_IOCTL_I915_PERF_OPEN) {
drm_i915_perf_open_param *param = reinterpret_cast<drm_i915_perf_open_param *>(arg);
std::memcpy(recentProperties.data(), reinterpret_cast<void *>(param->properties_ptr), param->num_properties * 8 * 2);
return ioctli915PerfOpenReturn;
}
return -1;
}
void setIoctlHelperPrelim20Mock() {
backUpIoctlHelper = std::move(ioctlHelper);
ioctlHelper = static_cast<std::unique_ptr<NEO::IoctlHelper>>(std::make_unique<IoctlHelperPrelim20Mock>());
}
void restoreIoctlHelperPrelim20() {
ioctlHelper = std::move(backUpIoctlHelper);
}
std::unique_ptr<NEO::IoctlHelper> backUpIoctlHelper;
int ioctli915PerfOpenReturn = 1;
std::array<uint64_t, 10u> recentProperties{};
};
class MetricIpSamplingLinuxTestPrelim : public DeviceFixture,
public ::testing::Test {
public:
void SetUp() override {
DeviceFixture::SetUp();
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->osInterface = std::make_unique<NEO::OSInterface>();
auto &osInterface = device->getOsInterface();
osInterface.setDriverModel(std::make_unique<DrmPrelimMock>(const_cast<NEO::RootDeviceEnvironment &>(neoDevice->getRootDeviceEnvironment())));
metricIpSamplingOsInterface = MetricIpSamplingOsInterface::create(static_cast<L0::Device &>(*device));
}
void TearDown() override {
DeviceFixture::TearDown();
}
std::unique_ptr<MetricIpSamplingOsInterface> metricIpSamplingOsInterface = nullptr;
};
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, givenCorrectArgumentsWhenStartMeasurementIsCalledThenReturnSuccess, IsPVC) {
constexpr uint32_t samplingGranularity = 251;
constexpr uint32_t gpuClockPeriodNs = 1000000;
constexpr uint32_t samplingUnit = 3;
uint32_t notifyEveryNReports = 0, samplingPeriodNs = samplingGranularity * samplingUnit * gpuClockPeriodNs;
EXPECT_EQ(metricIpSamplingOsInterface->startMeasurement(notifyEveryNReports, samplingPeriodNs), ZE_RESULT_SUCCESS);
EXPECT_EQ(samplingPeriodNs, samplingGranularity * samplingUnit * gpuClockPeriodNs);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, givenGetTimestampFrequencyFailsWhenStartMeasurementIsCalledThenReturnFailure, IsPVC) {
auto drm = static_cast<DrmPrelimMock *>(device->getOsInterface().getDriverModel()->as<NEO::Drm>());
VariableBackup<int> backupCsTimeStampFrequency(&drm->storedCsTimestampFrequency, 0);
VariableBackup<int> backupStoredRetVal(&drm->storedRetVal, -1);
uint32_t notifyEveryNReports = 0, samplingPeriodNs = 10000;
EXPECT_EQ(metricIpSamplingOsInterface->startMeasurement(notifyEveryNReports, samplingPeriodNs), ZE_RESULT_ERROR_UNKNOWN);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, givenIoctlI915PerfOpenFailsWhenStartMeasurementIsCalledThenReturnFailure, IsPVC) {
auto drm = static_cast<DrmPrelimMock *>(device->getOsInterface().getDriverModel()->as<NEO::Drm>());
uint32_t notifyEveryNReports = 0, samplingPeriodNs = 10000;
VariableBackup<int> backupI915PerfOpenReturn(&drm->ioctli915PerfOpenReturn, -1);
EXPECT_EQ(metricIpSamplingOsInterface->startMeasurement(notifyEveryNReports, samplingPeriodNs), ZE_RESULT_ERROR_UNKNOWN);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, givenI915PerfIoctlEnableFailsWhenStartMeasurementIsCalledThenReturnFailure, IsPVC) {
uint32_t notifyEveryNReports = 0, samplingPeriodNs = 10000;
VariableBackup<decltype(SysCalls::sysCallsIoctl)> mockIoctl(&SysCalls::sysCallsIoctl, [](int fileDescriptor, unsigned long int request, void *arg) -> int {
if (request == I915_PERF_IOCTL_ENABLE) {
return -1;
}
return 0;
});
EXPECT_EQ(metricIpSamplingOsInterface->startMeasurement(notifyEveryNReports, samplingPeriodNs), ZE_RESULT_ERROR_UNKNOWN);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, givenCloseSucceedsWhenStopMeasurementIsCalledThenReturnSuccess, IsPVC) {
VariableBackup<int> backupCloseFuncRetval(&NEO::SysCalls::closeFuncRetVal, 0);
EXPECT_EQ(metricIpSamplingOsInterface->stopMeasurement(), ZE_RESULT_SUCCESS);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, givenCloseFailsWhenStopMeasurementIsCalledThenReturnFailure, IsPVC) {
VariableBackup<int> backupCloseFuncRetval(&NEO::SysCalls::closeFuncRetVal, -1);
EXPECT_EQ(metricIpSamplingOsInterface->stopMeasurement(), ZE_RESULT_ERROR_UNKNOWN);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, givenPreadSucceedsWhenReadDataIsCalledThenReturnSuccess, IsPVC) {
VariableBackup<decltype(SysCalls::sysCallsPread)> mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
return 1;
});
uint8_t pRawData = 0u;
size_t pRawDataSize = 0;
EXPECT_EQ(metricIpSamplingOsInterface->readData(&pRawData, &pRawDataSize), ZE_RESULT_SUCCESS);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, givenPreadFailsWhenReadDataIsCalledThenReturnFailure, IsPVC) {
VariableBackup<decltype(SysCalls::sysCallsPread)> mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t {
return -1;
});
uint8_t pRawData = 0u;
size_t pRawDataSize = 0;
EXPECT_EQ(metricIpSamplingOsInterface->readData(&pRawData, &pRawDataSize), ZE_RESULT_ERROR_UNKNOWN);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, WhenGetRequiredBufferSizeIsCalledThenCorrectSizeIsReturned, IsPVC) {
constexpr uint32_t unitReportSize = 64;
EXPECT_EQ(metricIpSamplingOsInterface->getRequiredBufferSize(10), unitReportSize * 10);
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, GivenPollIsSuccessfulWhenisNReportsAvailableIsCalledThenReturnSuccess, IsPVC) {
VariableBackup<decltype(SysCalls::sysCallsPoll)> mockPoll(&SysCalls::sysCallsPoll, [](struct pollfd *pollFd, unsigned long int numberOfFds, int timeout) -> int {
return 1;
});
EXPECT_TRUE(metricIpSamplingOsInterface->isNReportsAvailable());
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, GivenPollIsFailureWhenisNReportsAvailableIsCalledThenReturnFailure, IsPVC) {
VariableBackup<decltype(SysCalls::sysCallsPoll)> mockPoll(&SysCalls::sysCallsPoll, [](struct pollfd *pollFd, unsigned long int numberOfFds, int timeout) -> int {
return -1;
});
EXPECT_FALSE(metricIpSamplingOsInterface->isNReportsAvailable());
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, GivenUnsupportedProductFamilyIsUsedWhenIsDependencyAvailableIsCalledThenReturnFailure, IsDG2) {
auto hwInfo = neoDevice->getRootDeviceEnvironment().getMutableHardwareInfo();
hwInfo->platform.eProductFamily = productFamily;
EXPECT_FALSE(metricIpSamplingOsInterface->isDependencyAvailable());
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, GivenSupportedProductFamilyAndUnsupportedDeviceIdIsUsedWhenIsDependencyAvailableIsCalledThenReturnFailure, IsPVC) {
auto hwInfo = neoDevice->getRootDeviceEnvironment().getMutableHardwareInfo();
hwInfo->platform.eProductFamily = productFamily;
hwInfo->platform.usDeviceID = NEO::XE_HPC_CORE::pvcXlDeviceId;
EXPECT_FALSE(metricIpSamplingOsInterface->isDependencyAvailable());
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, GivenSupportedProductFamilyAndSupportedDeviceIdIsUsedWhenIsDependencyAvailableIsCalledThenReturnFailure, IsPVC) {
auto hwInfo = neoDevice->getRootDeviceEnvironment().getMutableHardwareInfo();
hwInfo->platform.eProductFamily = productFamily;
const std::vector<uint32_t> supportedDeviceIds = {
NEO::XE_HPC_CORE::pvcXtDeviceIds[0],
NEO::XE_HPC_CORE::pvcXtDeviceIds[1],
NEO::XE_HPC_CORE::pvcXtDeviceIds[2],
NEO::XE_HPC_CORE::pvcXtDeviceIds[3],
NEO::XE_HPC_CORE::pvcXtDeviceIds[4]};
for (uint32_t deviceId : supportedDeviceIds) {
hwInfo->platform.usDeviceID = deviceId;
EXPECT_TRUE(metricIpSamplingOsInterface->isDependencyAvailable());
}
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, GivenDriverOpenFailsWhenIsDependencyAvailableIsCalledThenReturnFailure, IsPVC) {
auto hwInfo = neoDevice->getRootDeviceEnvironment().getMutableHardwareInfo();
hwInfo->platform.eProductFamily = productFamily;
hwInfo->platform.usDeviceID = NEO::XE_HPC_CORE::pvcXtDeviceIds[0];
auto drm = static_cast<DrmPrelimMock *>(device->getOsInterface().getDriverModel()->as<NEO::Drm>());
VariableBackup<int> backupCsTimeStampFrequency(&drm->storedCsTimestampFrequency, 0);
VariableBackup<int> backupStoredRetVal(&drm->storedRetVal, -1);
EXPECT_FALSE(metricIpSamplingOsInterface->isDependencyAvailable());
}
HWTEST2_F(MetricIpSamplingLinuxTestPrelim, GivenIoctlHelperFailsWhenIsDependencyAvailableIsCalledThenReturnFailure, IsPVC) {
auto hwInfo = neoDevice->getRootDeviceEnvironment().getMutableHardwareInfo();
hwInfo->platform.eProductFamily = productFamily;
hwInfo->platform.usDeviceID = NEO::XE_HPC_CORE::pvcXtDeviceIds[0];
auto drm = static_cast<DrmPrelimMock *>(device->getOsInterface().getDriverModel()->as<NEO::Drm>());
drm->setIoctlHelperPrelim20Mock();
EXPECT_FALSE(metricIpSamplingOsInterface->isDependencyAvailable());
drm->restoreIoctlHelperPrelim20();
}
struct MetricIpSamplingLinuxMultiDeviceTest : public ::testing::Test {
std::unique_ptr<UltDeviceFactory> createDevices(uint32_t numSubDevices) {
DebugManager.flags.CreateMultipleSubDevices.set(numSubDevices);
NEO::ExecutionEnvironment *executionEnvironment = new MockExecutionEnvironment(defaultHwInfo.get(), false, 1);
executionEnvironment->parseAffinityMask();
executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(new OSInterface);
executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(
std::make_unique<DrmPrelimMock>(const_cast<NEO::RootDeviceEnvironment &>(*executionEnvironment->rootDeviceEnvironments[0])));
return std::make_unique<UltDeviceFactory>(1, numSubDevices, *executionEnvironment);
}
DebugManagerStateRestore restorer;
};
HWTEST2_F(MetricIpSamplingLinuxMultiDeviceTest, GivenCombinationOfAffinityMaskWhenStartMeasurementIsCalledForRootDeviceThenInstanceIdIsCorrect, IsPVC) {
DebugManager.flags.ZE_AFFINITY_MASK.set("0.1,0.2,0.3");
auto deviceFactory = createDevices(4);
auto driverHandle = std::make_unique<DriverHandleImp>();
ze_result_t returnValue = ZE_RESULT_SUCCESS;
auto rootDevice = std::unique_ptr<L0::Device>(L0::Device::create(driverHandle.get(), deviceFactory->rootDevices[0], false, &returnValue));
auto metricIpSamplingOsInterface = MetricIpSamplingOsInterface::create(static_cast<L0::Device &>(*rootDevice));
uint32_t notifyEveryNReports = 0, samplingPeriodNs = 10000;
EXPECT_EQ(metricIpSamplingOsInterface->startMeasurement(notifyEveryNReports, samplingPeriodNs), ZE_RESULT_SUCCESS);
// verifying engine instance is set correctly
auto drm = static_cast<DrmPrelimMock *>(rootDevice->getOsInterface().getDriverModel()->as<NEO::Drm>());
EXPECT_EQ(drm->recentProperties[9], 1ull);
}
HWTEST2_F(MetricIpSamplingLinuxMultiDeviceTest, GivenCombinationOfAffinityMaskWhenStartMeasurementIsCalledForSubDeviceThenInstanceIdIsCorrect, IsPVC) {
DebugManager.flags.ZE_AFFINITY_MASK.set("0.2,0.3");
auto deviceFactory = createDevices(4);
auto driverHandle = std::make_unique<DriverHandleImp>();
ze_result_t returnValue = ZE_RESULT_SUCCESS;
auto rootDevice = std::unique_ptr<L0::Device>(L0::Device::create(driverHandle.get(), deviceFactory->rootDevices[0], false, &returnValue));
uint32_t subDeviceCount = 2;
ze_device_handle_t subDevices[2] = {};
rootDevice->getSubDevices(&subDeviceCount, subDevices);
auto metricIpSamplingOsInterface = MetricIpSamplingOsInterface::create(static_cast<L0::Device &>(*subDevices[0]));
uint32_t notifyEveryNReports = 0, samplingPeriodNs = 10000;
EXPECT_EQ(metricIpSamplingOsInterface->startMeasurement(notifyEveryNReports, samplingPeriodNs), ZE_RESULT_SUCCESS);
// verifying engine instance is set correctly
auto drm = static_cast<DrmPrelimMock *>(rootDevice->getOsInterface().getDriverModel()->as<NEO::Drm>());
EXPECT_EQ(drm->recentProperties[9], 2ull);
metricIpSamplingOsInterface = MetricIpSamplingOsInterface::create(static_cast<L0::Device &>(*subDevices[1]));
EXPECT_EQ(metricIpSamplingOsInterface->startMeasurement(notifyEveryNReports, samplingPeriodNs), ZE_RESULT_SUCCESS);
EXPECT_EQ(drm->recentProperties[9], 3ull);
}
} // namespace ult
} // namespace L0

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/test/common/libult/linux/drm_mock.h"
#include "shared/test/common/test_macros/test.h"
#include "level_zero/tools/source/metrics/os_metric_ip_sampling.h"
#include "level_zero/tools/test/unit_tests/sources/metrics/mock_metric_oa.h"
namespace L0 {
namespace ult {
class DrmTipMock : public DrmMock {
public:
DrmTipMock(RootDeviceEnvironment &rootDeviceEnvironment) : DrmTipMock(rootDeviceEnvironment, defaultHwInfo.get()) {}
DrmTipMock(RootDeviceEnvironment &rootDeviceEnvironment, HardwareInfo *inputHwInfo) : DrmMock(rootDeviceEnvironment) {
rootDeviceEnvironment.setHwInfo(inputHwInfo);
setupIoctlHelper(rootDeviceEnvironment.getHardwareInfo()->platform.eProductFamily);
}
void getPrelimVersion(std::string &prelimVersion) override {
prelimVersion = "";
}
};
class MetricIpSamplingLinuxTestUpstream : public MetricContextFixture,
public ::testing::Test {
public:
void SetUp() override {
MetricContextFixture::SetUp();
neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[device->getRootDeviceIndex()]->osInterface = std::make_unique<NEO::OSInterface>();
auto &osInterface = device->getOsInterface();
osInterface.setDriverModel(std::make_unique<DrmTipMock>(const_cast<NEO::RootDeviceEnvironment &>(neoDevice->getRootDeviceEnvironment())));
metricIpSamplingOsInterface = MetricIpSamplingOsInterface::create(static_cast<L0::Device &>(*device));
}
void TearDown() override {
MetricContextFixture::TearDown();
}
std::unique_ptr<MetricIpSamplingOsInterface> metricIpSamplingOsInterface = nullptr;
};
HWTEST2_F(MetricIpSamplingLinuxTestUpstream, GivenSupportedProductFamilyAndSupportedDeviceIdIsUsedForUpstreamWhenIsDependencyAvailableIsCalledThenReturnFailure, IsPVC) {
auto hwInfo = neoDevice->getRootDeviceEnvironment().getMutableHardwareInfo();
hwInfo->platform.eProductFamily = productFamily;
const std::vector<uint32_t> supportedDeviceIds = {
NEO::XE_HPC_CORE::pvcXtDeviceIds[0],
NEO::XE_HPC_CORE::pvcXtDeviceIds[1],
NEO::XE_HPC_CORE::pvcXtDeviceIds[2],
NEO::XE_HPC_CORE::pvcXtDeviceIds[3],
NEO::XE_HPC_CORE::pvcXtDeviceIds[4]};
for (uint32_t deviceId : supportedDeviceIds) {
hwInfo->platform.usDeviceID = deviceId;
EXPECT_FALSE(metricIpSamplingOsInterface->isDependencyAvailable());
}
}
} // namespace ult
} // namespace L0

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/test/common/test_macros/test.h"
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
#include "level_zero/tools/source/metrics/os_metric_ip_sampling.h"
using ::testing::_;
using ::testing::Return;
namespace L0 {
namespace ult {
class MetricIpSamplingWindowsTest : public DeviceFixture,
public ::testing::Test {
public:
void SetUp() override {
DeviceFixture::SetUp();
metricIpSamplingOsInterface = MetricIpSamplingOsInterface::create(static_cast<L0::Device &>(*device));
}
void TearDown() override {
DeviceFixture::TearDown();
}
std::unique_ptr<MetricIpSamplingOsInterface> metricIpSamplingOsInterface = nullptr;
};
TEST_F(MetricIpSamplingWindowsTest, WhenIpSamplingOsInterfaceIsUsedReturnUnsupported) {
EXPECT_FALSE(metricIpSamplingOsInterface->isDependencyAvailable());
EXPECT_FALSE(metricIpSamplingOsInterface->isNReportsAvailable());
EXPECT_EQ(metricIpSamplingOsInterface->getRequiredBufferSize(0), 0);
EXPECT_EQ(metricIpSamplingOsInterface->getUnitReportSize(), 0);
EXPECT_EQ(metricIpSamplingOsInterface->readData(nullptr, nullptr), ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
uint32_t dummy;
EXPECT_EQ(metricIpSamplingOsInterface->startMeasurement(dummy, dummy), ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
EXPECT_EQ(metricIpSamplingOsInterface->stopMeasurement(), ZE_RESULT_ERROR_UNSUPPORTED_FEATURE);
}
} // namespace ult
} // namespace L0

View File

@@ -112,6 +112,8 @@ class IoctlHelper {
virtual std::optional<uint64_t> getCopyClassSaturateLinkCapability() = 0;
virtual int vmBind(Drm *drm, const VmBindParams &vmBindParams) = 0;
virtual int vmUnbind(Drm *drm, const VmBindParams &vmBindParams) = 0;
virtual bool getEuStallProperties(std::array<uint64_t, 10u> &properties, uint64_t dssBufferSize, uint64_t samplingRate, uint64_t pollPeriod, uint64_t engineInstance) = 0;
virtual uint32_t getEuStallFdParameter() = 0;
};
class IoctlHelperUpstream : public IoctlHelper {
@@ -155,6 +157,8 @@ class IoctlHelperUpstream : public IoctlHelper {
std::optional<uint64_t> getCopyClassSaturateLinkCapability() override;
int vmBind(Drm *drm, const VmBindParams &vmBindParams) override;
int vmUnbind(Drm *drm, const VmBindParams &vmBindParams) override;
bool getEuStallProperties(std::array<uint64_t, 10u> &properties, uint64_t dssBufferSize, uint64_t samplingRate, uint64_t pollPeriod, uint64_t engineInstance) override;
uint32_t getEuStallFdParameter() override;
};
template <PRODUCT_FAMILY gfxProduct>
@@ -211,6 +215,8 @@ class IoctlHelperPrelim20 : public IoctlHelper {
std::optional<uint64_t> getCopyClassSaturateLinkCapability() override;
int vmBind(Drm *drm, const VmBindParams &vmBindParams) override;
int vmUnbind(Drm *drm, const VmBindParams &vmBindParams) override;
bool getEuStallProperties(std::array<uint64_t, 10u> &properties, uint64_t dssBufferSize, uint64_t samplingRate, uint64_t pollPeriod, uint64_t engineInstance) override;
uint32_t getEuStallFdParameter() override;
};
} // namespace NEO

View File

@@ -319,6 +319,24 @@ int32_t IoctlHelperPrelim20::getComputeEngineClass() {
std::optional<int> IoctlHelperPrelim20::getHasPageFaultParamId() {
return PRELIM_I915_PARAM_HAS_PAGE_FAULT;
};
bool IoctlHelperPrelim20::getEuStallProperties(std::array<uint64_t, 10u> &properties, uint64_t dssBufferSize, uint64_t samplingRate, uint64_t pollPeriod, uint64_t engineInstance) {
properties[0] = PRELIM_DRM_I915_EU_STALL_PROP_BUF_SZ;
properties[1] = dssBufferSize;
properties[2] = PRELIM_DRM_I915_EU_STALL_PROP_SAMPLE_RATE;
properties[3] = samplingRate;
properties[4] = PRELIM_DRM_I915_EU_STALL_PROP_POLL_PERIOD;
properties[5] = pollPeriod;
properties[6] = PRELIM_DRM_I915_EU_STALL_PROP_ENGINE_CLASS;
properties[7] = PRELIM_I915_ENGINE_CLASS_COMPUTE;
properties[8] = PRELIM_DRM_I915_EU_STALL_PROP_ENGINE_INSTANCE;
properties[9] = engineInstance;
return true;
}
uint32_t IoctlHelperPrelim20::getEuStallFdParameter() {
return PRELIM_I915_PERF_FLAG_FD_EU_STALL;
}
std::unique_ptr<uint8_t[]> IoctlHelperPrelim20::createVmControlExtRegion(const std::optional<MemoryClassInstance> &regionInstanceClass) {

View File

@@ -164,6 +164,13 @@ bool IoctlHelperUpstream::completionFenceExtensionSupported(const HardwareInfo &
std::optional<int> IoctlHelperUpstream::getHasPageFaultParamId() {
return std::nullopt;
};
bool IoctlHelperUpstream::getEuStallProperties(std::array<uint64_t, 10u> &properties, uint64_t dssBufferSize, uint64_t samplingRate, uint64_t pollPeriod, uint64_t engineInstance) {
return false;
}
uint32_t IoctlHelperUpstream::getEuStallFdParameter() {
return 0u;
}
std::unique_ptr<uint8_t[]> IoctlHelperUpstream::createVmControlExtRegion(const std::optional<MemoryClassInstance> &regionInstanceClass) {
return {};

View File

@@ -47,6 +47,8 @@ bool isInvalidAILTest = false;
int (*sysCallsOpen)(const char *pathname, int flags) = nullptr;
ssize_t (*sysCallsPread)(int fd, void *buf, size_t count, off_t offset) = nullptr;
int (*sysCallsReadlink)(const char *path, char *buf, size_t bufsize) = nullptr;
int (*sysCallsIoctl)(int fileDescriptor, unsigned long int request, void *arg) = nullptr;
int (*sysCallsPoll)(struct pollfd *pollFd, unsigned long int numberOfFds, int timeout) = nullptr;
int close(int fileDescriptor) {
closeFuncCalled++;
@@ -77,6 +79,11 @@ void *dlopen(const char *filename, int flag) {
}
int ioctl(int fileDescriptor, unsigned long int request, void *arg) {
if (sysCallsIoctl != nullptr) {
return sysCallsIoctl(fileDescriptor, request, arg);
}
if (fileDescriptor == fakeFileDescriptor) {
if (request == DRM_IOCTL_VERSION) {
auto pVersion = static_cast<drm_version_t *>(arg);
@@ -157,6 +164,9 @@ int getDevicePath(int deviceFd, char *buf, size_t &bufSize) {
}
int poll(struct pollfd *pollFd, unsigned long int numberOfFds, int timeout) {
if (sysCallsPoll != nullptr) {
return sysCallsPoll(pollFd, numberOfFds, timeout);
}
return 0;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2021 Intel Corporation
* Copyright (C) 2021-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -13,6 +13,8 @@ namespace SysCalls {
extern int (*sysCallsOpen)(const char *pathname, int flags);
extern ssize_t (*sysCallsPread)(int fd, void *buf, size_t count, off_t offset);
extern int (*sysCallsReadlink)(const char *path, char *buf, size_t bufsize);
extern int (*sysCallsIoctl)(int fileDescriptor, unsigned long int request, void *arg);
extern int (*sysCallsPoll)(struct pollfd *pollFd, unsigned long int numberOfFds, int timeout);
} // namespace SysCalls
} // namespace NEO

View File

@@ -241,3 +241,22 @@ TEST_F(IoctlPrelimHelperTests, givenValidInputWhenFillVmBindSyncFenceThenProperV
vmBindExtSyncFence.release();
}
TEST_F(IoctlPrelimHelperTests, givenPrelimWhenGettingEuStallPropertiesThenCorrectPropertiesAreReturned) {
std::array<uint64_t, 10u> properties = {};
EXPECT_TRUE(ioctlHelper.getEuStallProperties(properties, 0x101, 0x102, 0x103, 1));
EXPECT_EQ(properties[0], PRELIM_DRM_I915_EU_STALL_PROP_BUF_SZ);
EXPECT_EQ(properties[1], 0x101u);
EXPECT_EQ(properties[2], PRELIM_DRM_I915_EU_STALL_PROP_SAMPLE_RATE);
EXPECT_EQ(properties[3], 0x102u);
EXPECT_EQ(properties[4], PRELIM_DRM_I915_EU_STALL_PROP_POLL_PERIOD);
EXPECT_EQ(properties[5], 0x103u);
EXPECT_EQ(properties[6], PRELIM_DRM_I915_EU_STALL_PROP_ENGINE_CLASS);
EXPECT_EQ(properties[7], PRELIM_I915_ENGINE_CLASS_COMPUTE);
EXPECT_EQ(properties[8], PRELIM_DRM_I915_EU_STALL_PROP_ENGINE_INSTANCE);
EXPECT_EQ(properties[9], 1u);
}
TEST_F(IoctlPrelimHelperTests, givenPrelimWhenGettingEuStallFdParameterThenCorrectIoctlValueIsReturned) {
EXPECT_EQ(static_cast<uint32_t>(PRELIM_I915_PERF_FLAG_FD_EU_STALL), ioctlHelper.getEuStallFdParameter());
}

View File

@@ -316,3 +316,14 @@ TEST(IoctlHelperTestsUpstream, whenVmUnbindIsCalledThenZeroIsReturned) {
VmBindParams vmBindParams{};
EXPECT_EQ(0, ioctlHelper.vmUnbind(drm.get(), vmBindParams));
}
TEST(IoctlHelperTestsUpstream, givenUpstreamWhenGettingEuStallPropertiesThenFailureIsReturned) {
IoctlHelperUpstream ioctlHelper{};
std::array<uint64_t, 10u> properties = {};
EXPECT_FALSE(ioctlHelper.getEuStallProperties(properties, 0x101, 0x102, 0x103, 1));
}
TEST(IoctlHelperTestsUpstream, givenUpstreamWhenGettingEuStallFdParameterThenZeroIsReturned) {
IoctlHelperUpstream ioctlHelper{};
EXPECT_EQ(0u, ioctlHelper.getEuStallFdParameter());
}