[SWDEV-511234] Added amdsmi_get_gpu_cper_entries & CLI implementation
Added amdsmi_get_gpu_cper_entries() in the python and C APIs Signed-off-by: Maisam Arif <Maisam.Arif@amd.com> Signed-off-by: Oliveira, Daniel <daniel.oliveira@amd.com> Co-authored-by: Saeed, Oosman <Oosman.Saeed@amd.com> Co-authored-by: AL Musaffar, Yazen <Yazen.ALMusaffar@amd.com>
This commit is contained in:
23 files changed
+1532
-127
No files matched your search
@@ -25,7 +25,7 @@ import os
|
||||
import re
|
||||
import sys
|
||||
from collections.abc import Iterable
|
||||
from enum import IntEnum
|
||||
from enum import IntEnum, Enum
|
||||
from pathlib import Path
|
||||
from time import asctime, localtime, time
|
||||
from typing import Any, Dict, List, Tuple, Union
|
||||
@@ -386,6 +386,21 @@ class AmdSmiRasErrState(IntEnum):
|
||||
INVALID = amdsmi_wrapper.AMDSMI_RAS_ERR_STATE_INVALID
|
||||
|
||||
|
||||
class AmdSmiCperNotifyType(Enum):
|
||||
CMC = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_CMC
|
||||
CPE = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_CPE
|
||||
MCE = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_MCE
|
||||
PCIE = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_PCIE
|
||||
INIT = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_INIT
|
||||
NMI = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_NMI
|
||||
BOOT = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_BOOT
|
||||
DMAr = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_DMAR
|
||||
SEA = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_SEA
|
||||
SEI = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_SEI
|
||||
PEI = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_PEI
|
||||
CXL_COMPONENT = amdsmi_wrapper.AMDSMI_CPER_NOTIFY_TYPE_CXL_COMPONENT
|
||||
|
||||
|
||||
class AmdSmiMemoryType(IntEnum):
|
||||
VRAM = amdsmi_wrapper.AMDSMI_MEM_TYPE_VRAM
|
||||
VIS_VRAM = amdsmi_wrapper.AMDSMI_MEM_TYPE_VIS_VRAM
|
||||
@@ -460,6 +475,7 @@ class AmdSmiVirtualizationMode(IntEnum):
|
||||
GUEST = amdsmi_wrapper.AMDSMI_VIRTUALIZATION_MODE_GUEST
|
||||
PASSTHROUGH = amdsmi_wrapper.AMDSMI_VIRTUALIZATION_MODE_PASSTHROUGH
|
||||
|
||||
|
||||
class AmdSmiVramType(IntEnum):
|
||||
UNKNOWN = amdsmi_wrapper.AMDSMI_VRAM_TYPE_UNKNOWN
|
||||
HBM = amdsmi_wrapper.AMDSMI_VRAM_TYPE_HBM
|
||||
@@ -478,6 +494,7 @@ class AmdSmiVramType(IntEnum):
|
||||
GDDR7 = amdsmi_wrapper.AMDSMI_VRAM_TYPE_GDDR7
|
||||
MAX = amdsmi_wrapper.AMDSMI_VRAM_TYPE__MAX
|
||||
|
||||
|
||||
class AmdSmiVramVendor(IntEnum):
|
||||
SAMSUNG = amdsmi_wrapper.AMDSMI_VRAM_VENDOR_SAMSUNG
|
||||
INFINEON = amdsmi_wrapper.AMDSMI_VRAM_VENDOR_INFINEON
|
||||
@@ -491,6 +508,7 @@ class AmdSmiVramVendor(IntEnum):
|
||||
MICRON = amdsmi_wrapper.AMDSMI_VRAM_VENDOR_MICRON
|
||||
UNKNOWN = amdsmi_wrapper.AMDSMI_VRAM_VENDOR_UNKNOWN
|
||||
|
||||
|
||||
class AmdSmiEventReader:
|
||||
def __init__(
|
||||
self, processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
||||
@@ -699,6 +717,21 @@ def _validate_if_max_uint(value, uint_type: MaxUIntegerTypes, isActivity=False,
|
||||
else:
|
||||
return return_val
|
||||
|
||||
|
||||
def _notifyTypeToString(notify_type_b):
|
||||
guid = []
|
||||
# Iterate over only the first 8 bytes, but backwards
|
||||
for i in notify_type_b[7::-1]:
|
||||
guid.append(format(i, '02x'))
|
||||
hex_string = "".join(guid)
|
||||
hex_value = int(hex_string, 16)
|
||||
if hex_value in AmdSmiCperNotifyType._value2member_map_:
|
||||
# Convert to the corresponding enum name
|
||||
return AmdSmiCperNotifyType(hex_value).name
|
||||
else:
|
||||
return "Unknown"
|
||||
|
||||
|
||||
def amdsmi_get_socket_handles() -> List[amdsmi_wrapper.amdsmi_socket_handle]:
|
||||
"""
|
||||
Function that gets socket handles. Wraps the same named function call.
|
||||
@@ -1782,7 +1815,7 @@ def amdsmi_get_gpu_enumeration_info(processor_handle: amdsmi_wrapper.amdsmi_proc
|
||||
|
||||
# Call the C function to populate the struct
|
||||
status = amdsmi_wrapper.amdsmi_get_gpu_enumeration_info(processor_handle, ctypes.byref(enumeration_info))
|
||||
|
||||
|
||||
# Validate the status result
|
||||
_check_res(status)
|
||||
|
||||
@@ -2238,6 +2271,96 @@ def amdsmi_get_gpu_total_ecc_count(
|
||||
"deferred_count": ec.deferred_count,
|
||||
}
|
||||
|
||||
def notifyTypeToString(notify_type_b):
|
||||
idx = 0
|
||||
guid = []
|
||||
for i in notify_type_b:
|
||||
guid.append(format(i, '02x'))
|
||||
if idx == 7:
|
||||
break
|
||||
idx = idx +1
|
||||
return "".join(guid[::-1])
|
||||
|
||||
def amdsmi_get_gpu_cper_entries(processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
||||
severity_mask: int,
|
||||
buffer_size: int = 4*1048576,
|
||||
cursor: int = 0
|
||||
) -> Tuple[List[Dict[str, Any]], int]:
|
||||
|
||||
if not isinstance(processor_handle, amdsmi_wrapper.amdsmi_processor_handle):
|
||||
raise AmdSmiParameterException(
|
||||
processor_handle, amdsmi_wrapper.amdsmi_processor_handle
|
||||
)
|
||||
|
||||
# Allocate a buffer for CPER data.
|
||||
buf = ctypes.create_string_buffer(buffer_size)
|
||||
buf_size = ctypes.c_uint64(buffer_size)
|
||||
entry_count = ctypes.c_uint64(20)
|
||||
cur = ctypes.c_uint64(cursor)
|
||||
# Allocate a pointer for the CPER header array.
|
||||
cper_hdrs_array = (ctypes.POINTER(amdsmi_wrapper.amdsmi_cper_hdr_t) * 20)()
|
||||
cper_hdrs = ctypes.cast(cper_hdrs_array, ctypes.POINTER(ctypes.POINTER(amdsmi_wrapper.amdsmi_cper_hdr_t)))
|
||||
|
||||
# Call the underlying AMD-SMI API.
|
||||
ret = amdsmi_wrapper.amdsmi_get_gpu_cper_entries(
|
||||
processor_handle,
|
||||
ctypes.c_uint32(severity_mask),
|
||||
buf,
|
||||
ctypes.byref(buf_size),
|
||||
cper_hdrs,
|
||||
ctypes.byref(entry_count),
|
||||
ctypes.byref(cur)
|
||||
)
|
||||
if ret != amdsmi_wrapper.AMDSMI_STATUS_SUCCESS:
|
||||
raise AmdSmiLibraryException(ret)
|
||||
|
||||
entries = {}
|
||||
cper_data = []
|
||||
offset = 0
|
||||
# Iterate over each entry using its variable record_length.
|
||||
for i in range(entry_count.value):
|
||||
entry_address = ctypes.addressof(buf) + offset
|
||||
entry_ptr = ctypes.cast(entry_address, ctypes.POINTER(amdsmi_wrapper.amdsmi_cper_hdr_t))
|
||||
cper_data.append({
|
||||
"bytes":list((entry_ptr.contents.record_length * ctypes.c_byte).from_address(entry_address)),
|
||||
"size":entry_ptr.contents.record_length
|
||||
})
|
||||
# Extract the timestamp fields.
|
||||
year = entry_ptr.contents.timestamp.year
|
||||
# Adjust the year if it's less than 100. You can tweak this logic based on your expected data.
|
||||
if year < 100:
|
||||
year += 2000
|
||||
formatted_timestamp = (
|
||||
f"{year:04d}/"
|
||||
f"{entry_ptr.contents.timestamp.month:02d}/"
|
||||
f"{entry_ptr.contents.timestamp.day:02d} "
|
||||
f"{entry_ptr.contents.timestamp.hours:02d}:"
|
||||
f"{entry_ptr.contents.timestamp.minutes:02d}:"
|
||||
f"{entry_ptr.contents.timestamp.seconds:02d}"
|
||||
)
|
||||
cper_entry = {
|
||||
"error_severity": amdsmi_wrapper.amdsmi_cper_sev_t__enumvalues.get(entry_ptr.contents.error_severity, "AMDSMI_CPER_SEV_UNUSED").replace("AMDSMI_CPER_SEV_", "").lower(),
|
||||
"notify_type": _notifyTypeToString(entry_ptr.contents.notify_type.b),
|
||||
"timestamp": formatted_timestamp,
|
||||
"signature" : entry_ptr.contents.signature,
|
||||
"revision" : entry_ptr.contents.revision,
|
||||
"signature_end" : hex(entry_ptr.contents.signature_end),
|
||||
"sec_cnt" : entry_ptr.contents.sec_cnt,
|
||||
"record_length" : entry_ptr.contents.record_length,
|
||||
"platform_id" : entry_ptr.contents.platform_id,
|
||||
"creator_id" : entry_ptr.contents.creator_id,
|
||||
"record_id" : entry_ptr.contents.record_id,
|
||||
"flags" : entry_ptr.contents.flags,
|
||||
"persistence_info" : entry_ptr.contents.persistence_info,
|
||||
#"reserved" : entry_ptr.contents.reserved
|
||||
#"cper_valid_bit" : entry_ptr.contents.cper_valid_bits,
|
||||
#"partition_id" : entry_ptr.contents.partition_id,
|
||||
}
|
||||
entries[i] = cper_entry.copy()
|
||||
offset += entry_ptr.contents.record_length # Use the actual record length to advance the offset
|
||||
|
||||
return entries, cur.value, cper_data
|
||||
|
||||
|
||||
def amdsmi_get_gpu_board_info(
|
||||
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
|
||||
@@ -2938,7 +3061,7 @@ def amdsmi_get_gpu_memory_partition_config(processor_handle: amdsmi_wrapper.amds
|
||||
raise AmdSmiParameterException(
|
||||
processor_handle, amdsmi_wrapper.amdsmi_processor_handle
|
||||
)
|
||||
|
||||
|
||||
config = amdsmi_wrapper.amdsmi_memory_partition_config_t()
|
||||
|
||||
_check_res(
|
||||
@@ -3017,10 +3140,10 @@ def amdsmi_get_gpu_accelerator_partition_profile(
|
||||
)
|
||||
profile_type_ret = amdsmi_wrapper.amdsmi_accelerator_partition_type_t__enumvalues[profile.profile_type].replace("AMDSMI_ACCELERATOR_PARTITION_", "")
|
||||
profile_type_ret = profile_type_ret.replace("INVALID", "N/A")
|
||||
|
||||
|
||||
length = profile.num_partitions
|
||||
partition_ids = []
|
||||
|
||||
|
||||
#partition_id[0] will contain the partition id of each device
|
||||
#BM/Guest will include this logic. Host will only display primary partition ids.
|
||||
kPOSITION_OF_PARTITION_ID = 0
|
||||
@@ -3079,7 +3202,7 @@ def amdsmi_get_gpu_accelerator_partition_profile_config(processor_handle: amdsmi
|
||||
profile_type_ret = profile_type_ret.replace("INVALID", "N/A")
|
||||
resources = []
|
||||
|
||||
|
||||
|
||||
mem_caps_list = []
|
||||
if profile.memory_caps.nps_flags.nps1_cap == 1:
|
||||
mem_caps_list.append("NPS1")
|
||||
@@ -3104,7 +3227,7 @@ def amdsmi_get_gpu_accelerator_partition_profile_config(processor_handle: amdsmi
|
||||
logging.debug("\namdsmi_interface.py | amdsmi_get_gpu_accelerator_partition_profile_config | resource_profile_dict = " + str(resource_profile_dict))
|
||||
resources.append(resource_profile_dict)
|
||||
resource_idx += 1
|
||||
|
||||
|
||||
profile_dict = {
|
||||
"profile_type": profile_type_ret,
|
||||
"num_partitions": profile.num_partitions,
|
||||
|
||||
Reference in new issue
Block a user