compute-runtime/level_zero/sysman/source/shared/windows/pmt/sysman_pmt.cpp

229 lines
9.1 KiB
C++

/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "level_zero/sysman/source/shared/windows/pmt/sysman_pmt.h"
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/helpers/debug_helpers.h"
namespace L0 {
namespace Sysman {
ze_result_t PlatformMonitoringTech::readValue(const std::string &key, uint32_t &value) {
auto offset = keyOffsetMap.find(key);
if (offset == keyOffsetMap.end()) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Key %s has not been defined in key offset map.\n", key.c_str());
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
PmtSysman::PmtTelemetryRead readRequest = {0};
readRequest.version = 0;
readRequest.index = (offset->second).second;
readRequest.offset = baseOffset + (offset->second).first;
readRequest.count = 1;
uint32_t bytesReturned = 0;
auto res = ioctlReadWriteData(deviceInterface, PmtSysman::IoctlPmtGetTelemtryDword, (void *)&readRequest, sizeof(PmtSysman::PmtTelemetryRead), &value, sizeof(uint32_t), &bytesReturned);
if (res == ZE_RESULT_SUCCESS && value != NULL && bytesReturned != 0) {
return ZE_RESULT_SUCCESS;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Ioctl call could not return a valid value for register key %s\n", key.c_str());
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t PlatformMonitoringTech::readValue(const std::string &key, uint64_t &value) {
auto offset = keyOffsetMap.find(key);
if (offset == keyOffsetMap.end()) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Key %s has not been defined in key offset map.\n", key.c_str());
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
PmtSysman::PmtTelemetryRead readRequest = {0};
readRequest.version = 0;
readRequest.index = (offset->second).second;
readRequest.offset = baseOffset + (offset->second).first;
readRequest.count = 1;
uint32_t bytesReturned = 0;
auto res = ioctlReadWriteData(deviceInterface, PmtSysman::IoctlPmtGetTelemtryQword, (void *)&readRequest, sizeof(PmtSysman::PmtTelemetryRead), &value, sizeof(uint64_t), &bytesReturned);
if (res == ZE_RESULT_SUCCESS && value != NULL && bytesReturned != 0) {
return ZE_RESULT_SUCCESS;
}
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Ioctl call could not return a valid value for register key %s\n", key.c_str());
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t PlatformMonitoringTech::getGuid() {
ze_result_t status;
unsigned long sizeNeeded;
PmtSysman::PmtTelemetryDiscovery *telemetryDiscovery = nullptr;
// Get Telmetry Discovery size
status = ioctlReadWriteData(deviceInterface, PmtSysman::IoctlPmtGetTelemetryDiscoverySize, NULL, 0, (void *)&sizeNeeded, sizeof(sizeNeeded), NULL);
if (status != ZE_RESULT_SUCCESS || sizeNeeded == 0) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Ioctl call could not return a valid value for the PMT interface telemetry size needed\n");
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
telemetryDiscovery = (PmtSysman::PmtTelemetryDiscovery *)heapAllocFunction(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeNeeded);
if (telemetryDiscovery == nullptr) {
return ZE_RESULT_ERROR_UNKNOWN;
}
// Get Telmetry Discovery Structure
status = ioctlReadWriteData(deviceInterface, PmtSysman::IoctlPmtGetTelemetryDiscovery, NULL, 0, (void *)telemetryDiscovery, sizeNeeded, NULL);
if (status != ZE_RESULT_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Ioctl call could not return a valid value for the PMT telemetry structure which provides the guids supported.\n");
DEBUG_BREAK_IF(true);
heapFreeFunction(GetProcessHeap(), 0, telemetryDiscovery);
return ZE_RESULT_ERROR_UNKNOWN;
}
auto maxEntriesCount = (sizeNeeded - offsetof(PmtSysman::PmtTelemetryDiscovery, telemetry)) / sizeof(PmtSysman::PmtTelemetryEntry);
if (telemetryDiscovery->count > maxEntriesCount) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr, "Incorrect telemetry entries count.\n");
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
for (uint32_t i = 0; i < telemetryDiscovery->count; i++) {
if (telemetryDiscovery->telemetry[i].index < PmtSysman::PmtMaxInterfaces) {
guidToIndexList[telemetryDiscovery->telemetry[i].index] = telemetryDiscovery->telemetry[i].guid;
} else {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Telemetry index is out of range.\n");
DEBUG_BREAK_IF(true);
heapFreeFunction(GetProcessHeap(), 0, telemetryDiscovery);
return ZE_RESULT_ERROR_UNKNOWN;
}
}
return heapFreeFunction(GetProcessHeap(), 0, telemetryDiscovery) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN;
}
ze_result_t PlatformMonitoringTech::init() {
ze_result_t result = getGuid();
if (result != ZE_RESULT_SUCCESS) {
return result;
}
result = getKeyOffsetMap(keyOffsetMap);
return result;
}
std::unique_ptr<PlatformMonitoringTech> PlatformMonitoringTech::create() {
std::vector<wchar_t> deviceInterface;
if (enumeratePMTInterface(&PmtSysman::GuidIntefacePmtTelemetry, deviceInterface) == ZE_RESULT_SUCCESS) {
std::unique_ptr<PlatformMonitoringTech> pPmt;
pPmt = std::make_unique<PlatformMonitoringTech>(deviceInterface);
UNRECOVERABLE_IF(nullptr == pPmt);
if (pPmt->init() != ZE_RESULT_SUCCESS) {
pPmt.reset(nullptr);
}
return pPmt;
}
return nullptr;
}
PlatformMonitoringTech::~PlatformMonitoringTech() {
}
ze_result_t PlatformMonitoringTech::enumeratePMTInterface(const GUID *guid, std::vector<wchar_t> &deviceInterface) {
unsigned long cmListCharCount = 0;
CONFIGRET status = CR_SUCCESS;
do {
// Get the total size of list of all instances
// N.B. Size returned is total length in "characters"
status = NEO::SysCalls::cmGetDeviceInterfaceListSize(&cmListCharCount, (LPGUID)guid, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
if (status != CR_SUCCESS) {
break;
}
// Free previous allocation if present.
if (!deviceInterface.empty()) {
deviceInterface.clear();
}
// Allocate buffer
deviceInterface.resize(cmListCharCount);
if (deviceInterface.empty()) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Could not allocate memory to store the PMT device interface path.\n");
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
// N.B. cmListCharCount is length in characters
status = NEO::SysCalls::cmGetDeviceInterfaceList((LPGUID)guid, NULL, &deviceInterface[0], cmListCharCount, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
} while (status == CR_BUFFER_SMALL);
if (status != CR_SUCCESS) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Could not find and store the PMT device inteface path.\n");
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
return ZE_RESULT_SUCCESS;
}
ze_result_t PlatformMonitoringTech::ioctlReadWriteData(std::vector<wchar_t> &path, uint32_t ioctl, void *bufferIn, uint32_t inSize, void *bufferOut, uint32_t outSize, uint32_t *sizeReturned) {
void *handle;
BOOL status = FALSE;
if (path.empty()) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"PMT interface path is empty.\n");
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
// Open handle to driver
handle = this->pcreateFile(&path[0], GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
if (handle == INVALID_HANDLE_VALUE) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"Could not open the pmt interface path %s.\n", &path[0]);
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
// Call DeviceIoControl
status = this->pdeviceIoControl(handle, ioctl, bufferIn, inSize, bufferOut, outSize, reinterpret_cast<unsigned long *>(sizeReturned), NULL);
this->pcloseHandle(handle);
if (status == FALSE) {
NEO::printDebugString(NEO::debugManager.flags.PrintDebugMessages.get(), stderr,
"deviceIoControl call failed\n");
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_UNKNOWN;
}
return ZE_RESULT_SUCCESS;
}
} // namespace Sysman
} // namespace L0