diff --git a/amdsmi_cli/amdsmi_parser.py b/amdsmi_cli/amdsmi_parser.py index 0ca762e717..d1aaef89ba 100644 --- a/amdsmi_cli/amdsmi_parser.py +++ b/amdsmi_cli/amdsmi_parser.py @@ -308,6 +308,7 @@ class AMDSMIParser(argparse.ArgumentParser): """ class _CheckInputFilePath(argparse.Action): # Checks the values + outputformat=self.helpers.get_output_format() def __call__(self, parser, args, values, option_string=None): path = Path(values) try: diff --git a/include/aca-decode/aca_api.h b/include/aca-decode/aca_api.h new file mode 100644 index 0000000000..a8cbc207dc --- /dev/null +++ b/include/aca-decode/aca_api.h @@ -0,0 +1,48 @@ +#ifndef ACA_API_H +#define ACA_API_H + +#include +#include + +/** + * @brief Structure containing decoded error information + */ +typedef struct +{ + const char *bank_ref; /**< Reference to bank name string */ + const char *error_type_ref; /**< Reference to error type string */ + const char *severity_ref; /**< Reference to error severity string */ + const char *category_ref; /**< Reference to error category string */ + const char *instance_ref; /**< Reference to instance name string */ + int oam; /**< OAM value */ + int aid; /**< AID value */ + int afid; /**< AFID value (AMD Field ID) */ + uint64_t raw_status; /**< Raw status register value */ + uint64_t raw_addr; /**< Raw address register value */ + uint64_t raw_ipid; /**< Raw IPID register value */ + uint64_t raw_synd; /**< Raw syndrome register value */ + uint8_t scrub; /**< Scrub bit from status */ + uint8_t error_code_ext; /**< Extended error code from status */ +} aca_error_info_t; + +/** + * @brief Decodes the AFID from a register array + * @param[in] register_array Pointer to an array of 64-bit register values + * @param[in] array_len Size of register array in elements + * @param[in] flag Decoder flags + * @param[in] hw_revision Hardware revision number + * @return AFID value or -1 if decoding fails + */ +int decode_afid(const uint64_t *register_array, size_t array_len, uint32_t flag, uint16_t hw_revision); + +/** + * @brief Decodes and returns complete error information from a register array + * @param[in] register_array Pointer to an array of 64-bit register values + * @param[in] array_len Size of register array in elements + * @param[in] flag Decoder flags + * @param[in] hw_revision Hardware revision number + * @return Complete error information structure + */ +aca_error_info_t decode_error_info(const uint64_t *register_array, size_t array_len, uint32_t flag, uint16_t hw_revision); + +#endif // ACA_API_H diff --git a/include/aca-decode/aca_decode.h b/include/aca-decode/aca_decode.h index 692eb0fe37..94c7474537 100755 --- a/include/aca-decode/aca_decode.h +++ b/include/aca-decode/aca_decode.h @@ -2,13 +2,15 @@ * @file aca_decode.h * @brief Internal decoder interface and data structures */ -#ifndef ACA_DECODE_H -#define ACA_DECODE_H #ifdef __cplusplus extern "C" { #endif +#ifndef ACA_DECODE_H +#define ACA_DECODE_H + +#include "aca_api.h" #include "aca_fields.h" /** @@ -17,6 +19,7 @@ extern "C" { typedef struct { uint64_t aca_status; /**< Raw status register value */ + uint64_t aca_addr; /**< Raw address register value */ uint64_t aca_ipid; /**< Raw IPID register value */ uint64_t aca_synd; /**< Raw syndrome register value */ uint32_t flags; /**< Decoder flags */ @@ -33,24 +36,13 @@ typedef struct typedef struct { uint64_t aca_status; /**< Raw status register value */ + uint64_t aca_addr; /**< Raw address register value */ uint64_t aca_ipid; /**< Raw IPID register value */ uint64_t aca_synd; /**< Raw syndrome register value */ uint32_t flags; /**< Flags from descriptor */ uint16_t hw_revision; /**< Hardware hw_revision number */ } aca_raw_data_t; -/** - * @brief Structure containing decoded error information - */ -typedef struct -{ - const char *bank_ref; /**< Reference to bank name string */ - const char *error_type_ref; /**< Reference to error type string */ - const char *severity_ref; /**< Reference to error severity string */ - const char *category_ref; /**< Reference to error category string */ - int afid; /**< AFID value (AMD Field ID) */ -} aca_error_info_t; - /** * @brief Main decode function that processes raw ACA error data * @param[in] raw_data Pointer to structure containing raw ACA error data diff --git a/include/aca-decode/aca_fields.h b/include/aca-decode/aca_fields.h index b51214f727..c3a38339eb 100644 --- a/include/aca-decode/aca_fields.h +++ b/include/aca-decode/aca_fields.h @@ -79,6 +79,16 @@ typedef struct uint32_t reserved39; } aca_synd_fields_t; +/** + * @brief Structure containing decoded ACA address register fields + */ +typedef struct +{ + aca_fields_t base; + uint64_t error_addr; + uint64_t reserved; +} aca_addr_fields_t; + /** * @brief Reads the raw value from an ACA field structure * @param[in] fields Pointer to the ACA fields structure @@ -107,4 +117,11 @@ void aca_ipid_init(aca_ipid_fields_t *fields, uint64_t ipid_reg); */ void aca_synd_init(aca_synd_fields_t *fields, uint64_t synd_reg); +/** + * @brief Initializes ACA address fields from a raw address register value + * @param[out] fields Pointer to the address fields structure to initialize + * @param[in] addr_reg Raw 64-bit address register value + */ +void aca_addr_init(aca_addr_fields_t *fields, uint64_t addr_reg); + #endif diff --git a/include/aca-decode/aca_tables.h b/include/aca-decode/aca_tables.h index 11660f0d1b..3fe4d457eb 100644 --- a/include/aca-decode/aca_tables.h +++ b/include/aca-decode/aca_tables.h @@ -40,6 +40,25 @@ typedef struct const char *type; /**< Error type string */ } aca_error_entry_t; +/** + * @brief Structure mapping instance_id_hi to OAM and AID values + */ +typedef struct +{ + uint8_t oam; /**< OAM value */ + uint8_t aid; /**< AID value */ +} oam_aid_map_t; + +/** + * @brief Structure for mapping bank and instance ID LO to instance name + */ +typedef struct +{ + const char *bank; /**< Bank name */ + uint32_t instance_id_lo; /**< Instance ID Lo (masked with 0xFFFFFFFC) */ + const char *name; /**< Instance name */ +} aca_instance_entry_t; + // External table declarations extern const aca_bank_entry_t bank_table[]; extern const aca_error_type_t error_table[]; @@ -81,4 +100,21 @@ int find_error_type_by_bank(const char *bank, uint32_t error_code, const char ** int find_error_in_table(const aca_error_entry_t *table, size_t table_size, uint32_t error_code, const char **error_type); +/** + * @brief Find OAM and AID values based on instance_id_hi + * @param[in] instance_id_hi Instance ID low value (0x00-0x0F) + * @param[out] oam_aid Pointer to store OAM and AID values + * @return 0 on success, 1 if not found, -1 on parameter error + */ +int find_oam_aid(uint8_t instance_id_hi, oam_aid_map_t *oam_aid); + +/** + * @brief Find instance name based on bank and instance ID + * @param[in] bank Bank name string + * @param[in] instance_id_lo Instance ID (will be masked with 0xFFFFFFFC) + * @param[out] instance_name Pointer to store result string + * @return 0 on success, 1 if not found, -1 on parameter error + */ +int find_instance_name(const char *bank, uint32_t instance_id_lo, const char **instance_name); + #endif diff --git a/src/aca-decode/aca_api.c b/src/aca-decode/aca_api.c new file mode 100644 index 0000000000..143f9dc275 --- /dev/null +++ b/src/aca-decode/aca_api.c @@ -0,0 +1,71 @@ +#include "aca_decode.h" + +int decode_afid(const uint64_t *register_array, size_t array_len, uint32_t flag, uint16_t hw_revision) +{ + if (!register_array) + { + return -1; + } + + aca_raw_data_t raw_data; + + if (array_len == 4) // 32 bytes + { + raw_data.aca_status = register_array[0]; + raw_data.aca_addr = register_array[1]; + raw_data.aca_ipid = register_array[2]; + raw_data.aca_synd = register_array[3]; + } + else if (array_len == 16) // 128 bytes + { + raw_data.aca_status = register_array[1]; + raw_data.aca_addr = register_array[2]; + raw_data.aca_ipid = register_array[5]; + raw_data.aca_synd = register_array[6]; + } + + else + { + return -1; // Unsupported size + } + + raw_data.flags = flag; + raw_data.hw_revision = hw_revision; + + aca_error_info_t error_info = aca_decode(&raw_data); + return error_info.afid; +} + +aca_error_info_t decode_error_info(const uint64_t *register_array, size_t array_len, uint32_t flag, uint16_t hw_revision) +{ + aca_raw_data_t raw_data = {0}; + aca_error_info_t error_info = {0}; + + if (!register_array) + { + return error_info; + } if (array_len == 4) // 32 bytes + { + raw_data.aca_status = register_array[0]; + raw_data.aca_addr = register_array[1]; + raw_data.aca_ipid = register_array[2]; + raw_data.aca_synd = register_array[3]; + } + else if (array_len == 16) // 128 bytes + { + raw_data.aca_status = register_array[1]; + raw_data.aca_addr = register_array[2]; + raw_data.aca_ipid = register_array[5]; + raw_data.aca_synd = register_array[6]; + } + else + { + return error_info; // Return zero-initialized structure for unsupported size + } + + raw_data.flags = flag; + raw_data.hw_revision = hw_revision; + + return aca_decode(&raw_data); +} + diff --git a/src/aca-decode/aca_decode.c b/src/aca-decode/aca_decode.c index b38fada092..a6876123af 100644 --- a/src/aca-decode/aca_decode.c +++ b/src/aca-decode/aca_decode.c @@ -167,7 +167,17 @@ static void aca_decoder_get_error_info(const aca_decoder_t *decoder, aca_error_i { const char *bank; const char *error_type; + const char *instance_name; int result; + + info->raw_status = decoder->aca_status; + info->raw_addr = decoder->aca_addr; + info->raw_ipid = decoder->aca_ipid; + info->raw_synd = decoder->aca_synd; + + info->scrub = decoder->status.scrub; + info->error_code_ext = decoder->status.error_code_ext; + result = aca_decoder_get_bank(decoder, &bank); if (result < 0) @@ -176,6 +186,15 @@ static void aca_decoder_get_error_info(const aca_decoder_t *decoder, aca_error_i } info->bank_ref = bank; + if (find_instance_name(bank, decoder->ipid.instance_id_lo, &instance_name) == 0) + { + info->instance_ref = instance_name; + } + else + { + info->instance_ref = "Decode Inapplicable"; + } + // 0b1000 indicate error threshold has been exceeded, and is always fatal if (decoder->flags & 0x8) { @@ -186,6 +205,20 @@ static void aca_decoder_get_error_info(const aca_decoder_t *decoder, aca_error_i info->severity_ref = get_error_severity(&decoder->status); } + // Decode OAM and AID from instance_id_lo + oam_aid_map_t oam_aid = {0}; + uint8_t instance_id_lo = decoder->ipid.instance_id_lo & 0xFF; // Get lower 8 bits + if (find_oam_aid(instance_id_lo, &oam_aid) == 0) + { + info->oam = oam_aid.oam; + info->aid = oam_aid.aid; + } + else + { + info->oam = -1; // Invalid value + info->aid = -1; // Invalid value + } + if (decoder->status.error_code_ext >= 0x3A && decoder->status.error_code_ext <= 0x3E) { uint32_t instance_id = decoder->ipid.instance_id_lo; @@ -239,7 +272,7 @@ static void aca_decoder_get_error_info(const aca_decoder_t *decoder, aca_error_i { service_error = info->error_type_ref; } - + info->afid = get_error_id(info->category_ref, service_error, info->severity_ref); } diff --git a/src/aca-decode/aca_fields.c b/src/aca-decode/aca_fields.c index 465c33fa92..bb72be931d 100644 --- a/src/aca-decode/aca_fields.c +++ b/src/aca-decode/aca_fields.c @@ -74,3 +74,10 @@ void aca_synd_init(aca_synd_fields_t *fields, uint64_t synd_reg) fields->syndrome = EXTRACT_BITS(synd_reg, 32, 7, uint16_t); fields->reserved39 = EXTRACT_BITS(synd_reg, 39, 25, uint32_t); } + +void aca_addr_init(aca_addr_fields_t *fields, uint64_t addr_reg) +{ + fields->base.raw_value = addr_reg; + fields->error_addr = EXTRACT_BITS(addr_reg, 0, 56, uint64_t); + fields->reserved = EXTRACT_BITS(addr_reg, 56, 8, uint8_t); +} diff --git a/src/aca-decode/aca_tables.c b/src/aca-decode/aca_tables.c index aecc61e985..4d0c5e70c4 100644 --- a/src/aca-decode/aca_tables.c +++ b/src/aca-decode/aca_tables.c @@ -299,10 +299,144 @@ const aca_error_entry_t aid_error_table[] = { {0x2a, "Reserved"}, {0x2b, "Reserved"}}; +/** + * @brief Table mapping instance_id_hi to OAM and AID values + */ +static const oam_aid_map_t oam_aid_table[] = { + {0, 0}, /* 0x00 */ + {1, 0}, /* 0x01 */ + {2, 0}, /* 0x02 */ + {3, 0}, /* 0x03 */ + {0, 1}, /* 0x04 */ + {1, 1}, /* 0x05 */ + {2, 1}, /* 0x06 */ + {3, 1}, /* 0x07 */ + {0, 2}, /* 0x08 */ + {1, 2}, /* 0x09 */ + {2, 2}, /* 0x0A */ + {3, 2}, /* 0x0B */ + {0, 3}, /* 0x0C */ + {1, 3}, /* 0x0D */ + {2, 3}, /* 0x0E */ + {3, 3} /* 0x0F */ +}; + +// Constants are now defined as global variables + +/** + * @brief Table mapping bank and instance ID to instance names + */ +static const aca_instance_entry_t instance_table[] = { + {"cs", 0x1F002000, "cmp0"}, + {"cs", 0x1F000000, "cs0"}, + {"cs", 0x1F000A00, "cs10"}, + {"cs", 0x1F000B00, "cs11"}, + {"cs", 0x1F000C00, "cs12"}, + {"cs", 0x1F000D00, "cs13"}, + {"cs", 0x1F000E00, "cs14"}, + {"cs", 0x1F000F00, "cs15"}, + {"cs", 0x1F001000, "cs16"}, + {"cs", 0x1F001100, "cs17"}, + {"cs", 0x1F001200, "cs18"}, + {"cs", 0x1F001300, "cs19"}, + {"cs", 0x1F000100, "cs1"}, + {"cs", 0x1F001400, "cs20"}, + {"cs", 0x1F001500, "cs21"}, + {"cs", 0x1F001600, "cs22"}, + {"cs", 0x1F001700, "cs23"}, + {"cs", 0x1F001800, "cs24"}, + {"cs", 0x1F001900, "cs25"}, + {"cs", 0x1F001A00, "cs26"}, + {"cs", 0x1F001B00, "cs27"}, + {"cs", 0x1F001C00, "cs28"}, + {"cs", 0x1F001D00, "cs29"}, + {"cs", 0x1F000200, "cs2"}, + {"cs", 0x1F001E00, "cs30"}, + {"cs", 0x1F001F00, "cs31"}, + {"cs", 0x1F000300, "cs3"}, + {"cs", 0x1F000400, "cs4"}, + {"cs", 0x1F000500, "cs5"}, + {"cs", 0x1F000600, "cs6"}, + {"cs", 0x1F000700, "cs7"}, + {"cs", 0x1F000800, "cs8"}, + {"cs", 0x1F000900, "cs9"}, + {"mall", 0x1F005900, "mall0"}, + {"mall", 0x1F006300, "mall10"}, + {"mall", 0x1F006400, "mall11"}, + {"mall", 0x1F006500, "mall12"}, + {"mall", 0x1F006600, "mall13"}, + {"mall", 0x1F006700, "mall14"}, + {"mall", 0x1F006800, "mall15"}, + {"mall", 0x1F006900, "mall16"}, + {"mall", 0x1F006A00, "mall17"}, + {"mall", 0x1F006B00, "mall18"}, + {"mall", 0x1F006C00, "mall19"}, + {"mall", 0x1F005A00, "mall1"}, + {"mall", 0x1F006D00, "mall20"}, + {"mall", 0x1F006E00, "mall21"}, + {"mall", 0x1F006F00, "mall22"}, + {"mall", 0x1F007000, "mall23"}, + {"mall", 0x1F007100, "mall24"}, + {"mall", 0x1F007200, "mall25"}, + {"mall", 0x1F007300, "mall26"}, + {"mall", 0x1F007400, "mall27"}, + {"mall", 0x1F007500, "mall28"}, + {"mall", 0x1F007600, "mall29"}, + {"mall", 0x1F005B00, "mall2"}, + {"mall", 0x1F007700, "mall30"}, + {"mall", 0x1F007800, "mall31"}, + {"mall", 0x1F005C00, "mall3"}, + {"mall", 0x1F005D00, "mall4"}, + {"mall", 0x1F005E00, "mall5"}, + {"mall", 0x1F005F00, "mall6"}, + {"mall", 0x1F006000, "mall7"}, + {"mall", 0x1F006100, "mall8"}, + {"mall", 0x1F006200, "mall9"}, + {"pb", 0x5EA00, "pb"}, + {"pb", 0x30082900, "ccd0 pbccd"}, + {"pb", 0x32082900, "ccd1 pbccd"}, + {"pb", 0x34082900, "ccd2 pbccd"}, + {"pb", 0x36082900, "xcd0 pbccd"}, + {"pb", 0x38082900, "xcd1 pbccd"}, + {"umc", 0x90F00, "ch0 umc0"}, + {"umc", 0x290F00, "ch0 umc1"}, + {"umc", 0x490F00, "ch0 umc2"}, + {"umc", 0x690F00, "ch0 umc3"}, + {"umc", 0x91F00, "ch1 umc0"}, + {"umc", 0x291F00, "ch1 umc1"}, + {"umc", 0x491F00, "ch1 umc2"}, + {"umc", 0x691F00, "ch1 umc3"}, + {"umc", 0x92F00, "ch2 umc0"}, + {"umc", 0x292F00, "ch2 umc1"}, + {"umc", 0x492F00, "ch2 umc2"}, + {"umc", 0x692F00, "ch2 umc3"}, + {"umc", 0x93F00, "ch3 umc0"}, + {"umc", 0x293F00, "ch3 umc1"}, + {"umc", 0x493F00, "ch3 umc2"}, + {"umc", 0x693F00, "ch3 umc3"}, + {"umc", 0x190F00, "ch4 umc0"}, + {"umc", 0x390F00, "ch4 umc1"}, + {"umc", 0x590F00, "ch4 umc2"}, + {"umc", 0x790F00, "ch4 umc3"}, + {"umc", 0x191F00, "ch5 umc0"}, + {"umc", 0x391F00, "ch5 umc1"}, + {"umc", 0x591F00, "ch5 umc2"}, + {"umc", 0x791F00, "ch5 umc3"}, + {"umc", 0x192F00, "ch6 umc0"}, + {"umc", 0x392F00, "ch6 umc1"}, + {"umc", 0x592F00, "ch6 umc2"}, + {"umc", 0x792F00, "ch6 umc3"}, + {"umc", 0x193F00, "ch7 umc0"}, + {"umc", 0x393F00, "ch7 umc1"}, + {"umc", 0x593F00, "ch7 umc2"}, + {"umc", 0x793F00, "ch7 umc3"}}; + +const size_t NUM_OAM_AID_ENTRIES = sizeof(oam_aid_table) / sizeof(oam_aid_table[0]); const size_t NUM_BANKS = sizeof(bank_table) / sizeof(bank_table[0]); const size_t NUM_ERRORS = sizeof(error_table) / sizeof(error_table[0]); const size_t NUM_XCD_ERRORS = sizeof(xcd_error_table) / sizeof(xcd_error_table[0]); const size_t NUM_AID_ERRORS = sizeof(aid_error_table) / sizeof(aid_error_table[0]); +const size_t NUM_INSTANCES = sizeof(instance_table) / sizeof(instance_table[0]); int find_bank_name(uint16_t hw_id, uint16_t aca_type, const char **bank_name) { @@ -366,3 +500,39 @@ int find_error_in_table(const aca_error_entry_t *table, size_t table_size, *error_type = "UNKNOWN"; return 1; } + +int find_oam_aid(uint8_t instance_id_hi, oam_aid_map_t *oam_aid) +{ + if (!oam_aid || instance_id_hi >= NUM_OAM_AID_ENTRIES) + { + return -1; + } + + oam_aid->oam = oam_aid_table[instance_id_hi].oam; + oam_aid->aid = oam_aid_table[instance_id_hi].aid; + return 0; +} + +int find_instance_name(const char *bank, uint32_t instance_id_lo, const char **instance_name) +{ + if (!bank || !instance_name) + { + return -1; + } + + // Mask off the lower 2 bits as specified + uint32_t masked_id = instance_id_lo & 0xFFFFFFFC; + + for (size_t i = 0; i < NUM_INSTANCES; i++) + { + if (instance_table[i].instance_id_lo == masked_id && + strcmp(bank, instance_table[i].bank) == 0) + { + *instance_name = instance_table[i].name; + return 0; + } + } + + *instance_name = "UNKNOWN"; + return 1; +} diff --git a/src/aca-decode/error_map.c b/src/aca-decode/error_map.c index 3a051465a0..24257fae3c 100644 --- a/src/aca-decode/error_map.c +++ b/src/aca-decode/error_map.c @@ -1,6 +1,8 @@ #include "error_map.h" #include +#define AFID_VERSION "0.7" + static const error_map_entry_t error_map[] = { {1, "Boot-Time Errors", "FW Load", "CPER", "Fail-to-init"}, {2, "Boot-Time Errors", "HBM BIST Test", "CPER", "Fail-to-init"}, @@ -31,7 +33,11 @@ static const error_map_entry_t error_map[] = { {27, "Device Internal Errors", "Watchdog Timeout (WDT)", "CPER", "Fatal"}, {28, "Device Internal Errors", "All Others", "CPER", "Uncorrected, Non-fatal"}, {29, "Device Internal Errors", "All Others", "CPER", "Corrected"}, - {30, "Device Internal Errors", "All Others", "CPER", "Fatal"}}; + {30, "Device Internal Errors", "All Others", "CPER", "Fatal"}, + {31, "CPER Format", "Malformed CPER", "CPER", "ALL"}, + {32, "CPER Format", "Incomplete ACA Data", "CPER", "ALL"}, + {33, "CPER Format", "Invalid ACA Data", "CPER", "ALL"}, + {34, "Unidentified Errors", "Unidentified Error", "CPER", "ALL"}}; static const size_t NUM_ERROR_ENTRIES = sizeof(error_map) / sizeof(error_map[0]); @@ -42,7 +48,7 @@ int get_error_id(const char *error_category, const char *error_type, const char strcmp(error_type, "UNKNOWN") == 0 || strcmp(error_severity, "UNKNOWN") == 0) { - return -1; + return 33; // Return ID for "Invalid Error" if any input is "UNKNOWN" or NULL } for (size_t i = 0; i < NUM_ERROR_ENTRIES; i++) @@ -55,5 +61,5 @@ int get_error_id(const char *error_category, const char *error_type, const char } } - return -1; + return 34; // Return ID for "Unidentified Errors" if no match found }