Removed CPER tests and adjust the implementation (#269)

- Moved helper functions into amdsmi_utils.cc
- Removed tests since they are not working.

---------

Co-authored-by: Saeed, Oosman <Oosman.Saeed@amd.com>

[ROCm/amdsmi commit: d6954bcc62]
This commit is contained in:
AL Musaffar, Yazen
2025-04-21 14:54:47 -05:00
کامیت شده توسط GitHub
والد f635fab179
کامیت 0551b2aa67
6فایلهای تغییر یافته به همراه234 افزوده شده و 616 حذف شده
@@ -4706,13 +4706,6 @@ typedef struct {
uint8_t century;
} amdsmi_cper_timestamp_t;
typedef struct {
uint32_t platform_id : 1;
uint32_t timestamp : 1;
uint32_t partition_id : 1;
uint32_t reserved : 29;
} valid_bits_t;
typedef union {
struct valid_bits_ {
uint32_t platform_id : 1;
@@ -4729,11 +4722,7 @@ typedef struct {
uint32_t signature_end; /* 0xFFFFFFFF */
uint16_t sec_cnt;
amdsmi_cper_sev_t error_severity;
// valid_bits_t valid_bits;
// uint32_t valid_mask;
amdsmi_cper_valid_bits_t cper_valid_bits;
uint32_t record_length; /* Total size of CPER Entry */
amdsmi_cper_timestamp_t timestamp;
char platform_id[16];
@@ -4783,6 +4772,7 @@ typedef struct {
*
* @return ::amdsmi_status_t | ::AMDSMI_STATUS_SUCCESS on success, non-zero on fail
*/
amdsmi_status_t
amdsmi_get_gpu_cper_entries(amdsmi_processor_handle processor_handle, uint32_t severity_mask, char *cper_data,
uint64_t *buf_size, amdsmi_cper_hdr_t** cper_hdrs, uint64_t *entry_count, uint64_t *cursor);
@@ -54,6 +54,7 @@ amdsmi_status_t smi_amdgpu_get_market_name_from_dev_id(amd::smi::AMDSmiGPUDevice
amdsmi_status_t smi_amdgpu_is_gpu_power_management_enabled(amd::smi::AMDSmiGPUDevice* device, bool *enabled);
std::string smi_split_string(std::string str, char delim);
std::string smi_amdgpu_get_status_string(amdsmi_status_t ret, bool fullStatus);
amdsmi_status_t amdsmi_get_gpu_cper_entries_by_path(const char *amdgpu_ring_cper_file, uint32_t severity_mask, char *cper_data, uint64_t *buf_size, amdsmi_cper_hdr_t **cper_hdrs, uint64_t *entry_count, uint64_t *cursor);
/**
* @brief Get the device index given the processor handle.
@@ -3559,241 +3559,6 @@ amdsmi_get_gpu_total_ecc_count(amdsmi_processor_handle processor_handle, amdsmi_
return AMDSMI_STATUS_SUCCESS;
}
namespace {
static std::vector<const amdsmi_cper_hdr_t *>
amdsmi_get_gpu_cper_headers(const char *buffer, size_t buffer_sz) {
std::ostringstream ss;
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] buffer_sz: " << buffer_sz;
LOG_DEBUG(ss);
std::vector<const amdsmi_cper_hdr_t *> headers;
if(!buffer) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] buffer is null";
LOG_ERROR(ss);
return headers;
}
static constexpr char cper_signature[] = "CPER";
static constexpr size_t cper_signature_size = sizeof(cper_signature) - 1;
for(size_t data_idx = 0;
buffer_sz >= cper_signature_size &&
data_idx < buffer_sz - cper_signature_size;
++data_idx) {
const amdsmi_cper_hdr_t *hdr = reinterpret_cast<const amdsmi_cper_hdr_t *>(
&buffer[data_idx]);
if(hdr->signature[0] != 'C' || hdr->signature[1] != 'P' ||
hdr->signature[2] != 'E' || hdr->signature[3] != 'R' ) {
continue;
}
if(hdr->signature_end != 0xFFFFFFFF) {
continue;
}
if(hdr->record_length > buffer_sz) {
continue;
}
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] add header at data_idx: " << data_idx
<< ", sig: " << hdr->signature[0] << hdr->signature[1] << hdr->signature[2] << hdr->signature[3];
LOG_DEBUG(ss);
headers.emplace_back(hdr);
}
return headers;
}
struct CperFileCtx {
amdsmi_status_t status = AMDSMI_STATUS_FILE_ERROR;
std::unique_ptr<char[]> buffer;
long file_size = 0;
};
static auto amdsmi_read_cper_file(const std::string &filepath) {
std::ostringstream ss;
CperFileCtx ctx;
ctx.status = AMDSMI_STATUS_FILE_ERROR;
ctx.file_size = 0;
struct stat file_stats;
if (stat(filepath.c_str(), &file_stats) == 0) {
if (!S_ISREG(file_stats.st_mode)) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] file is not a regular file: "
<< filepath << ", errno: " << errno << "): " << strerror(errno);
return ctx;
}
} else {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] file does not exist: "
<< filepath << ", errno: " << errno << "): " << strerror(errno);
ctx.status = AMDSMI_STATUS_NOT_SUPPORTED;
return ctx;
}
ctx.file_size = file_stats.st_size;
ctx.buffer = std::make_unique<char[]>(ctx.file_size);
int file = open(filepath.c_str(), O_RDONLY);
if (file == -1) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] failed to open file: "
<< filepath << ", errno:()" << errno << "): " << strerror(errno);
LOG_ERROR(ss);
return ctx;
}
long bytes_read = read(file, ctx.buffer.get(), ctx.file_size);
if (bytes_read <= 0) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] failed to read complete file, read only "
<< bytes_read << " of " << ctx.file_size << " bytes";
LOG_ERROR(ss);
return ctx;
}
close(file);
ctx.status = AMDSMI_STATUS_SUCCESS;
ctx.file_size = bytes_read;
return ctx;
}
}//namespace
amdsmi_status_t
amdsmi_get_gpu_cper_entries_by_path(
const std::string &amdgpu_ring_cper_file,
uint32_t severity_mask,
char *cper_data,
uint64_t *buf_size,
amdsmi_cper_hdr_t **cper_hdrs,
uint64_t *entry_count,
uint64_t *cursor) {
std::ostringstream ss;
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] begin\n"
<< ", amdgpu_ring_cper_file: " << amdgpu_ring_cper_file
<< ", severity_mask: " << severity_mask;
LOG_DEBUG(ss);
if(!cper_data) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper_data should be a valid memory address\n";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
if(buf_size) { *buf_size = 0; }
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!buf_size) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] buf_size should be a valid memory address";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
if(buf_size) { *buf_size = 0; }
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!*buf_size) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] buf_size should be greater than zero";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
if(buf_size) { *buf_size = 0; }
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!cper_hdrs) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper_hdrs should be a valid memory address";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
if(buf_size) { *buf_size = 0; }
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!entry_count) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] entry_count should be a valid memory address";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
if(buf_size) { *buf_size = 0; }
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!*entry_count) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] entry_count should be greater than 0";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
if(buf_size) { *buf_size = 0; }
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!cursor) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cursor should be a valid memory address";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
if(buf_size) { *buf_size = 0; }
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
auto ctx = amdsmi_read_cper_file(amdgpu_ring_cper_file);
if(ctx.status != AMDSMI_STATUS_SUCCESS) {
return ctx.status;
}
auto headers = amdsmi_get_gpu_cper_headers(ctx.buffer.get(), ctx.file_size);
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] num headers: " << headers.size();
LOG_DEBUG(ss);
uint64_t data_idx = 0;
uint64_t header_idx = 0;
size_t num_headers_copied = 0;
for(const amdsmi_cper_hdr_t *header: headers) {
if(((1 << header->error_severity) & severity_mask) !=
(1 << header->error_severity)) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper header rejected with severity: 0x"
<< std::hex << (1 << header->error_severity) << ", given severity_mask: 0x"
<< std::hex << severity_mask << ", record_length:"
<< std::dec << header->record_length;
LOG_DEBUG(ss);
continue;
}
else {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper header accepted with severity: 0x"
<< std::hex << (1 << header->error_severity) << ", given severity_mask: 0x"
<< std::hex << severity_mask << ", record_length:"
<< std::dec << header->record_length;
LOG_DEBUG(ss);
}
if((*buf_size - data_idx) < header->record_length ) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] buffer filled up without copying all cper entries, buf_size: " << std::dec << *buf_size;
LOG_ERROR(ss);
*entry_count = num_headers_copied;
*buf_size = data_idx;
return (data_idx == 0) ?
AMDSMI_STATUS_OUT_OF_RESOURCES :
AMDSMI_STATUS_MORE_DATA;
}
if(num_headers_copied == *entry_count) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper_hdrs filled up before finished with copying all header pointers, entry_count: " << std::dec << *entry_count;
LOG_ERROR(ss);
*entry_count = num_headers_copied;
*buf_size = data_idx;
return (data_idx == 0) ?
AMDSMI_STATUS_OUT_OF_RESOURCES :
AMDSMI_STATUS_MORE_DATA;
}
if(*cursor != header_idx) {
++header_idx;
continue;
}
cper_hdrs[num_headers_copied] = reinterpret_cast<amdsmi_cper_hdr_t*>(&cper_data[data_idx]);
++num_headers_copied;
*cursor = ++header_idx;
std::memcpy(
&cper_data[data_idx],
reinterpret_cast<const char*>(header),
header->record_length);
data_idx += header->record_length;
}
*entry_count = num_headers_copied;
*buf_size = data_idx;
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] *entry_count: " << (entry_count ? *entry_count : -1)
<< ", *cursor: " << (cursor ? *cursor : -1)
<< ", *buf_size: " << (buf_size ? *buf_size : -1);
LOG_DEBUG(ss);
return AMDSMI_STATUS_SUCCESS;
}
amdsmi_status_t
amdsmi_get_gpu_cper_entries(
amdsmi_processor_handle processor_handle,
@@ -3820,7 +3585,7 @@ amdsmi_get_gpu_cper_entries(
return amdsmi_get_gpu_cper_entries_by_path(
path,
path.c_str(),
severity_mask,
cper_data,
buf_size,
@@ -876,3 +876,234 @@ amdsmi_status_t smi_amdgpu_get_processor_handle_by_index(
LOG_DEBUG(ss);
return AMDSMI_STATUS_API_FAILED;
}
static std::vector<const amdsmi_cper_hdr_t *>
amdsmi_get_gpu_cper_headers(const char *buffer, size_t buffer_sz) {
std::ostringstream ss;
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] buffer_sz: " << buffer_sz;
LOG_DEBUG(ss);
std::vector<const amdsmi_cper_hdr_t *> headers;
if(!buffer) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] buffer is null";
LOG_ERROR(ss);
return headers;
}
static constexpr char cper_signature[] = "CPER";
static constexpr size_t cper_signature_size = sizeof(cper_signature) - 1;
for(size_t data_idx = 0;
buffer_sz >= cper_signature_size &&
data_idx < buffer_sz - cper_signature_size;
++data_idx) {
const amdsmi_cper_hdr_t *hdr = reinterpret_cast<const amdsmi_cper_hdr_t *>(
&buffer[data_idx]);
if(hdr->signature[0] != 'C' || hdr->signature[1] != 'P' ||
hdr->signature[2] != 'E' || hdr->signature[3] != 'R' ) {
continue;
}
if(hdr->signature_end != 0xFFFFFFFF) {
continue;
}
if(hdr->record_length > buffer_sz) {
continue;
}
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] add header at data_idx: " << data_idx
<< ", sig: " << hdr->signature[0] << hdr->signature[1] << hdr->signature[2] << hdr->signature[3];
LOG_DEBUG(ss);
headers.emplace_back(hdr);
}
return headers;
}
struct CperFileCtx {
amdsmi_status_t status = AMDSMI_STATUS_FILE_ERROR;
std::unique_ptr<char[]> buffer;
long file_size = 0;
};
static auto amdsmi_read_cper_file(const std::string &filepath) -> CperFileCtx {
std::ostringstream ss;
CperFileCtx ctx;
ctx.status = AMDSMI_STATUS_FILE_ERROR;
ctx.file_size = 0;
struct stat file_stats;
if (stat(filepath.c_str(), &file_stats) == 0) {
if (!S_ISREG(file_stats.st_mode)) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] file is not a regular file: "
<< filepath << ", errno: " << errno << "): " << strerror(errno);
return ctx;
}
} else {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] file does not exist: "
<< filepath << ", errno: " << errno << "): " << strerror(errno);
ctx.status = AMDSMI_STATUS_NOT_SUPPORTED;
return ctx;
}
ctx.file_size = file_stats.st_size;
ctx.buffer = std::make_unique<char[]>(ctx.file_size);
int file = open(filepath.c_str(), O_RDONLY);
if (file == -1) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] failed to open file: "
<< filepath << ", errno:()" << errno << "): " << strerror(errno);
LOG_ERROR(ss);
return ctx;
}
long bytes_read = read(file, ctx.buffer.get(), ctx.file_size);
if (bytes_read <= 0) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] failed to read complete file, read only "
<< bytes_read << " of " << ctx.file_size << " bytes";
LOG_ERROR(ss);
return ctx;
}
close(file);
ctx.status = AMDSMI_STATUS_SUCCESS;
ctx.file_size = bytes_read;
return ctx;
}
amdsmi_status_t amdsmi_get_gpu_cper_entries_by_path(
const char *amdgpu_ring_cper_file,
uint32_t severity_mask,
char *cper_data,
uint64_t *buf_size,
amdsmi_cper_hdr_t **cper_hdrs,
uint64_t *entry_count,
uint64_t *cursor) {
std::ostringstream ss;
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] begin\n"
<< ", amdgpu_ring_cper_file: " << amdgpu_ring_cper_file
<< ", severity_mask: " << severity_mask;
LOG_DEBUG(ss);
if(!cper_data) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper_data should be a valid memory address\n";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
if(buf_size) { *buf_size = 0; }
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!buf_size) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] buf_size should be a valid memory address";
LOG_ERROR(ss);
if(entry_count) {*entry_count = 0;}
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!entry_count) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] entry_count should be a valid memory address";
LOG_ERROR(ss);
*buf_size = 0;
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!*buf_size) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] buf_size should be greater than zero";
LOG_ERROR(ss);
*entry_count = 0;
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!*entry_count) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] entry_count should be greater than 0";
LOG_ERROR(ss);
*buf_size = 0;
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!cper_hdrs) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper_hdrs should be a valid memory address";
LOG_ERROR(ss);
*entry_count = 0;
*buf_size = 0;
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
else if(!cursor) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cursor should be a valid memory address";
LOG_ERROR(ss);
*entry_count = 0;
*buf_size = 0;
return AMDSMI_STATUS_OUT_OF_RESOURCES;
}
auto ctx = amdsmi_read_cper_file(amdgpu_ring_cper_file);
if(ctx.status != AMDSMI_STATUS_SUCCESS) {
*entry_count = 0;
*buf_size = 0;
return ctx.status;
}
auto headers = amdsmi_get_gpu_cper_headers(ctx.buffer.get(), ctx.file_size);
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] num headers: " << headers.size();
LOG_DEBUG(ss);
uint64_t data_idx = 0;
uint64_t header_idx = 0;
size_t num_headers_copied = 0;
for(const amdsmi_cper_hdr_t *header: headers) {
if(((1 << header->error_severity) & severity_mask) !=
static_cast<uint32_t>(1 << header->error_severity)) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper header rejected with severity: 0x"
<< std::hex << (1 << header->error_severity) << ", given severity_mask: 0x"
<< std::hex << severity_mask << ", record_length:"
<< std::dec << header->record_length;
LOG_DEBUG(ss);
continue;
}
else {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper header accepted with severity: 0x"
<< std::hex << (1 << header->error_severity) << ", given severity_mask: 0x"
<< std::hex << severity_mask << ", record_length:"
<< std::dec << header->record_length;
LOG_DEBUG(ss);
}
if((*buf_size - data_idx) < header->record_length ) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] buffer filled up without copying all cper entries, buf_size: " << std::dec << *buf_size;
LOG_ERROR(ss);
*entry_count = num_headers_copied;
*buf_size = data_idx;
return (data_idx == 0) ?
AMDSMI_STATUS_OUT_OF_RESOURCES :
AMDSMI_STATUS_MORE_DATA;
}
if(num_headers_copied == *entry_count) {
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__ << "[CPER] cper_hdrs filled up before finished with copying all header pointers, entry_count: " << std::dec << *entry_count;
LOG_ERROR(ss);
*entry_count = num_headers_copied;
*buf_size = data_idx;
return (data_idx == 0) ?
AMDSMI_STATUS_OUT_OF_RESOURCES :
AMDSMI_STATUS_MORE_DATA;
}
if(*cursor != header_idx) {
++header_idx;
continue;
}
cper_hdrs[num_headers_copied] = reinterpret_cast<amdsmi_cper_hdr_t*>(&cper_data[data_idx]);
++num_headers_copied;
*cursor = ++header_idx;
std::memcpy(
&cper_data[data_idx],
reinterpret_cast<const char*>(header),
header->record_length);
data_idx += header->record_length;
}
*entry_count = num_headers_copied;
*buf_size = data_idx;
ss << __PRETTY_FUNCTION__ << "\n:" << __LINE__
<< "[CPER] *entry_count: " << entry_count
<< ", *cursor: " << cursor
<< ", *buf_size: " << buf_size;
LOG_DEBUG(ss);
return AMDSMI_STATUS_SUCCESS;
}
@@ -61,9 +61,6 @@ target_link_libraries(${TEST}
stdc++
pthread)
target_compile_definitions(${TEST} PRIVATE
CPER_SYS_ROOT="${CMAKE_CURRENT_SOURCE_DIR}/cper")
# Install tests
install(
TARGETS ${TEST}
@@ -79,4 +76,3 @@ install(
install(TARGETS gtest gtest_main
DESTINATION ${SHARE_INSTALL_PREFIX}/tests
COMPONENT ${TESTS_COMPONENT})
@@ -1,365 +0,0 @@
/*
* Copyright (c) Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in 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:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* 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
* AUTHORS 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 IN
* THE SOFTWARE.
*/
#include <cstdint>
#include <gtest/gtest.h>
#include "amd_smi/amdsmi.h"
#include "rocm_smi/rocm_smi_logger.h"
extern amdsmi_status_t
amdsmi_get_gpu_cper_entries_by_path(
const std::string &amdgpu_ring_cper_file,
uint32_t severity_mask,
char *cper_data,
uint64_t *buf_size,
amdsmi_cper_hdr_t **cper_hdrs,
uint64_t *entry_count,
uint64_t *cursor);
class CperEntriesTest : public testing::Test{
//class object public so that it is accessible
//within the tests that are written
public:
CperEntriesTest() {
setenv("CPER_SYS_ROOT", CPER_SYS_ROOT, 1);
ROCmLogging::Logger::getInstance()->
updateLogLevel(ROCmLogging::LogLevel::LOG_LEVEL_DEBUG);
}
};
TEST_F(CperEntriesTest, TestNullCperData){
uint32_t gpu_num = 9;
uint32_t severity_mask = amdsmi_cper_sev_t::AMDSMI_CPER_SEV_FATAL;
char *cper_data = nullptr;
uint64_t buf_size = 0;
amdsmi_cper_hdr_t *cper_hdrs = nullptr;
uint64_t entry_count = 0;
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data,
nullptr,
&cper_hdrs,
&entry_count,
&cursor);
ASSERT_EQ(err, AMDSMI_STATUS_OUT_OF_RESOURCES);
}
TEST_F(CperEntriesTest, TestNullBufferSize){
uint32_t gpu_num = 9;
uint32_t severity_mask = amdsmi_cper_sev_t::AMDSMI_CPER_SEV_FATAL;
uint64_t buf_size = 0;
auto cper_data = std::make_unique<char[]>(buf_size);
amdsmi_cper_hdr_t *cper_hdrs = nullptr;
uint64_t entry_count = 0;
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
nullptr,
&cper_hdrs,
&entry_count,
&cursor);
ASSERT_EQ(err, AMDSMI_STATUS_OUT_OF_RESOURCES);
}
TEST_F(CperEntriesTest, TestNullCperHeaders){
uint32_t gpu_num = 9;
uint32_t severity_mask = amdsmi_cper_sev_t::AMDSMI_CPER_SEV_FATAL;
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
amdsmi_cper_hdr_t *cper_hdrs = nullptr;
uint64_t entry_count = 0;
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
&cper_hdrs,
&entry_count,
&cursor);
ASSERT_EQ(err, AMDSMI_STATUS_OUT_OF_RESOURCES);
}
TEST_F(CperEntriesTest, TestNullCperHeaderEntryCount){
uint32_t gpu_num = 9;
uint32_t severity_mask = amdsmi_cper_sev_t::AMDSMI_CPER_SEV_FATAL;
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 0;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
nullptr,
&cursor);
ASSERT_EQ(err, AMDSMI_STATUS_OUT_OF_RESOURCES);
}
TEST_F(CperEntriesTest, TestNotEnoughBufferSize){
uint32_t gpu_num = 9;
uint32_t severity_mask =
AMDSMI_CPER_SEV_NON_FATAL_UNCORRECTED|
AMDSMI_CPER_SEV_NON_FATAL_CORRECTED|
AMDSMI_CPER_SEV_FATAL;
uint64_t buf_size = 1024;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 10;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(err, AMDSMI_STATUS_MORE_DATA);
ASSERT_EQ(entry_count, 2);
}
TEST_F(CperEntriesTest, TestNotEnoughHeaderPtrs){
uint32_t gpu_num = 9;
uint32_t severity_mask =
AMDSMI_CPER_SEV_NON_FATAL_UNCORRECTED|
AMDSMI_CPER_SEV_NON_FATAL_CORRECTED|
AMDSMI_CPER_SEV_FATAL;
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 4;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(entry_count, 4);
ASSERT_EQ(err, AMDSMI_STATUS_MORE_DATA);
}
TEST_F(CperEntriesTest, TestGetsAllSeverityErrors){
uint32_t gpu_num = 9;
uint32_t severity_mask =
(1 << AMDSMI_CPER_SEV_NON_FATAL_UNCORRECTED)|
(1 << AMDSMI_CPER_SEV_NON_FATAL_CORRECTED)|
(1 << AMDSMI_CPER_SEV_FATAL);
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 10;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(entry_count, 8);
ASSERT_EQ(err, AMDSMI_STATUS_SUCCESS);
}
TEST_F(CperEntriesTest, TestGetsCorrectableSeverityErrors){
uint32_t gpu_num = 9;
uint32_t severity_mask =
(1 << AMDSMI_CPER_SEV_NON_FATAL_CORRECTED);
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 10;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(entry_count, 1);
ASSERT_EQ(err, AMDSMI_STATUS_SUCCESS);
}
TEST_F(CperEntriesTest, TestGetsFatalSeverityErrors){
uint32_t gpu_num = 9;
uint32_t severity_mask =
(1 << AMDSMI_CPER_SEV_FATAL);
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 10;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(entry_count, 1);
ASSERT_EQ(err, AMDSMI_STATUS_SUCCESS);
}
TEST_F(CperEntriesTest, TestGetsUncorrectableSeverityErrors){
uint32_t gpu_num = 9;
uint32_t severity_mask =
(1 << AMDSMI_CPER_SEV_NON_FATAL_UNCORRECTED);
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 10;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(entry_count, 6);
ASSERT_EQ(err, AMDSMI_STATUS_SUCCESS);
}
TEST_F(CperEntriesTest, TestCursor5GetsLast3HeadersGivenTotal8Headers){
uint32_t gpu_num = 9;
uint32_t severity_mask =
(1 << AMDSMI_CPER_SEV_NON_FATAL_UNCORRECTED)|
(1 << AMDSMI_CPER_SEV_NON_FATAL_CORRECTED)|
(1 << AMDSMI_CPER_SEV_FATAL);
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 10;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 5;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(entry_count, 3);
ASSERT_EQ(err, AMDSMI_STATUS_SUCCESS);
}
TEST_F(CperEntriesTest, TestCursorAdvances){
uint32_t gpu_num = 9;
uint32_t severity_mask =
(1 << AMDSMI_CPER_SEV_NON_FATAL_UNCORRECTED)|
(1 << AMDSMI_CPER_SEV_NON_FATAL_CORRECTED)|
(1 << AMDSMI_CPER_SEV_FATAL);
uint64_t buf_size = 512;//4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 10;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t buf_size_original = buf_size;
uint64_t entry_count_original = entry_count;
uint64_t cursor_idx = 0;
uint64_t cursor = 0;
while(true) {
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(entry_count, 1);
ASSERT_EQ(cursor, ++cursor_idx);
ASSERT_TRUE(err == AMDSMI_STATUS_MORE_DATA || err == AMDSMI_STATUS_SUCCESS);
if(err == AMDSMI_STATUS_SUCCESS) {
break;
}
buf_size = buf_size_original;
entry_count = entry_count_original;
}
}
TEST_F(CperEntriesTest, TestGetsCorrectHeaderCountFromAllDevices) {
//we can get these deviceids by calling:
// ls -alh tests/amd_smi_test/cper/sys/kernel/debug/dri/
static constexpr int deviceids[] = { 1, 9, 17, 25, 33};
//we can get the numbers in the expected_num_headers array below by calling:
// hexdump -C tests/amd_smi_test/cper/sys/kernel/debug/dri/<deviceid>/amdgpu_ring_cper | grep CPER|wc -l
// where <deviceid> is one of the entries in the deviceids array above.
static constexpr int expected_num_headers[] = { 19, 8, 7, 4, 7};
for(int device_idx = 0;
device_idx < sizeof(deviceids)/sizeof(deviceids[0]);
++device_idx) {
uint32_t gpu_num = deviceids[device_idx];
uint32_t severity_mask =
(1 << AMDSMI_CPER_SEV_NON_FATAL_UNCORRECTED)|
(1 << AMDSMI_CPER_SEV_NON_FATAL_CORRECTED)|
(1 << AMDSMI_CPER_SEV_FATAL);
uint64_t buf_size = 4 * (1<<20); //4 MB;
auto cper_data = std::make_unique<char[]>(buf_size);
uint64_t entry_count = 20;
auto cper_hdrs = std::make_unique<amdsmi_cper_hdr_t*[]>(entry_count);
uint64_t cursor = 0;
std::string gpu = std::string(CPER_SYS_ROOT) + "/sys/kernel/debug/dri/" + std::to_string(gpu_num) + "/amdgpu_ring_cper";
amdsmi_status_t err = amdsmi_get_gpu_cper_entries_by_path(
gpu,
severity_mask,
cper_data.get(),
&buf_size,
cper_hdrs.get(),
&entry_count,
&cursor);
ASSERT_EQ(err, AMDSMI_STATUS_SUCCESS);
ASSERT_EQ(entry_count, expected_num_headers[device_idx]);
ASSERT_EQ(cursor, expected_num_headers[device_idx]);
}
}