Add APIs for PM table and register table

Read the PM table and register table as the name value pair.

Change-Id: Ie44fe67a28af3341bd6beb90d809e90f280351ac


[ROCm/amdsmi commit: ac1ba33371]
Этот коммит содержится в:
Bill(Shuzhou) Liu
2023-11-13 09:05:05 -06:00
коммит произвёл Shuzhou Liu
родитель 09125ca639
Коммит c7f9cff2cb
10 изменённых файлов: 855 добавлений и 0 удалений
+2
Просмотреть файл
@@ -141,6 +141,7 @@ set(CMN_SRC_LIST
"${ROCM_SRC_DIR}/rocm_smi_counters.cc"
"${ROCM_SRC_DIR}/rocm_smi_device.cc"
"${ROCM_SRC_DIR}/rocm_smi_gpu_metrics.cc"
"${ROCM_SRC_DIR}/rocm_smi_binary_parser.cc"
"${ROCM_SRC_DIR}/rocm_smi_io_link.cc"
"${ROCM_SRC_DIR}/rocm_smi_kfd.cc"
"${ROCM_SRC_DIR}/rocm_smi_main.cc"
@@ -163,6 +164,7 @@ set(CMN_INC_LIST
"${ROCM_INC_DIR}/rocm_smi_counters.h"
"${ROCM_INC_DIR}/rocm_smi_device.h"
"${ROCM_INC_DIR}/rocm_smi_gpu_metrics.h"
"${ROCM_INC_DIR}/rocm_smi_binary_parser.h"
"${ROCM_INC_DIR}/rocm_smi_exception.h"
"${ROCM_INC_DIR}/rocm_smi_io_link.h"
"${ROCM_INC_DIR}/rocm_smi_kfd.h"
+93
Просмотреть файл
@@ -1213,6 +1213,28 @@ typedef struct {
/// @endcond
} amdsmi_gpu_metrics_t;
#define MAX_AMDSMI_NAME_LENGTH 64
/**
* @brief This structure holds the name value pairs
*/
typedef struct {
char name[MAX_AMDSMI_NAME_LENGTH]; //!< Name
uint64_t value; //!< Use uint64_t to make it universal
} amdsmi_name_value_t;
/**
* @brief This register type for register table
*/
typedef enum {
AMDSMI_REG_XGMI,
AMDSMI_REG_WAFL,
AMDSMI_REG_PCIE,
AMDSMI_REG_USR,
AMDSMI_REG_USR1,
} amdsmi_reg_type_t;
/**
* @brief This structure holds ras feature
*/
@@ -2585,6 +2607,77 @@ amdsmi_status_t amdsmi_get_gpu_od_volt_info(amdsmi_processor_handle processor_ha
amdsmi_status_t amdsmi_get_gpu_metrics_info(amdsmi_processor_handle processor_handle,
amdsmi_gpu_metrics_t *pgpu_metrics);
/**
* @brief Get the pm metrics table with provided device index.
*
* @details Given a device handle @p processor_handle, @p pm_metrics pointer,
* and @p num_of_metrics pointer,
* this function will write the pm metrics name value pair
* to the array at @p pm_metrics and the number of metrics retreived to @p num_of_metrics
* Note: the library allocated memory for pm_metrics, and user must call
* free(pm_metrics) to free it after use.
*
* @param[in] processor_handle a processor handle
*
* @param[inout] pm_metrics A pointerto an array to hold multiple PM metrics. On successs,
* the library will allocate memory of pm_metrics and write metrics to this array.
* The caller must free this memory after usage to avoid memory leak.
*
* @param[inout] num_of_metrics a pointer to uint32_t to which the number of
* metrics is allocated for pm_metrics array as input, and the number of metrics retreived
* as output. If this parameter is NULL, this function will return
* ::AMDSMI_STATUS_INVALID_ARGS if the function is supported with the provided,
* arguments and ::AMDSMI_STATUS_NOT_SUPPORTED if it is not supported with the
* provided arguments.
*
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
* support this function with the given arguments
* @retval ::AMDSMI_STATUS_INVALID_ARGS the provided arguments are not valid
*
*/
amdsmi_status_t amdsmi_get_gpu_pm_metrics_info(
amdsmi_processor_handle processor_handle,
amdsmi_name_value_t** pm_metrics,
uint32_t *num_of_metrics);
/**
* @brief Get the register metrics table with provided device index and register type.
*
* @details Given a device handle @p processor_handle, @p reg_type, @p reg_metrics pointer,
* and @p num_of_metrics pointer,
* this function will write the register metrics name value pair
* to the array at @p reg_metrics and the number of metrics retreived to @p num_of_metrics
* Note: the library allocated memory for reg_metrics, and user must call
* free(reg_metrics) to free it after use.
*
* @param[in] processor_handle a processor handle
*
* @param[in] reg_type The register type
*
* @param[inout] reg_metrics A pointerto an array to hold multiple register metrics. On successs,
* the library will allocate memory of reg_metrics and write metrics to this array.
* The caller must free this memory after usage to avoid memory leak.
*
* @param[inout] num_of_metrics a pointer to uint32_t to which the number of
* metrics is allocated for reg_metrics array as input, and the number of metrics retreived
* as output. If this parameter is NULL, this function will return
* ::AMDSMI_STATUS_INVALID_ARGS if the function is supported with the provided,
* arguments and ::AMDSMI_STATUS_NOT_SUPPORTED if it is not supported with the
* provided arguments.
*
* @retval ::AMDSMI_STATUS_SUCCESS call was successful
* @retval ::AMDSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
* support this function with the given arguments
* @retval ::AMDSMI_STATUS_INVALID_ARGS the provided arguments are not valid
*
*/
amdsmi_status_t amdsmi_get_gpu_reg_table_info(
amdsmi_processor_handle processor_handle,
amdsmi_reg_type_t reg_type,
amdsmi_name_value_t** reg_metrics,
uint32_t *num_of_metrics);
/**
* @brief This function sets the clock range information. It is not supported on virtual
* machine guest
+92
Просмотреть файл
@@ -1063,6 +1063,28 @@ typedef struct {
/// \endcond
} rsmi_gpu_metrics_t;
#define MAX_RSMI_NAME_LENGTH 64
/**
* @brief This structure holds the name value pairs
*/
typedef struct {
char name[MAX_RSMI_NAME_LENGTH]; //!< Name
uint64_t value; //!< Use uint64_t to make it universal
} rsmi_name_value_t;
/**
* @brief This register type for register table
*/
typedef enum {
RSMI_REG_XGMI,
RSMI_REG_WAFL,
RSMI_REG_PCIE,
RSMI_REG_USR,
RSMI_REG_USR1,
} rsmi_reg_type_t;
/**
* @brief This structure holds error counts.
*/
@@ -2765,6 +2787,76 @@ rsmi_status_t rsmi_dev_od_volt_info_get(uint32_t dv_ind,
rsmi_status_t rsmi_dev_gpu_metrics_info_get(uint32_t dv_ind,
rsmi_gpu_metrics_t *pgpu_metrics);
/**
* @brief Get the pm metrics table with provided device index.
*
* @details Given a device index @p dv_ind, @p pm_metrics pointer,
* and @p num_of_metrics pointer,
* this function will write the pm metrics name value pair
* to the array at @p pm_metrics and the number of metrics retreived to @p num_of_metrics
* Note: the library allocated memory for pm_metrics, and user must call
* free(pm_metrics) to free it after use.
*
* @param[in] dv_ind a device index
*
* @param[inout] pm_metrics A pointerto an array to hold multiple PM metrics. On successs,
* the library will allocate memory of pm_metrics and write metrics to this array.
* The caller must free this memory after usage to avoid memory leak.
*
* @param[inout] num_of_metrics a pointer to uint32_t to which the number of
* metrics is allocated for pm_metrics array as input, and the number of metrics retreived
* as output. If this parameter is NULL, this function will return
* ::RSMI_STATUS_INVALID_ARGS if the function is supported with the provided,
* arguments and ::RSMI_STATUS_NOT_SUPPORTED if it is not supported with the
* provided arguments.
*
* @retval ::RSMI_STATUS_SUCCESS call was successful
* @retval ::RSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
* support this function with the given arguments
* @retval ::RSMI_STATUS_INVALID_ARGS the provided arguments are not valid
*
*/
rsmi_status_t rsmi_dev_pm_metrics_info_get(uint32_t dv_ind,
rsmi_name_value_t** pm_metrics,
uint32_t *num_of_metrics);
/**
* @brief Get the register metrics table with provided device index and registertype.
*
* @details Given a device index @p dv_ind, @p reg_type, @p reg_metrics pointer,
* and @p num_of_metrics pointer,
* this function will write the register metrics name value pair
* to the array at @p reg_metrics and the number of metrics retreived to @p num_of_metrics
* Note: the library allocated memory for reg_metrics, and user must call
* free(reg_metrics) to free it after use.
*
* @param[in] dv_ind a device index
*
* @param[in] reg_type The register type
*
* @param[inout] reg_metrics A pointerto an array to hold multiple register metrics. On successs,
* the library will allocate memory of reg_metrics and write metrics to this array.
* The caller must free this memory after usage to avoid memory leak.
*
* @param[inout] num_of_metrics a pointer to uint32_t to which the number of
* metrics is allocated for reg_metrics array as input, and the number of metrics retreived
* as output. If this parameter is NULL, this function will return
* ::RSMI_STATUS_INVALID_ARGS if the function is supported with the provided,
* arguments and ::RSMI_STATUS_NOT_SUPPORTED if it is not supported with the
* provided arguments.
*
* @retval ::RSMI_STATUS_SUCCESS call was successful
* @retval ::RSMI_STATUS_NOT_SUPPORTED installed software or hardware does not
* support this function with the given arguments
* @retval ::RSMI_STATUS_INVALID_ARGS the provided arguments are not valid
*
*/
rsmi_status_t rsmi_dev_reg_table_info_get(uint32_t dv_ind,
rsmi_reg_type_t reg_type,
rsmi_name_value_t** reg_metrics,
uint32_t *num_of_metrics);
/**
* @brief This function sets the clock range information
*
+262
Просмотреть файл
@@ -0,0 +1,262 @@
/*
* =============================================================================
* The University of Illinois/NCSA
* Open Source License (NCSA)
*
* Copyright (c) 2017-2023, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Developed by:
*
* AMD Research and AMD ROC Software Development
*
* Advanced Micro Devices, Inc.
*
* www.amd.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal with the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimers.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimers in
* the documentation and/or other materials provided with the distribution.
* - Neither the names of <Name of Development Group, Name of Institution>,
* nor the names of its contributors may be used to endorse or promote
* products derived from this Software without specific prior written
* permission.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS WITH THE SOFTWARE.
*
*/
#ifndef ROCM_SMI_ROCM_SMI_BINARY_PARSER_H_
#define ROCM_SMI_ROCM_SMI_BINARY_PARSER_H_
#include "rocm_smi/rocm_smi_common.h"
#include "rocm_smi/rocm_smi.h"
#include <cstdint>
#include <map>
#include <memory>
#include <tuple>
#include <vector>
/**
* A binary parser to read the pm table and register table
*
*/
namespace amd::smi {
// definition for register table
enum amdgpu_sysfs_reg_offset {
AMDGPU_SYS_REG_STATE_XGMI = 0x0000,
AMDGPU_SYS_REG_STATE_WAFL = 0x1000,
AMDGPU_SYS_REG_STATE_PCIE = 0x2000,
AMDGPU_SYS_REG_STATE_USR = 0x3000,
AMDGPU_SYS_REG_STATE_USR_1 = 0x4000,
AMDGPU_SYS_REG_STATE_END = 0x5000,
};
#define FIELD_FLAG_NUM_INSTANCE 0x01
#define FIELD_FLAG_NUM_SMN 0x02
#define FIELD_FLAG_INSTANCE_START 0x04
#define FIELD_FLAG_SMN_START 0x08
#define FIELD_TYPE_U8 0x01
#define FIELD_TYPE_U16 0x02
#define FIELD_TYPE_U32 0x04
#define FIELD_TYPE_U64 0x08
struct metric_field {
uint8_t field_type;
int field_arr_size;
const char *field_name;
uint8_t field_flag;
};
struct metric_field xgmi_regs[] = {
{ FIELD_TYPE_U16, 1, "structure_size", 0 },
{ FIELD_TYPE_U8, 1, "format_revision", 0 },
{ FIELD_TYPE_U8, 1, "content_revision", 0 },
{ FIELD_TYPE_U8, 1, "state_type", 0 },
{ FIELD_TYPE_U8, 1, "num_instances", FIELD_FLAG_NUM_INSTANCE },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U16, 1, "instance", FIELD_FLAG_INSTANCE_START },
{ FIELD_TYPE_U16, 1, "state", 0 },
{ FIELD_TYPE_U16, 1, "num_smn_regs", FIELD_FLAG_NUM_SMN },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U64, 1, "addr", FIELD_FLAG_SMN_START },
{ FIELD_TYPE_U32, 1, "value", 0 },
{ FIELD_TYPE_U32, 1, "pad", 0 },
{ 0, 0, NULL, 0 },
};
// check me!
struct metric_field wafl_regs[] = {
{ FIELD_TYPE_U16, 1, "structure_size", 0 },
{ FIELD_TYPE_U8, 1, "format_revision", 0 },
{ FIELD_TYPE_U8, 1, "content_revision", 0 },
{ FIELD_TYPE_U8, 1, "state_type", 0 },
{ FIELD_TYPE_U8, 1, "num_instances", FIELD_FLAG_NUM_INSTANCE },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U16, 1, "instance", FIELD_FLAG_INSTANCE_START },
{ FIELD_TYPE_U16, 1, "state", 0 },
{ FIELD_TYPE_U16, 1, "num_smn_regs", FIELD_FLAG_NUM_SMN },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U64, 1, "addr", FIELD_FLAG_SMN_START },
{ FIELD_TYPE_U32, 1, "value", 0 },
{ FIELD_TYPE_U32, 1, "pad", 0 },
{ 0, 0, NULL, 0 },
};
struct metric_field pcie_regs[] = {
{ FIELD_TYPE_U16, 1, "structure_size", 0 },
{ FIELD_TYPE_U8, 1, "format_revision", 0 },
{ FIELD_TYPE_U8, 1, "content_revision", 0 },
{ FIELD_TYPE_U8, 1, "state_type", 0 },
{ FIELD_TYPE_U8, 1, "num_instances", FIELD_FLAG_NUM_INSTANCE },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U16, 1, "instance", FIELD_FLAG_INSTANCE_START },
{ FIELD_TYPE_U16, 1, "state", 0 },
{ FIELD_TYPE_U16, 1, "num_smn_regs", FIELD_FLAG_NUM_SMN },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U16, 1, "device_status", 0 },
{ FIELD_TYPE_U16, 1, "link_status", 0 },
{ FIELD_TYPE_U32, 1, "sub_bus_number_latency", 0 },
{ FIELD_TYPE_U32, 1, "pcie_corr_err_status", 0 },
{ FIELD_TYPE_U32, 1, "pcie_uncorr_err_status", 0 },
{ FIELD_TYPE_U64, 1, "addr", FIELD_FLAG_SMN_START },
{ FIELD_TYPE_U32, 1, "value", 0 },
{ FIELD_TYPE_U32, 1, "pad", 0 },
{ 0, 0, NULL, 0 },
};
struct metric_field usr_regs[] = {
{ FIELD_TYPE_U16, 1, "structure_size", 0 },
{ FIELD_TYPE_U8, 1, "format_revision", 0 },
{ FIELD_TYPE_U8, 1, "content_revision", 0 },
{ FIELD_TYPE_U8, 1, "state_type", 0 },
{ FIELD_TYPE_U8, 1, "num_instances", FIELD_FLAG_NUM_INSTANCE },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U16, 1, "instance", FIELD_FLAG_INSTANCE_START },
{ FIELD_TYPE_U16, 1, "state", 0 },
{ FIELD_TYPE_U16, 1, "num_smn_regs", FIELD_FLAG_NUM_SMN },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U64, 1, "addr", FIELD_FLAG_SMN_START },
{ FIELD_TYPE_U32, 1, "value", 0 },
{ FIELD_TYPE_U32, 1, "pad", 0 },
{ 0, 0, NULL, 0 },
};
// definition for pm metrics table
#define FIELD_FLAG_ACCUMULATOR 0x01
struct metric_field smu_13_0_6_v8[] = {
{ FIELD_TYPE_U16, 1, "structure_size", 0 },
{ FIELD_TYPE_U16, 1, "pad", 0 },
{ FIELD_TYPE_U32, 1, "mp1_ip_discovery_version", 0 },
{ FIELD_TYPE_U32, 1, "pmfw_version", 0 },
{ FIELD_TYPE_U32, 1, "pmmetrics_version", 0 },
{ FIELD_TYPE_U32, 1, "AccumulationCounter", 0 },
{ FIELD_TYPE_U32, 1, "MaxSocketTemperature", 0 },
{ FIELD_TYPE_U32, 1, "MaxVrTemperature", 0 },
{ FIELD_TYPE_U32, 1, "MaxHbmTemperature", 0 },
{ FIELD_TYPE_U64, 1, "MaxSocketTemperatureAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 1, "MaxVrTemperatureAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 1, "MaxHbmTemperatureAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "SocketPowerLimit", 0 },
{ FIELD_TYPE_U32, 1, "MaxSocketPowerLimit", 0 },
{ FIELD_TYPE_U32, 1, "SocketPower", 0 },
{ FIELD_TYPE_U64, 1, "Timestamp", 0 },
{ FIELD_TYPE_U64, 1, "SocketEnergyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 1, "CcdEnergyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 1, "XcdEnergyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 1, "AidEnergyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 1, "HbmEnergyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "CclkFrequencyLimit", 0 },
{ FIELD_TYPE_U32, 1, "GfxclkFrequencyLimit", 0 },
{ FIELD_TYPE_U32, 1, "FclkFrequency", 0 },
{ FIELD_TYPE_U32, 1, "UclkFrequency", 0 },
{ FIELD_TYPE_U32, 4, "SocclkFrequency", 0 },
{ FIELD_TYPE_U32, 4, "VclkFrequency", 0 },
{ FIELD_TYPE_U32, 4, "DclkFrequency", 0 },
{ FIELD_TYPE_U32, 4, "LclkFrequency", 0 },
{ FIELD_TYPE_U64, 8, "GfxclkFrequencyAcc", FIELD_FLAG_ACCUMULATOR},
{ FIELD_TYPE_U64, 96, "CclkFrequencyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "MaxCclkFrequency", 0 },
{ FIELD_TYPE_U32, 1, "MinCclkFrequency", 0 },
{ FIELD_TYPE_U32, 1, "MaxGfxclkFrequency", 0 },
{ FIELD_TYPE_U32, 1, "MinGfxclkFrequency", 0 },
{ FIELD_TYPE_U32, 4, "FclkFrequencyTable", 0 },
{ FIELD_TYPE_U32, 4, "UclkFrequencyTable", 0 },
{ FIELD_TYPE_U32, 4, "SocclkFrequencyTable", 0 },
{ FIELD_TYPE_U32, 4, "VclkFrequencyTable", 0 },
{ FIELD_TYPE_U32, 4, "DclkFrequencyTable", 0 },
{ FIELD_TYPE_U32, 4, "LclkFrequencyTable", 0 },
{ FIELD_TYPE_U32, 1, "MaxLclkDpmRange", 0 },
{ FIELD_TYPE_U32, 1, "MinLclkDpmRange", 0 },
{ FIELD_TYPE_U32, 1, "XgmiWidth", 0 },
{ FIELD_TYPE_U32, 1, "XgmiBitrate", 0 },
{ FIELD_TYPE_U64, 8, "XgmiReadBandwidthAcc", 0 },
{ FIELD_TYPE_U64, 8, "XgmiWriteBandwidthAcc", 0 },
{ FIELD_TYPE_U32, 1, "SocketC0Residency", 0 },
{ FIELD_TYPE_U32, 1, "SocketGfxBusy", 0 },
{ FIELD_TYPE_U32, 1, "DramBandwidthUtilization", 0 },
{ FIELD_TYPE_U64, 1, "SocketC0ResidencyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 1, "SocketGfxBusyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 1, "DramBandwidthAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "MaxDramBandwidth", 0 },
{ FIELD_TYPE_U64, 1, "DramBandwidthUtilizationAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 4, "PcieBandwidthAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "ProchotResidencyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "PptResidencyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "SocketThmResidencyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "VrThmResidencyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "HbmThmResidencyAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U32, 1, "GfxLockXCDMak", 0 },
{ FIELD_TYPE_U32, 8, "GfxclkFrequency", 0 },
{ FIELD_TYPE_U64, 4, "PublicSerialNumber_AID", 0 },
{ FIELD_TYPE_U64, 8, "PublicSerialNumber_XCD", 0 },
{ FIELD_TYPE_U64, 12, "PublicSerialNumber_CCD", 0 },
{ FIELD_TYPE_U64, 8, "XgmiReadDataSizeAcc", FIELD_FLAG_ACCUMULATOR },
{ FIELD_TYPE_U64, 8, "XgmiWriteDataSizeAcc", FIELD_FLAG_ACCUMULATOR },
{ 0, 0, NULL, 0 },
};
} // namespace amd::smi
#endif // ROCM_SMI_ROCM_SMI_BINARY_PARSER_H_
+3
Просмотреть файл
@@ -171,6 +171,8 @@ enum DevInfoTypes {
kDevMemPageBad,
kDevNumaNode,
kDevGpuMetrics,
kDevPmMetrics,
kDevRegMetrics,
kDevGpuReset,
kDevAvailableComputePartition,
kDevComputePartition,
@@ -205,6 +207,7 @@ class Device {
int readDevInfo(DevInfoTypes type, std::vector<std::string> *retVec);
int readDevInfo(DevInfoTypes type, std::size_t b_size,
void *p_binary_data);
std::string get_sys_file_path_by_type(DevInfoTypes type) const;
// Get the property from a file which may contain multiple properties.
int readDevInfo(DevInfoTypes type, const std::string& property,
std::string& value);
+42
Просмотреть файл
@@ -106,6 +106,14 @@ static const std::map<rsmi_clk_type_t, amd::smi::DevInfoTypes> kClkTypeMap = {
#define TRY try {
#define CATCH } catch (...) {return amd::smi::handleException();}
// declare pm metrics and register table function
namespace amd::smi {
int present_pmmetrics(const char* sysfs_file_name,
rsmi_name_value_t **kv, uint32_t *kvnum);
int present_reg_state(const char* fname, rsmi_reg_type_t reg_type,
rsmi_name_value_t **kv, uint32_t *kvnum);
}
static uint64_t get_multiplier_from_str(char units_char) {
uint32_t multiplier = 0;
@@ -2479,6 +2487,40 @@ rsmi_dev_vendor_name_get(uint32_t dv_ind, char *name, size_t len) {
CATCH
}
rsmi_status_t rsmi_dev_pm_metrics_info_get(uint32_t dv_ind,
rsmi_name_value_t** pm_metrics,
uint32_t *num_of_metrics) {
TRY
DEVICE_MUTEX
CHK_SUPPORT_NAME_ONLY(num_of_metrics)
std::string file_path = dev->
get_sys_file_path_by_type(amd::smi::kDevPmMetrics);
int ret = amd::smi::present_pmmetrics(
file_path.c_str(), pm_metrics, num_of_metrics);
if (ret == 0) return RSMI_STATUS_SUCCESS;
return RSMI_STATUS_NOT_SUPPORTED;
CATCH
}
rsmi_status_t rsmi_dev_reg_table_info_get(uint32_t dv_ind,
rsmi_reg_type_t reg_type,
rsmi_name_value_t** reg_metrics,
uint32_t *num_of_metrics) {
TRY
DEVICE_MUTEX
CHK_SUPPORT_NAME_ONLY(num_of_metrics)
std::string file_path = dev->
get_sys_file_path_by_type(amd::smi::kDevRegMetrics);
int ret = amd::smi::present_reg_state(
file_path.c_str(), reg_type, reg_metrics, num_of_metrics);
if (ret == 0) return RSMI_STATUS_SUCCESS;
return RSMI_STATUS_NOT_SUPPORTED;
CATCH
}
rsmi_status_t
rsmi_dev_pci_bandwidth_get(uint32_t dv_ind, rsmi_pcie_bandwidth_t *b) {
+320
Просмотреть файл
@@ -0,0 +1,320 @@
/*
* =============================================================================
* The University of Illinois/NCSA
* Open Source License (NCSA)
*
* Copyright (c) 2017-2023, Advanced Micro Devices, Inc.
* All rights reserved.
*
* Developed by:
*
* AMD Research and AMD ROC Software Development
*
* Advanced Micro Devices, Inc.
*
* www.amd.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal with the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimers.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimers in
* the documentation and/or other materials provided with the distribution.
* - Neither the names of <Name of Development Group, Name of Institution>,
* nor the names of its contributors may be used to endorse or promote
* products derived from this Software without specific prior written
* permission.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS WITH THE SOFTWARE.
*
*/
#include "rocm_smi/rocm_smi_binary_parser.h"
#include "rocm_smi/rocm_smi_common.h" // Should go before rocm_smi.h
#include "rocm_smi/rocm_smi.h"
#include "rocm_smi/rocm_smi_main.h"
#include "rocm_smi/rocm_smi_utils.h"
#include "rocm_smi/rocm_smi_exception.h"
#include "rocm_smi/rocm_smi_device.h"
#include "rocm_smi/rocm_smi_logger.h"
#include <dirent.h>
#include <pthread.h>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <variant>
#include <vector>
namespace amd::smi {
static uint64_t get_value(uint8_t **ptr, struct metric_field *field) {
uint64_t v;
switch (field->field_type) {
case FIELD_TYPE_U8:
v = *(uint8_t*)(*ptr);
++(*ptr);
break;
case FIELD_TYPE_U16:
v = *(uint16_t*)(*ptr);
(*ptr) += 2;
break;
case FIELD_TYPE_U32:
v = *(uint32_t*)(*ptr);
(*ptr) += 4;
break;
case FIELD_TYPE_U64:
v = *(uint64_t*)(*ptr);
(*ptr) += 8;
break;
}
return v;
}
static int parse_pmmetric_table(uint8_t *buf, struct metric_field *table,
int32_t buflen, rsmi_name_value_t **kv, uint32_t *kvnum) {
uint64_t v1;
int x, y;
uint8_t *origbuf = buf;
uint32_t kvsize = 64;
*kv = reinterpret_cast<rsmi_name_value_t*>(calloc(kvsize, sizeof **kv));
*kvnum = 0;
for (x = 0; table[x].field_name; x++) {
for (y = 0; y < table[x].field_arr_size; y++) {
v1 = get_value(&buf, &table[x]);
if ((intptr_t)(buf - origbuf) > buflen) {
fprintf(stderr,
"[ERROR]: Invalid buffer as buffer length exceeded\n");
return -1;
}
if (*kvnum == kvsize) {
kvsize += 64;
*kv = reinterpret_cast<rsmi_name_value_t*>
(realloc(*kv,kvsize * (sizeof **kv)));
}
if (table[x].field_arr_size == 1) {
sprintf((*kv)[*kvnum].name, "%s", table[x].field_name);
} else {
sprintf((*kv)[*kvnum].name, "%s[%d]", table[x].field_name, y);
}
(*kv)[*kvnum].value = v1;
++(*kvnum);
}
}
return 0;
}
/** present the PM metrics data
*
* @dri_instance: which card to pick under /sys/class/drm/card${instance}/device/
* @kv: pointer to pointer of rsmi_name_value pairs
* @kvnum: pointer to number of used rsmi_name_value pairs
*/
int present_pmmetrics(const char* fname,
rsmi_name_value_t **kv, uint32_t *kvnum)
{
uint8_t *buf1;
FILE *infile;
uint32_t pmmetrics_version;
metric_field *table;
int r;
int32_t len;
infile = fopen(fname, "rb");
if (!infile) {
fprintf(stderr, "[ERROR]: pm_metrics file not found \n");
return -1;
}
buf1 = reinterpret_cast<uint8_t *>(calloc(1, 65536));
if (!buf1) {
return -1;
}
table = NULL;
len = fread(buf1, 1, 65536, infile);
fseek(infile, 0, SEEK_SET);
memcpy(&pmmetrics_version, &buf1[12], 4);
switch (pmmetrics_version) {
case 4: // ??? why 4?
table = &smu_13_0_6_v8[0];
break;
default:
fprintf(stderr, "Metrics version %d not supported\n"
, pmmetrics_version);
return -1;
}
r = parse_pmmetric_table(buf1, table, len, kv, kvnum);
fclose(infile);
free(buf1);
return r;
}
static int parse_reg_state_table(uint8_t *buf, int32_t buflen,
struct metric_field *table,
rsmi_name_value_t **kv, uint32_t *kvnum) {
int skip_smn, x, y, cur_instance, cur_smn,
num_instance, num_smn, instance_start, smn_start;
uint64_t v;
uint8_t *obuf, *origbuf;
int kvsize = 64;
*kv = reinterpret_cast<rsmi_name_value_t*>(calloc(kvsize, sizeof **kv));
*kvnum = 0;
skip_smn = cur_instance = num_instance = num_smn = 0;
instance_start = smn_start = 0x1000;
x = 0;
origbuf = buf;
top:
while (table[x].field_name != NULL) {
for (y = 0; y < table[x].field_arr_size; y++) {
obuf = buf;
v = get_value(&buf, &table[x]);
if ((intptr_t)(buf - origbuf) > buflen) {
fprintf(stderr,
"[ERROR] Invalid buffer as read length was exceeded\n");
return -1;
}
switch (table[x].field_flag) {
case FIELD_FLAG_INSTANCE_START:
instance_start = x;
num_smn = cur_smn = 0;
break;
case FIELD_FLAG_SMN_START:
// if we hit an SMN start but there are no registers then skip back to the start
// of the instance block
if (skip_smn) {
// out of instances we're done so bail!
if (!num_instance)
return 0;
x = instance_start;
--num_instance;
++cur_instance;
// rewind the buffer since we didn't actually consume
// this word
buf = obuf;
goto top;
} else {
smn_start = x;
}
break;
case FIELD_FLAG_NUM_INSTANCE:
num_instance = v;
break;
case FIELD_FLAG_NUM_SMN:
num_smn = v;
if (v)
skip_smn = 0;
else
skip_smn = 1;
break;
}
if (*kvnum == kvsize) {
kvsize += 64;
*kv = reinterpret_cast<rsmi_name_value_t*>(
realloc(*kv, kvsize * (sizeof **kv)));
}
sprintf((*kv)[*kvnum].name, "%s", table[x].field_name);
if (table[x].field_arr_size > 1) {
sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), "[%d]", y);
}
if (x >= instance_start)
sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), ".instance[%d]", cur_instance);
if (x >= smn_start)
sprintf((*kv)[*kvnum].name + strlen((*kv)[*kvnum].name), ".smn[%d]", cur_smn);
(*kv)[*kvnum].value = v;
++(*kvnum);
}
// done move to next or loop
++x;
if (table[x].field_name == NULL && --num_smn) {
x = smn_start;
++cur_smn;
} else if (table[x].field_name == NULL && --num_instance) {
x = instance_start;
++cur_instance;
}
}
return 0;
}
/** present_reg_state: present register state data
*
* @dri_instance: The DRI instance to select under /sys/class/drm/card${instance}/device
* @table: Name of the table to read {"xgmi', "wafl", "pcie", "usr", "usr_1"}
* @kv: pointer to pointer of rsmi_name_value pairs
* @kvnum: pointer to number of used rsmi_name_value pairs
*/
int present_reg_state(const char* fname,
rsmi_reg_type_t reg_type, rsmi_name_value_t **kv, uint32_t *kvnum) {
uint8_t buf[4096];
FILE *infile;
struct metric_field *tab;
int32_t len;
infile = fopen(fname, "rb");
if (!infile) {
fprintf(stderr, "[ERROR]: reg_state file not found\n");
return -1;
}
tab = NULL;
if (reg_type == RSMI_REG_XGMI) {
fseek(infile, AMDGPU_SYS_REG_STATE_XGMI, SEEK_SET);
tab = &xgmi_regs[0];
}
if (reg_type == RSMI_REG_WAFL) {
fseek(infile, AMDGPU_SYS_REG_STATE_WAFL, SEEK_SET);
tab = &wafl_regs[0];
}
if (reg_type == RSMI_REG_PCIE) {
fseek(infile, AMDGPU_SYS_REG_STATE_PCIE, SEEK_SET);
tab = &pcie_regs[0];
}
if (reg_type == RSMI_REG_USR) {
fseek(infile, AMDGPU_SYS_REG_STATE_USR, SEEK_SET);
tab = &usr_regs[0];
}
if (reg_type == RSMI_REG_USR1) {
fseek(infile, AMDGPU_SYS_REG_STATE_USR_1, SEEK_SET);
tab = &usr_regs[0];
}
if (!tab) {
fprintf(stderr, "[ERROR]: Invalid register space named <%d>\n", reg_type);
fclose(infile);
return -2;
}
len = fread(buf, 1, sizeof buf, infile);
fclose(infile);
return parse_reg_state_table(buf, len, tab, kv, kvnum);
}
} // namespace amd::smi
+14
Просмотреть файл
@@ -130,6 +130,8 @@ static const char *kDevXGMIErrorFName = "xgmi_error";
static const char *kDevSerialNumberFName = "serial_number";
static const char *kDevNumaNodeFName = "numa_node";
static const char *kDevGpuMetricsFName = "gpu_metrics";
static const char *kDevPmMetricsFName = "pm_metrics"; // PM log
static const char *kDevRegMetricsFName = "reg_state"; // register table
static const char *kDevAvailableComputePartitionFName =
"available_compute_partition";
static const char *kDevComputePartitionFName = "current_compute_partition";
@@ -312,6 +314,8 @@ static const std::map<DevInfoTypes, const char *> kDevAttribNameMap = {
{kDevMemPageBad, kDevMemPageBadFName},
{kDevNumaNode, kDevNumaNodeFName},
{kDevGpuMetrics, kDevGpuMetricsFName},
{kDevPmMetrics, kDevPmMetricsFName},
{kDevRegMetrics, kDevRegMetricsFName},
{kDevGpuReset, kDevGpuResetFName},
{kDevAvailableComputePartition, kDevAvailableComputePartitionFName},
{kDevComputePartition, kDevComputePartitionFName},
@@ -445,6 +449,8 @@ static const std::map<const char *, dev_depends_t> kDevFuncDependsMap = {
{"rsmi_dev_memory_reserved_pages_get", {{kDevMemPageBadFName}, {}}},
{"rsmi_topo_numa_affinity_get", {{kDevNumaNodeFName}, {}}},
{"rsmi_dev_gpu_metrics_info_get", {{kDevGpuMetricsFName}, {}}},
{"rsmi_dev_pm_metrics_info_get", {{kDevPmMetricsFName}, {}}},
{"rsmi_dev_reg_table_info_get", {{kDevRegMetricsFName}, {}}},
{"rsmi_dev_gpu_reset", {{kDevGpuResetFName}, {}}},
{"rsmi_dev_compute_partition_get", {{kDevComputePartitionFName}, {}}},
{"rsmi_dev_compute_partition_set", {{kDevComputePartitionFName}, {}}},
@@ -594,6 +600,14 @@ int Device::openDebugFileStream(DevInfoTypes type, T *fs, const char *str) {
return 0;
}
std::string Device::get_sys_file_path_by_type(DevInfoTypes type) const {
auto sysfs_path = path_;
sysfs_path += "/device/";
sysfs_path += kDevAttribNameMap.at(type);
return sysfs_path;
}
template <typename T>
int Device::openSysfsFileStream(DevInfoTypes type, T *fs, const char *str) {
auto sysfs_path = path_;
+2
Просмотреть файл
@@ -154,6 +154,8 @@ amd::smi::RocmSMI::devInfoTypesStrings = {
{amd::smi::kDevMemPageBad, amdSMI + "kDevMemPageBad"},
{amd::smi::kDevNumaNode, amdSMI + "kDevNumaNode"},
{amd::smi::kDevGpuMetrics, amdSMI + "kDevGpuMetrics"},
{amd::smi::kDevPmMetrics, amdSMI + "kDevPmMetrics"},
{amd::smi::kDevRegMetrics, amdSMI + "kDevRegMetrics"},
{amd::smi::kDevGpuReset, amdSMI + "kDevGpuReset"},
{amd::smi::kDevAvailableComputePartition, amdSMI +
"kDevAvailableComputePartition"},
+25
Просмотреть файл
@@ -1157,6 +1157,31 @@ amdsmi_status_t amdsmi_get_gpu_metrics_info(
reinterpret_cast<rsmi_gpu_metrics_t*>(pgpu_metrics));
}
amdsmi_status_t amdsmi_get_gpu_pm_metrics_info(
amdsmi_processor_handle processor_handle,
amdsmi_name_value_t** pm_metrics,
uint32_t *num_of_metrics) {
AMDSMI_CHECK_INIT();
return rsmi_wrapper(rsmi_dev_pm_metrics_info_get, processor_handle,
reinterpret_cast<rsmi_name_value_t**>(pm_metrics),
num_of_metrics);
}
amdsmi_status_t amdsmi_get_gpu_reg_table_info(
amdsmi_processor_handle processor_handle,
amdsmi_reg_type_t reg_type,
amdsmi_name_value_t** reg_metrics,
uint32_t *num_of_metrics) {
AMDSMI_CHECK_INIT();
return rsmi_wrapper(rsmi_dev_reg_table_info_get, processor_handle,
static_cast<rsmi_reg_type_t>(reg_type),
reinterpret_cast<rsmi_name_value_t**>(reg_metrics),
num_of_metrics);
}
amdsmi_status_t
amdsmi_get_power_cap_info(amdsmi_processor_handle processor_handle,
uint32_t sensor_ind,