[SWDEV-522623] Add afid functionality to API and CLI (#330)

Change-Id: I015bde926491d54e09da8f39b05650515711e09f

[SWDEV-522623] Add afid functionality to API and CLI


Change-Id: I015bde926491d54e09da8f39b05650515711e09f

Signed-off-by: Oosman Saeed <oossaeed@amd.com>
Co-authored-by: Oosman Saeed <oossaeed@amd.com>
This commit is contained in:
Saeed, Oosman
2025-05-15 21:49:56 -05:00
committed by GitHub
parent d4f057f95f
commit 1bb1f8acc2
21 changed files with 2228 additions and 209 deletions
+93 -26
View File
@@ -60,6 +60,9 @@ AMDSMI_MAX_NUM_JPEG = 32
AMDSMI_MAX_NUM_XCC = 8
AMDSMI_MAX_NUM_XCP = 8
# max num afids per cper record
MAX_NUMBER_OF_AFIDS_PER_RECORD = 12
# Max number of DPM policies
AMDSMI_MAX_NUM_PM_POLICIES = 32
@@ -1888,7 +1891,6 @@ def amdsmi_get_gpu_asic_info(
# Remove commas from vendor name for clean output
asic_info["vendor_name"] = asic_info["vendor_name"].replace(',', '')
# logging.debug("amdsmi_interface.py | amdsmi_get_gpu_asic_info | return_dictionary = \n" + str(json.dumps(asic_info, indent=4)))
return asic_info
@@ -2300,9 +2302,10 @@ def notifyTypeToString(notify_type_b):
idx = idx +1
return "".join(guid[::-1])
def amdsmi_get_gpu_cper_entries(processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
def amdsmi_get_gpu_cper_entries(
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
severity_mask: int,
buffer_size: int = 4*1048576,
buffer_size: int = 4 * 1048576,
cursor: int = 0
) -> Tuple[List[Dict[str, Any]], int]:
@@ -2316,6 +2319,7 @@ def amdsmi_get_gpu_cper_entries(processor_handle: amdsmi_wrapper.amdsmi_processo
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)))
@@ -2336,51 +2340,114 @@ def amdsmi_get_gpu_cper_entries(processor_handle: amdsmi_wrapper.amdsmi_processo
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))
# Extract the raw bytes and size of the entry.
cper_data.append({
"bytes":list((entry_ptr.contents.record_length * ctypes.c_byte).from_address(entry_address)),
"size":entry_ptr.contents.record_length
"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
if year < 100: # Adjust the year if it's less than 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}"
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}"
)
# Create a dictionary for the CPER entry.
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(),
"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,
"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
offset += entry_ptr.contents.record_length # Use the actual record length to advance the offset.
return entries, cur.value, cper_data
def amdsmi_get_afids_from_cper(
cper_afid_data: Union[bytes, bytearray, List[Dict[str, Any]]]
) -> Tuple[List[int], int]:
"""
Extract AFIDs from one or more CPER blobs.
Args:
cper_afid_data: Either
- raw bytes or bytearray of a single CPER record, or
- a list of dicts each with keys "bytes" (List[int]) and "size" (int).
Returns:
Tuple[List[int], int]: A tuple containing:
- A list of extracted AFIDs.
- The total count of AFIDs.
"""
# Normalize single blob into a list of records
if isinstance(cper_afid_data, (bytes, bytearray)):
cper_records = [{
"bytes": list(cper_afid_data),
"size": len(cper_afid_data)
}]
else:
cper_records = cper_afid_data
all_afids: List[int] = []
for record in cper_records:
raw_bytes = bytes(record["bytes"])
record_size = record["size"]
# Wrap as char*
buf = ctypes.create_string_buffer(raw_bytes, record_size)
buf_ptr = ctypes.cast(buf, ctypes.POINTER(ctypes.c_char))
afid_array = (ctypes.c_uint64 * MAX_NUMBER_OF_AFIDS_PER_RECORD)()
num_afids_ct = ctypes.c_uint32(MAX_NUMBER_OF_AFIDS_PER_RECORD)
# Call the wrapper function
status = amdsmi_wrapper.amdsmi_get_afids_from_cper(
buf_ptr,
ctypes.c_uint32(record_size),
afid_array,
ctypes.byref(num_afids_ct)
)
if status != amdsmi_wrapper.AMDSMI_STATUS_SUCCESS:
raise AmdSmiLibraryException(f"get_afids failed: {status}")
# Collect exactly the decoded AFIDs
count = num_afids_ct.value
all_afids.extend(afid_array[i] for i in range(count))
return all_afids, len(all_afids)
def amdsmi_get_gpu_board_info(
processor_handle: amdsmi_wrapper.amdsmi_processor_handle,
) -> Dict[str, Any]:
+6 -3
View File
@@ -2642,6 +2642,9 @@ amdsmi_cper_hdr_t = struct_amdsmi_cper_hdr_t
amdsmi_get_gpu_cper_entries = _libraries['libamd_smi.so'].amdsmi_get_gpu_cper_entries
amdsmi_get_gpu_cper_entries.restype = amdsmi_status_t
amdsmi_get_gpu_cper_entries.argtypes = [amdsmi_processor_handle, uint32_t, ctypes.POINTER(ctypes.c_char), ctypes.POINTER(ctypes.c_uint64), ctypes.POINTER(ctypes.POINTER(struct_amdsmi_cper_hdr_t)), ctypes.POINTER(ctypes.c_uint64), ctypes.POINTER(ctypes.c_uint64)]
amdsmi_get_afids_from_cper = _libraries['libamd_smi.so'].amdsmi_get_afids_from_cper
amdsmi_get_afids_from_cper.restype = amdsmi_status_t
amdsmi_get_afids_from_cper.argtypes = [ctypes.POINTER(ctypes.c_char), uint32_t, ctypes.POINTER(ctypes.c_uint64), ctypes.POINTER(ctypes.c_uint32)]
amdsmi_get_gpu_ecc_status = _libraries['libamd_smi.so'].amdsmi_get_gpu_ecc_status
amdsmi_get_gpu_ecc_status.restype = amdsmi_status_t
amdsmi_get_gpu_ecc_status.argtypes = [amdsmi_processor_handle, amdsmi_gpu_block_t, ctypes.POINTER(amdsmi_ras_err_state_t)]
@@ -3171,9 +3174,9 @@ __all__ = \
'amdsmi_free_name_value_pairs', 'amdsmi_freq_ind_t',
'amdsmi_freq_volt_region_t', 'amdsmi_frequencies_t',
'amdsmi_frequency_range_t', 'amdsmi_fw_block_t',
'amdsmi_fw_info_t', 'amdsmi_get_clk_freq',
'amdsmi_get_clock_info', 'amdsmi_get_cpu_cclk_limit',
'amdsmi_get_cpu_core_boostlimit',
'amdsmi_fw_info_t', 'amdsmi_get_afids_from_cper',
'amdsmi_get_clk_freq', 'amdsmi_get_clock_info',
'amdsmi_get_cpu_cclk_limit', 'amdsmi_get_cpu_core_boostlimit',
'amdsmi_get_cpu_core_current_freq_limit',
'amdsmi_get_cpu_core_energy',
'amdsmi_get_cpu_current_io_bandwidth',