LCOV - code coverage report
Current view: top level - adump/exception - kernel_pc_fixer.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 93.9 % 297 279
Test Date: 2026-08-31 10:09:28 Functions: 100.0 % 32 32

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : #include <algorithm>
      11              : #include <initializer_list>
      12              : #include <mutex>
      13              : #include "securec.h"
      14              : #include "runtime/base.h"
      15              : #include "kernel_pc_fixer.h"
      16              : #include "acc_error_info.h"
      17              : #include "common/adump_dsmi.h"
      18              : #include "common/adump_platform_manager.h"
      19              : #include "log/adx_log.h"
      20              : 
      21              : namespace Adx {
      22              : namespace {
      23              : constexpr uint32_t UINT32_BIT_NUM = 32U;
      24              : constexpr uint32_t V100_AIC_ERR_NUM = 6U;
      25              : std::mutex g_pcFixerMutex;
      26              : 
      27              : // start/end 为闭区间,当前调用点均使用合法常量范围。
      28         1972 : constexpr uint64_t GenPcMask64(uint64_t start, uint64_t end)
      29              : {
      30         1972 :     return static_cast<uint64_t>(((1ULL << (end - start + 1ULL)) - 1ULL) << start);
      31              : }
      32              : 
      33          220 : constexpr uint32_t GenPcMask32(uint32_t start, uint32_t end)
      34              : {
      35          220 :     return static_cast<uint32_t>(((1ULL << (end - start + 1ULL)) - 1ULL) << start);
      36              : }
      37              : 
      38          986 : PcFixEntry MakePcFixEntry(uint32_t errInfoRegNum, uint64_t srcMask, uint64_t dstMask)
      39              : {
      40          986 :     return {errInfoRegNum, srcMask, dstMask};
      41              : }
      42              : 
      43          580 : void AddPcFixGroup(
      44              :     std::vector<PcFixGroup>& groups, uint32_t moduleId, uint32_t aicErrMask, std::initializer_list<PcFixEntry> entries)
      45              : {
      46          580 :     if (aicErrMask == 0) {
      47          156 :         return;
      48              :     }
      49          424 :     PcFixGroup group;
      50          424 :     group.moduleId = moduleId;
      51          424 :     group.aicErrMask = aicErrMask;
      52          848 :     group.entries.insert(group.entries.end(), entries.begin(), entries.end());
      53          424 :     groups.push_back(group);
      54          424 : }
      55              : 
      56              : } // namespace
      57              : 
      58              : // 类外定义:C++17 前按引用传参会 ODR-use 静态成员,仅类内初始化会链接失败。
      59              : constexpr size_t PcFixerInterface::REG_NAME_MAX_LEN;
      60              : constexpr size_t PcFixerInterface::REG_ITEM_MAX_LEN;
      61              : 
      62           42 : void PcFixerInterface::ReplacePcBits(uint64_t& pc, uint32_t regValue, uint64_t srcMask, uint64_t dstMask)
      63              : {
      64           42 :     if (srcMask == 0 || dstMask == 0 || __builtin_popcountll(srcMask) != __builtin_popcountll(dstMask)) {
      65            0 :         IDE_LOGW("[Dump][Exception] Invalid PC fix mask, srcMask=%lu, dstMask=%lu.", srcMask, dstMask);
      66            0 :         return;
      67              :     }
      68           42 :     int srcShift = __builtin_ctzll(srcMask);
      69           42 :     int dstShift = __builtin_ctzll(dstMask);
      70           42 :     uint64_t extracted = (static_cast<uint64_t>(regValue) & srcMask) >> srcShift;
      71           42 :     pc = (pc & ~dstMask) | ((extracted << dstShift) & dstMask);
      72              : }
      73              : 
      74           44 : uint64_t PcFixerInterface::FixPc(uint64_t pc, const uint32_t errReg[], size_t errRegLen)
      75              : {
      76           44 :     if (errReg == nullptr || errRegLen == 0) {
      77            6 :         IDE_LOGW("[Dump][Exception] Invalid error register info, skip fix PC.");
      78            6 :         return pc;
      79              :     }
      80              : 
      81           38 :     std::vector<const PcFixGroup*> matchedGroups = GetMatchedGroups(errReg, errRegLen);
      82           38 :     if (matchedGroups.empty()) {
      83           10 :         IDE_LOGI("[Dump][Exception] No matched PC fix module, skip fix PC.");
      84           10 :         return pc;
      85              :     }
      86              : 
      87           28 :     std::vector<uint64_t> fixedPcs;
      88           28 :     fixedPcs.reserve(matchedGroups.size());
      89           87 :     for (const auto* matchedGroup : matchedGroups) {
      90           31 :         uint64_t moduleFixedPc = pc;
      91          106 :         for (const auto& entry : matchedGroup->entries) {
      92           44 :             if (entry.errInfoRegNum >= errRegLen) {
      93            2 :                 continue;
      94              :             }
      95           42 :             uint32_t regValue = errReg[entry.errInfoRegNum];
      96           42 :             ReplacePcBits(moduleFixedPc, regValue, entry.srcMask, entry.dstMask);
      97              :         }
      98           31 :         fixedPcs.push_back(moduleFixedPc);
      99           31 :         std::string moduleName = GetModuleName(matchedGroup->moduleId);
     100           31 :         IDE_LOGE(
     101              :             "[Dump][Exception] Fix PC with module=%s, originalPC=0x%lx, fixedPC=0x%lx.", moduleName.c_str(), pc,
     102              :             fixedPcs.back());
     103           31 :     }
     104           28 :     return fixedPcs.front();
     105           38 : }
     106              : 
     107            8 : std::string PcFixerInterface::GetErrorRegisters(const uint32_t errReg[], size_t errRegLen) const
     108              : {
     109            8 :     std::string result;
     110          238 :     for (const std::string& item : GetErrorRegisterItems(errReg, errRegLen)) {
     111          222 :         result += item;
     112          222 :         result += " ";
     113              :     }
     114            8 :     return result;
     115            0 : }
     116              : 
     117           38 : std::vector<const PcFixGroup*> PcFixerInterface::GetMatchedGroups(const uint32_t errReg[], size_t errRegLen) const
     118              : {
     119           38 :     std::vector<const PcFixGroup*> matchedGroups;
     120          688 :     for (uint32_t i = 0; i < errCount_; i++) {
     121          650 :         uint32_t errIdx = errStartIdx_ + i;
     122          650 :         if (errIdx >= errRegLen) {
     123           11 :             continue;
     124              :         }
     125          639 :         uint32_t errVal = errReg[errIdx];
     126          639 :         if (errVal == 0) {
     127          587 :             continue;
     128              :         }
     129           52 :         if (i >= table_.size() || table_[i].empty()) {
     130           18 :             continue;
     131              :         }
     132          120 :         for (const auto& group : table_[i]) {
     133           52 :             if ((errVal & group.aicErrMask) == 0) {
     134           17 :                 continue;
     135              :             }
     136           35 :             bool moduleExists = std::any_of(
     137              :                 matchedGroups.begin(), matchedGroups.end(),
     138            7 :                 [&group](const auto* matchedGroup) { return matchedGroup->moduleId == group.moduleId; });
     139           35 :             if (moduleExists) {
     140            4 :                 continue;
     141              :             }
     142           31 :             matchedGroups.push_back(&group);
     143              :         }
     144              :     }
     145           38 :     return matchedGroups;
     146            0 : }
     147              : 
     148              : // ===== V100(CloudV2)错误位名称表 =====
     149              : 
     150              : namespace {
     151              : const char* const AIC_ERROR_0_BIT_NAMES[UINT32_BIT_NUM] = {
     152              :     "biu_l2_read_oob",
     153              :     "biu_l2_write_oob",
     154              :     "ccu_call_depth_ovrflw",
     155              :     "ccu_div0",
     156              :     "ccu_illegal_instr",
     157              :     "ccu_loop_cnt_err",
     158              :     "ccu_loop_err",
     159              :     "ccu_neg_sqrt",
     160              :     "ccu_ub_ecc",
     161              :     "cube_invld_input",
     162              :     "cube_l0a_ecc",
     163              :     "cube_l0a_rdwr_cflt",
     164              :     "cube_l0a_wrap_around",
     165              :     "cube_l0b_ecc",
     166              :     "cube_l0b_rdwr_cflt",
     167              :     "cube_l0b_wrap_around",
     168              :     "cube_l0c_ecc",
     169              :     "cube_l0c_rdwr_cflt",
     170              :     "cube_l0c_self_rdwr_cflt",
     171              :     "cube_l0c_wrap_around",
     172              :     "ifu_bus_err",
     173              :     "mte_aipp_illegal_param",
     174              :     "mte_bas_raddr_obound",
     175              :     "mte_biu_rdwr_resp",
     176              :     "mte_cidx_overflow",
     177              :     "mte_decomp",
     178              :     "mte_f1wpos_larger_fsize",
     179              :     "mte_fmap_less_kernel",
     180              :     "mte_fmapwh_larger_l1size",
     181              :     "mte_fpos_larger_fsize",
     182              :     "mte_gdma_illegal_burst_len",
     183              :     "mte_gdma_illegal_burst_num",
     184              : };
     185              : 
     186              : const char* const AIC_ERROR_1_BIT_NAMES[UINT32_BIT_NUM] = {
     187              :     "mte_gdma_read_overflow",
     188              :     "mte_gdma_write_overflow",
     189              :     "mte_comp",
     190              :     "mte_illegal_fm_size",
     191              :     "mte_illegal_l1_3d_size",
     192              :     "mte_illegal_stride",
     193              :     "mte_l0a_rdwr_cflt",
     194              :     "mte_l0b_rdwr_cflt",
     195              :     "mte_l1_ecc",
     196              :     "mte_padding_cfg",
     197              :     "mte_read_overflow",
     198              :     "mte_rob_ecc",
     199              :     "mte_tlu_ecc",
     200              :     "mte_ub_ecc",
     201              :     "mte_unzip",
     202              :     "mte_write_3d_overflow",
     203              :     "mte_write_overflow",
     204              :     "vec_data_excp_ccu",
     205              :     "vec_data_excp_mte",
     206              :     "vec_data_excp_vec",
     207              :     "vec_div0",
     208              :     "vec_illegal_mask",
     209              :     "vec_inf_nan",
     210              :     "vec_l0c_ecc",
     211              :     "vec_l0c_rdwr_cflt",
     212              :     "vec_neg_ln",
     213              :     "vec_neg_sqrt",
     214              :     "vec_same_blk_addr",
     215              :     "vec_ub_ecc",
     216              :     "vec_ub_self_rdwr_cflt",
     217              :     "vec_ub_wrap_around",
     218              :     "biu_dfx_err",
     219              : };
     220              : 
     221              : const char* const AIC_ERROR_2_BIT_NAMES[UINT32_BIT_NUM] = {
     222              :     "ccu_sbuf_ecc",
     223              :     "vec_col2img_rd_fm_addr_ovflow",
     224              :     "vec_col2img_rd_dfm_addr_ovfflow",
     225              :     "vec_col2img_illegal_fm_size",
     226              :     "vec_col2img_illegal_stride",
     227              :     "vec_col2img_illegal_1st_win_pos",
     228              :     "vec_col2img_illegal_fetch_pos",
     229              :     "vec_col2img_illegal_k_size",
     230              :     "ccu_inf_nan",
     231              :     "mte_illegal_schn_cfg",
     232              :     "mte_atm_addr_misalg",
     233              :     "vec_instr_addr_misalign",
     234              :     "vec_instr_illegal_cfg",
     235              :     "vec_instr_undef",
     236              :     "ccu_addr_err",
     237              :     "reserved_ccu_bus_err",
     238              :     "mte_err_addr_misalign",
     239              :     "mte_err_dw_pad_conf_err",
     240              :     "mte_err_dw_fmap_h_illegal",
     241              :     "mte_err_wino_l0b_write_overflow",
     242              :     "mte_err_wino_l0b_read_overflow",
     243              :     "mte_err_illegal_v_cov_pad_ctl",
     244              :     "mte_err_illegal_h_cov_pad_ctl",
     245              :     "mte_err_illegal_w_size",
     246              :     "mte_err_illegal_h_size",
     247              :     "mte_err_illegal_chn_size",
     248              :     "mte_err_illegal_k_m_ext_step",
     249              :     "mte_err_illegal_k_m_start_pos",
     250              :     "mte_err_illegal_smallk_cfg",
     251              :     "mte_err_read_3d_overflow",
     252              :     "ccu_veciq_ecc",
     253              :     "ccu_dc_data_ecc",
     254              : };
     255              : 
     256              : const char* const AIC_ERROR_3_BIT_NAMES[UINT32_BIT_NUM] = {
     257              :     "ccu_dc_tag_ecc",
     258              :     "ccu_div0_fp",
     259              :     "ccu_neg_sqrt_fp",
     260              :     "cnt_sw_bus_err",
     261              :     "fixp_err_instr_addr_misal",
     262              :     "fixp_err_illegal_cfg",
     263              :     "fixp_err_read_l0c_ovflw",
     264              :     "fixp_err_read_l1_ovflw",
     265              :     "fixp_err_read_ub_ovflw",
     266              :     "fixp_err_write_l1_ovflw",
     267              :     "fixp_err_write_ub_ovflw",
     268              :     "fixp_err_fbuf_write_ovflw",
     269              :     "fixp_err_fbuf_read_ovflw",
     270              :     "sc_reg_parity_err",
     271              :     "mte_err_fifo_parity",
     272              :     "mte_err_waitset",
     273              :     "ccu_err_parity_err",
     274              :     "mte_err_cache_ecc",
     275              :     "cube_err_hset_cnt_unf",
     276              :     "cube_err_hset_cnt_ovf",
     277              :     "mte_err_instr_illegal_cfg",
     278              :     "mte_err_hebcd",
     279              :     "mte_err_hebce",
     280              :     "mte_err_waipp",
     281              :     "ccu_seq_err",
     282              :     "ccu_mpu_err",
     283              :     "ccu_lsu_err",
     284              :     "ccu_pb_ecc_err",
     285              :     "mte_ub_wr_ovflw",
     286              :     "mte_ub_rd_ovflw",
     287              :     "cube_illegal_instr",
     288              :     "ccu_safety_crc_err",
     289              : };
     290              : 
     291              : const char* const AIC_ERROR_4_BIT_NAMES[UINT32_BIT_NUM] = {
     292              :     "mte_timeout",
     293              :     "mte_ub_rd_cflt",
     294              :     "mte_ub_wr_cflt",
     295              :     "mte_ktable_wr_addr_overflow",
     296              :     "mte_ktable_rd_addr_overflow",
     297              :     "ccu_ub_rd_cflt",
     298              :     "ccu_ub_wr_cflt",
     299              :     "ccu_ub_overflow_err",
     300              :     "biu_unsplit_err",
     301              :     "mte_stb_ecc_err",
     302              :     "mte_aipp_ecc_err",
     303              :     "ccu_lsu_atomic_err",
     304              :     "ccu_cross_core_set_ovfl_err",
     305              :     "fixp_err_out_write_overflow",
     306              :     "cube_err_pbuf_wrap_around",
     307              :     "fixp_l0c_ecc",
     308              :     "mte_err_l0c_rdwr_cflt",
     309              :     "reserved",
     310              :     "reserved",
     311              :     "reserved",
     312              :     "reserved",
     313              :     "reserved",
     314              :     "reserved",
     315              :     "reserved",
     316              :     "reserved",
     317              :     "reserved",
     318              :     "reserved",
     319              :     "reserved",
     320              :     "reserved",
     321              :     "reserved",
     322              :     "reserved",
     323              :     "reserved",
     324              : };
     325              : 
     326              : const char* const AIC_ERROR_5_BIT_NAMES[UINT32_BIT_NUM] = {
     327              :     "vec_data_excpt_mte",    "vec_data_excpt_su",       "vec_data_excpt_vec",      "vec_instr_timeout",
     328              :     "vec_instrs_undef",      "vec_instr_ill_cfg",       "vec_instr_misalign",      "vec_instr_ill_mask",
     329              :     "vec_instr_ill_sqzn",    "vec_ub_addr_wrap_around", "vec_ub_ecc_mberr",        "vec_idata_inf_nan",
     330              :     "vec_div_by_zero",       "vec_valu_neg_ln",         "vec_valu_neg_sqrt",       "vec_vci_idata_out_range",
     331              :     "vec_ill_vloop_op",      "vec_ill_vloop_sreg",      "vec_ld_num_mismatch",     "vec_st_num_mismatch",
     332              :     "vec_ex_num_mismatch",   "vec_ld_num_exceed_limit", "vec_st_num_exceed_limit", "vec_ill_instr_padding",
     333              :     "vec_ill_vga_vpd_order", "vec_ic_ecc_err",          "vec_biu_resp_err",        "vec_pb_ecc_mberr",
     334              :     "vec_pb_read_no_resp",   "vec_valu_ill_issue",      "vec_err_parity_err",      "reserved",
     335              : };
     336              : 
     337              : const char* const* const AIC_ERROR_BIT_NAMES[V100_AIC_ERR_NUM] = {
     338              :     AIC_ERROR_0_BIT_NAMES, AIC_ERROR_1_BIT_NAMES, AIC_ERROR_2_BIT_NAMES,
     339              :     AIC_ERROR_3_BIT_NAMES, AIC_ERROR_4_BIT_NAMES, AIC_ERROR_5_BIT_NAMES,
     340              : };
     341              : 
     342              : enum V100ModuleIdx {
     343              :     V100_CUBE_INFO_IDX,
     344              :     V100_CCU_INFO_IDX,
     345              :     V100_IFU_INFO_IDX,
     346              :     V100_MTE_INFO_IDX,
     347              :     V100_VEC_INFO_IDX,
     348              :     V100_FIXP_INFO_IDX,
     349              :     V100_MODULE_ID_NUM
     350              : };
     351              : 
     352              : enum V200ErrorIdx {
     353              :     V200_SC_ERROR_T0_IDX,
     354              :     V200_SU_ERROR_T0_IDX,
     355              :     V200_MTE_ERROR_T0_IDX,
     356              :     V200_MTE_ERROR_T1_IDX,
     357              :     V200_VEC_ERROR_T0_IDX,
     358              :     V200_VEC_ERROR_T2_IDX,
     359              :     V200_CUBE_ERROR_T0_IDX,
     360              :     V200_CUBE_ERROR_T1_IDX,
     361              :     V200_L1_ERROR_T0_IDX,
     362              :     V200_L1_ERROR_T1_IDX,
     363              :     V200_ERROR_IDX_NUM
     364              : };
     365              : 
     366              : // 编译期求寄存器名的最大长度,用于在数组定义处校验 REG_NAME_MAX_LEN。
     367              : // 递归而非循环:C++11 的 constexpr 函数体只允许单条 return 语句。
     368              : constexpr size_t ConstMax(size_t lhs, size_t rhs) { return (lhs > rhs) ? lhs : rhs; }
     369              : 
     370              : constexpr size_t ConstStrLen(const char* str) { return (*str == '\0') ? 0U : (1U + ConstStrLen(str + 1)); }
     371              : 
     372              : constexpr size_t MaxRegNameLen(const char* const regNames[], size_t regNameNum)
     373              : {
     374              :     return (regNameNum == 0U) ?
     375              :                0U :
     376              :                ConstMax(ConstStrLen(regNames[regNameNum - 1U]), MaxRegNameLen(regNames, regNameNum - 1U));
     377              : }
     378              : 
     379              : // V100 errReg 下标对应的 RTS 寄存器枚举名称,与 rtErrRegInfoIdxV100_t 顺序一致。
     380              : constexpr const char* const V100_REG_NAMES[] = {
     381              :     "AIC_ERR_0", "AIC_ERR_1", "AIC_ERR_2",  "AIC_ERR_3",  "AIC_ERR_4",  "AIC_ERR_5",  "BIU_ERR_0", "BIU_ERR_1",
     382              :     "CCU_ERR_0", "CCU_ERR_1", "CUBE_ERR_0", "CUBE_ERR_1", "IFU_ERR_0",  "IFU_ERR_1",  "MTE_ERR_0", "MTE_ERR_1",
     383              :     "VEC_ERR_0", "VEC_ERR_1", "FIXP_ERR_0", "FIXP_ERR_1", "AIC_COND_0", "AIC_COND_1",
     384              : };
     385              : // 校验放在数组定义处,不依赖任何一个使用点的实现是否存在。
     386              : static_assert(
     387              :     MaxRegNameLen(V100_REG_NAMES, sizeof(V100_REG_NAMES) / sizeof(V100_REG_NAMES[0])) <=
     388              :         PcFixerInterface::REG_NAME_MAX_LEN,
     389              :     "V100_REG_NAMES exceeds REG_NAME_MAX_LEN, update the constant.");
     390              : 
     391              : // V200 errReg 下标对应的 RTS 寄存器枚举名称,与 rtErrRegInfoIdxV200_t 顺序一致。
     392              : constexpr const char* const V200_REG_NAMES[] = {
     393              :     "SU_ERR_INFO_T0_0",  "SU_ERR_INFO_T0_1",   "SU_ERR_INFO_T0_2",   "SU_ERR_INFO_T0_3",   "MTE_ERR_INFO_T0_0",
     394              :     "MTE_ERR_INFO_T0_1", "MTE_ERR_INFO_T0_2",  "MTE_ERR_INFO_T1_0",  "MTE_ERR_INFO_T1_1",  "MTE_ERR_INFO_T1_2",
     395              :     "VEC_ERR_INFO_T0_0", "VEC_ERR_INFO_T0_1",  "VEC_ERR_INFO_T0_2",  "VEC_ERR_INFO_T0_3",  "VEC_ERR_INFO_T0_4",
     396              :     "VEC_ERR_INFO_T0_5", "CUBE_ERR_INFO_T0_0", "CUBE_ERR_INFO_T0_1", "L1_ERR_INFO_T0_0",   "L1_ERR_INFO_T0_1",
     397              :     "SC_ERROR_T0_0",     "SU_ERROR_T0_0",      "MTE_ERROR_T0_0",     "MTE_ERROR_T1_0",     "VEC_ERROR_T0_0",
     398              :     "VEC_ERROR_T0_2",    "CUBE_ERROR_T0_0",    "CUBE_ERROR_T0_1",    "L1_ERROR_T0_0",      "L1_ERROR_T0_1",
     399              :     "SC_ERR_INFO_T0_0",  "SC_ERR_INFO_T0_1",   "SU_SPR_CONDITION_0", "SU_SPR_CONDITION_1", "SU_ERR_INFO_T0_4",
     400              :     "SU_ERR_INFO_T0_5",  "SU_ERR_INFO_T0_6",   "SU_ERR_INFO_T0_7",   "VEC_ERR_INFO_T0_6",  "SU_ERROR_T0_1",
     401              : };
     402              : static_assert(
     403              :     MaxRegNameLen(V200_REG_NAMES, sizeof(V200_REG_NAMES) / sizeof(V200_REG_NAMES[0])) <=
     404              :         PcFixerInterface::REG_NAME_MAX_LEN,
     405              :     "V200_REG_NAMES exceeds REG_NAME_MAX_LEN, update the constant.");
     406              : 
     407         2304 : std::string GetV100BitName(uint32_t aicErrorIdx, uint32_t bit)
     408              : {
     409         2304 :     if (aicErrorIdx >= V100_AIC_ERR_NUM || bit >= UINT32_BIT_NUM) {
     410            0 :         return "";
     411              :     }
     412         4608 :     return std::string(AIC_ERROR_BIT_NAMES[aicErrorIdx][bit]);
     413              : }
     414              : 
     415         2304 : bool IsCubeErrorBitName(const std::string& bitName)
     416              : {
     417         2304 :     return bitName.find("cube_") == 0 || bitName.find("cube_err_") == 0 || bitName.find("cube_invld_") == 0;
     418              : }
     419              : 
     420         2124 : bool IsCcuErrorBitName(const std::string& bitName)
     421              : {
     422         5748 :     return bitName.find("ccu_") == 0 || bitName.find("ccu_err_") == 0 || bitName.find("ccu_inf_") == 0 ||
     423         5436 :            bitName.find("ccu_addr_") == 0 || bitName.find("ccu_div0_fp") == 0 || bitName.find("ccu_neg_sqrt_fp") == 0 ||
     424         5436 :            bitName.find("ccu_dc_") == 0 || bitName.find("ccu_sbuf_") == 0 || bitName.find("ccu_veciq_") == 0 ||
     425         5436 :            bitName.find("ccu_pb_ecc_err") == 0 || bitName.find("ccu_seq_") == 0 || bitName.find("ccu_mpu_") == 0 ||
     426         5748 :            bitName.find("ccu_lsu_") == 0 || bitName.find("ccu_safety_") == 0;
     427              : }
     428              : 
     429         1080 : bool IsVecErrorBitName(const std::string& bitName)
     430              : {
     431         1920 :     return bitName.find("vec_") == 0 || bitName.find("vec_data_excp_") == 0 || bitName.find("vec_col2img_") == 0 ||
     432         1920 :            bitName.find("vec_instr_") == 0 || bitName.find("vec_err_parity_") == 0;
     433              : }
     434              : 
     435           72 : void BuildV100ModuleMasks(uint32_t aicErrorIdx, uint32_t moduleMasks[])
     436              : {
     437         2376 :     for (uint32_t bit = 0; bit < UINT32_BIT_NUM; bit++) {
     438         2304 :         std::string bitName = GetV100BitName(aicErrorIdx, bit);
     439         2304 :         if (IsCubeErrorBitName(bitName)) {
     440          180 :             moduleMasks[V100_CUBE_INFO_IDX] |= (1U << bit);
     441         2124 :         } else if (IsCcuErrorBitName(bitName)) {
     442          312 :             moduleMasks[V100_CCU_INFO_IDX] |= (1U << bit);
     443         1812 :         } else if (bitName.find("mte_") == 0 || bitName.find("mte_err_") == 0) {
     444          732 :             moduleMasks[V100_MTE_INFO_IDX] |= (1U << bit);
     445         1080 :         } else if (IsVecErrorBitName(bitName)) {
     446          660 :             moduleMasks[V100_VEC_INFO_IDX] |= (1U << bit);
     447          420 :         } else if (bitName.find("fixp_") == 0 || bitName.find("fixp_err_") == 0) {
     448          132 :             moduleMasks[V100_FIXP_INFO_IDX] |= (1U << bit);
     449              :         }
     450         2304 :     }
     451           72 : }
     452              : 
     453           72 : void AppendV100PcFixGroups(const uint32_t moduleMasks[], std::vector<PcFixGroup>& groups)
     454              : {
     455           72 :     AddPcFixGroup(
     456              :         groups, V100_CUBE_INFO_IDX, moduleMasks[V100_CUBE_INFO_IDX],
     457           72 :         {MakePcFixEntry(RT_V100_CUBE_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     458           72 :          MakePcFixEntry(RT_V100_CUBE_ERR_0, GenPcMask64(24, 31), GenPcMask64(10, 17))});
     459            0 :     AddPcFixGroup(
     460           72 :         groups, V100_CCU_INFO_IDX, moduleMasks[V100_CCU_INFO_IDX],
     461           72 :         {MakePcFixEntry(RT_V100_CCU_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     462           72 :          MakePcFixEntry(RT_V100_CCU_ERR_0, GenPcMask64(23, 30), GenPcMask64(10, 17))});
     463            0 :     AddPcFixGroup(
     464           72 :         groups, V100_MTE_INFO_IDX, moduleMasks[V100_MTE_INFO_IDX],
     465           72 :         {MakePcFixEntry(RT_V100_MTE_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     466           72 :          MakePcFixEntry(RT_V100_MTE_ERR_1, GenPcMask64(0, 7), GenPcMask64(10, 17))});
     467            0 :     AddPcFixGroup(
     468           72 :         groups, V100_VEC_INFO_IDX, moduleMasks[V100_VEC_INFO_IDX],
     469           72 :         {MakePcFixEntry(RT_V100_VEC_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     470           72 :          MakePcFixEntry(RT_V100_VEC_ERR_1, GenPcMask64(0, 7), GenPcMask64(10, 17))});
     471          144 :     AddPcFixGroup(
     472           72 :         groups, V100_FIXP_INFO_IDX, moduleMasks[V100_FIXP_INFO_IDX],
     473           72 :         {MakePcFixEntry(RT_V100_FIXP_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     474           72 :          MakePcFixEntry(RT_V100_FIXP_ERR_1, GenPcMask64(0, 7), GenPcMask64(10, 17))});
     475           72 : }
     476              : 
     477           10 : void InitV200CommonPcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     478              : {
     479           20 :     AddPcFixGroup(
     480           10 :         table[V200_SU_ERROR_T0_IDX], V200_SU_ERROR_T0_IDX, GenPcMask32(0, 31),
     481           10 :         {MakePcFixEntry(RT_V200_SU_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     482           20 :     AddPcFixGroup(
     483           10 :         table[V200_MTE_ERROR_T0_IDX], V200_MTE_ERROR_T0_IDX, GenPcMask32(0, 31),
     484           10 :         {MakePcFixEntry(RT_V200_MTE_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     485              :     // MTE_ERR_INFO_T1_0值废弃,使用MTE_ERR_INFO_T0_0
     486           20 :     AddPcFixGroup(
     487           10 :         table[V200_MTE_ERROR_T1_IDX], V200_MTE_ERROR_T0_IDX, GenPcMask32(0, 31),
     488           10 :         {MakePcFixEntry(RT_V200_MTE_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     489           10 : }
     490              : 
     491           10 : void InitV200VecPcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     492              : {
     493           20 :     AddPcFixGroup(
     494           10 :         table[V200_VEC_ERROR_T0_IDX], V200_VEC_ERROR_T0_IDX, GenPcMask32(0, 25),
     495           10 :         {MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_1, GenPcMask64(0, 31), GenPcMask64(0, 31)),
     496           10 :          MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_2, GenPcMask64(0, 16), GenPcMask64(32, 48))});
     497           20 :     AddPcFixGroup(
     498           10 :         table[V200_VEC_ERROR_T2_IDX], V200_VEC_ERROR_T0_IDX, GenPcMask32(0, 1),
     499           10 :         {MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_1, GenPcMask64(0, 31), GenPcMask64(0, 31)),
     500           10 :          MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_2, GenPcMask64(0, 16), GenPcMask64(32, 48))});
     501           10 : }
     502              : 
     503           10 : void InitV200CubeAndL1PcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     504              : {
     505           20 :     AddPcFixGroup(
     506           10 :         table[V200_CUBE_ERROR_T0_IDX], V200_CUBE_ERROR_T0_IDX, GenPcMask32(0, 15),
     507           10 :         {MakePcFixEntry(RT_V200_CUBE_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     508           20 :     AddPcFixGroup(
     509           10 :         table[V200_CUBE_ERROR_T1_IDX], V200_CUBE_ERROR_T0_IDX, GenPcMask32(0, 9),
     510           10 :         {MakePcFixEntry(RT_V200_CUBE_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     511           20 :     AddPcFixGroup(
     512           10 :         table[V200_L1_ERROR_T0_IDX], V200_L1_ERROR_T0_IDX, GenPcMask32(0, 30),
     513           10 :         {MakePcFixEntry(RT_V200_L1_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     514           20 :     AddPcFixGroup(
     515           10 :         table[V200_L1_ERROR_T1_IDX], V200_L1_ERROR_T0_IDX, GenPcMask32(0, 21),
     516           10 :         {MakePcFixEntry(RT_V200_L1_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     517           10 : }
     518              : 
     519           17 : std::vector<std::string> BuildErrorRegisterItems(
     520              :     const char* const regNames[], size_t regNameNum, const uint32_t errReg[], size_t errRegLen)
     521              : {
     522           17 :     constexpr size_t REG_ITEM_BUF_LEN = 128U;
     523           17 :     std::vector<std::string> items;
     524          553 :     for (size_t i = 0; i < regNameNum && i < errRegLen; i++) {
     525          536 :         char item[REG_ITEM_BUF_LEN] = {0};
     526          536 :         int len = snprintf_s(item, sizeof(item), sizeof(item) - 1, "%s=0x%x", regNames[i], errReg[i]);
     527          536 :         if (len < 0) {
     528            0 :             continue;
     529              :         }
     530          536 :         items.emplace_back(item);
     531              :     }
     532           17 :     return items;
     533            0 : }
     534              : } // namespace
     535              : 
     536              : // ===== CloudV2 PC 修正 =====
     537              : 
     538           12 : CloudV2PcFixer::CloudV2PcFixer()
     539              : {
     540           12 :     errStartIdx_ = static_cast<uint32_t>(RT_V100_AIC_ERR_0);
     541           12 :     errCount_ = V100_AIC_ERR_NUM;
     542           12 :     table_.resize(V100_AIC_ERR_NUM);
     543              : 
     544           84 :     for (uint32_t i = 0; i < V100_AIC_ERR_NUM; i++) {
     545           72 :         uint32_t moduleMasks[V100_MODULE_ID_NUM] = {0};
     546           72 :         BuildV100ModuleMasks(i, moduleMasks);
     547           72 :         AppendV100PcFixGroups(moduleMasks, table_[i]);
     548              :     }
     549           12 : }
     550              : 
     551           10 : std::vector<std::string> CloudV2PcFixer::GetErrorRegisterItems(const uint32_t errReg[], size_t errRegLen) const
     552              : {
     553           10 :     if (errReg == nullptr || errRegLen == 0) {
     554            2 :         return {};
     555              :     }
     556            8 :     constexpr size_t regNameNum = sizeof(V100_REG_NAMES) / sizeof(V100_REG_NAMES[0]);
     557            8 :     return BuildErrorRegisterItems(V100_REG_NAMES, regNameNum, errReg, errRegLen);
     558              : }
     559              : 
     560           10 : std::string CloudV2PcFixer::GetModuleName(uint32_t moduleId) const
     561              : {
     562           10 :     const char* const moduleNames[V100_MODULE_ID_NUM] = {"CUBE", "CCU", "IFU", "MTE", "VEC", "FIXP"};
     563           10 :     if (moduleId >= V100_MODULE_ID_NUM) {
     564            0 :         return "UNKNOWN";
     565              :     }
     566           20 :     return moduleNames[moduleId];
     567              : }
     568              : 
     569              : // ===== CloudV4 PC 修正 =====
     570              : 
     571           10 : CloudV4PcFixer::CloudV4PcFixer()
     572              : {
     573           10 :     errStartIdx_ = static_cast<uint32_t>(RT_V200_SC_ERROR_T0_0);
     574           10 :     errCount_ = V200_ERROR_IDX_NUM;
     575           10 :     table_.resize(errCount_);
     576              : 
     577              :     // SC_ERROR_T0_0 没有 PC 映射规则。
     578           10 :     table_[V200_SC_ERROR_T0_IDX] = {};
     579           10 :     InitV200CommonPcFixGroups(table_);
     580           10 :     InitV200VecPcFixGroups(table_);
     581           10 :     InitV200CubeAndL1PcFixGroups(table_);
     582           10 : }
     583              : 
     584            1 : std::vector<std::string> CloudV4PcFixer::GetErrorRegisterItems(const uint32_t errReg[], size_t errRegLen) const
     585              : {
     586            1 :     if (errReg == nullptr || errRegLen == 0) {
     587            0 :         return {};
     588              :     }
     589            1 :     constexpr size_t regNameNum = sizeof(V200_REG_NAMES) / sizeof(V200_REG_NAMES[0]);
     590            1 :     return BuildErrorRegisterItems(V200_REG_NAMES, regNameNum, errReg, errRegLen);
     591              : }
     592              : 
     593           11 : std::string CloudV4PcFixer::GetModuleName(uint32_t moduleId) const
     594              : {
     595           11 :     switch (moduleId) {
     596            4 :         case V200_SU_ERROR_T0_IDX:
     597            8 :             return "SU";
     598            3 :         case V200_MTE_ERROR_T0_IDX:
     599            6 :             return "MTE";
     600            2 :         case V200_VEC_ERROR_T0_IDX:
     601            4 :             return "VEC";
     602            1 :         case V200_CUBE_ERROR_T0_IDX:
     603            2 :             return "CUBE";
     604            1 :         case V200_L1_ERROR_T0_IDX:
     605            2 :             return "L1";
     606            0 :         default:
     607            0 :             return "UNKNOWN";
     608              :     }
     609              : }
     610              : 
     611              : // === CloudV5 PC Fixer ====
     612              : namespace {
     613              : // V5 errReg 采用 V200 布局,各寄存器下标沿用 rtErrRegInfoIdxV200_t 的绝对值。
     614              : // 其中 SU_ERROR_T0_1 复用 RT_V200_SU_ERROR_T0_1,在 V200 布局下位于离群下标处。
     615              : enum V300ErrorIdx {
     616              :     V300_SC_ERROR_T0_0_IDX = RT_V200_SC_ERROR_T0_0,
     617              :     V300_SU_ERROR_T0_0_IDX = RT_V200_SU_ERROR_T0_0,
     618              :     V300_SU_ERROR_T0_1_IDX = RT_V200_SU_ERROR_T0_1,
     619              :     V300_MTE_ERROR_T0_0_IDX = RT_V200_MTE_ERROR_T0_0,
     620              :     V300_MTE_ERROR_T1_0_IDX = RT_V200_MTE_ERROR_T1_0,
     621              :     V300_VEC_ERROR_T0_0_IDX = RT_V200_VEC_ERROR_T0_0,
     622              :     V300_VEC_ERROR_T0_2_IDX = RT_V200_VEC_ERROR_T0_2,
     623              :     V300_CUBE_ERROR_T0_0_IDX = RT_V200_CUBE_ERROR_T0_0,
     624              :     V300_CUBE_ERROR_T0_1_IDX = RT_V200_CUBE_ERROR_T0_1,
     625              :     V300_L1_ERROR_T0_0_IDX = RT_V200_L1_ERROR_T0_0,
     626              :     V300_L1_ERROR_T0_1_IDX = RT_V200_L1_ERROR_T0_1,
     627              :     V300_ERROR_IDX_NUM = RT_V200_SU_ERROR_T0_1 + 1
     628              : };
     629              : 
     630           13 : void InitV300CommonPcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     631              : {
     632           26 :     AddPcFixGroup(
     633           13 :         table[V300_SU_ERROR_T0_0_IDX], V300_SU_ERROR_T0_0_IDX, GenPcMask32(0, 31),
     634           13 :         {MakePcFixEntry(RT_V200_SU_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     635           26 :     AddPcFixGroup(
     636           13 :         table[V300_SU_ERROR_T0_1_IDX], V300_SU_ERROR_T0_0_IDX, GenPcMask32(0, 3),
     637           13 :         {MakePcFixEntry(RT_V200_SU_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     638           26 :     AddPcFixGroup(
     639           13 :         table[V300_MTE_ERROR_T0_0_IDX], V300_MTE_ERROR_T0_0_IDX, GenPcMask32(0, 31),
     640           13 :         {MakePcFixEntry(RT_V200_MTE_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     641              :     // MTE_ERR_INFO_T1_0值废弃,使用MTE_ERR_INFO_T0_0
     642           26 :     AddPcFixGroup(
     643           13 :         table[V300_MTE_ERROR_T1_0_IDX], V300_MTE_ERROR_T0_0_IDX, GenPcMask32(0, 31),
     644           13 :         {MakePcFixEntry(RT_V200_MTE_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     645           13 : }
     646              : 
     647           13 : void InitV300VecPcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     648              : {
     649           26 :     AddPcFixGroup(
     650           13 :         table[V300_VEC_ERROR_T0_0_IDX], V300_VEC_ERROR_T0_0_IDX, GenPcMask32(0, 29),
     651           13 :         {MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_1, GenPcMask64(0, 31), GenPcMask64(0, 31)),
     652           13 :          MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_2, GenPcMask64(0, 16), GenPcMask64(32, 48))});
     653           26 :     AddPcFixGroup(
     654           13 :         table[V300_VEC_ERROR_T0_2_IDX], V300_VEC_ERROR_T0_0_IDX, GenPcMask32(0, 12),
     655           13 :         {MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_1, GenPcMask64(0, 31), GenPcMask64(0, 31)),
     656           13 :          MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_2, GenPcMask64(0, 16), GenPcMask64(32, 48))});
     657           13 : }
     658              : 
     659           13 : void InitV300CubeAndL1PcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     660              : {
     661           26 :     AddPcFixGroup(
     662           13 :         table[V300_CUBE_ERROR_T0_0_IDX], V300_CUBE_ERROR_T0_0_IDX, GenPcMask32(0, 18),
     663           13 :         {MakePcFixEntry(RT_V200_CUBE_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     664           26 :     AddPcFixGroup(
     665           13 :         table[V300_CUBE_ERROR_T0_1_IDX], V300_CUBE_ERROR_T0_0_IDX, GenPcMask32(0, 9),
     666           13 :         {MakePcFixEntry(RT_V200_CUBE_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     667           26 :     AddPcFixGroup(
     668           13 :         table[V300_L1_ERROR_T0_0_IDX], V300_L1_ERROR_T0_0_IDX, GenPcMask32(0, 30),
     669           13 :         {MakePcFixEntry(RT_V200_L1_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     670           26 :     AddPcFixGroup(
     671           13 :         table[V300_L1_ERROR_T0_1_IDX], V300_L1_ERROR_T0_0_IDX, GenPcMask32(0, 22),
     672           13 :         {MakePcFixEntry(RT_V200_L1_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     673           13 : }
     674              : } // namespace
     675              : 
     676           13 : CloudV5PcFixer::CloudV5PcFixer()
     677              : {
     678              :     // V5 errReg 为 V200 布局,table_ 按 errReg 绝对下标寻址,故 errStartIdx_ 从 0 起,
     679              :     // errCount_ 覆盖到最大用到的下标;未使用的位置留空并在扫描时跳过。
     680              :     // 最大下标为 RT_V200_SU_ERROR_T0_1(值 39),故 errCount_ = 40;SU_ERROR_T0_1
     681              :     // 与常规错误下标(0~29)之间的 30~38 为 ERR_INFO 类寄存器,非空洞,table_ 空条目占比很低,
     682              :     // 连续 vector 寻址 O(1)、无需哈希映射。
     683           13 :     errStartIdx_ = 0;
     684           13 :     errCount_ = V300_ERROR_IDX_NUM;
     685           13 :     table_.resize(errCount_);
     686              : 
     687              :     // SC_ERROR_T0_0 没有 PC 映射规则。
     688           13 :     table_[V300_SC_ERROR_T0_0_IDX] = {};
     689           13 :     InitV300CommonPcFixGroups(table_);
     690           13 :     InitV300VecPcFixGroups(table_);
     691           13 :     InitV300CubeAndL1PcFixGroups(table_);
     692           13 : }
     693              : 
     694           12 : std::vector<std::string> CloudV5PcFixer::GetErrorRegisterItems(const uint32_t errReg[], size_t errRegLen) const
     695              : {
     696           12 :     if (errReg == nullptr || errRegLen == 0) {
     697            4 :         return {};
     698              :     }
     699              :     // V5 errReg 为 V200 布局,寄存器名沿用 V200_REG_NAMES。
     700            8 :     constexpr size_t regNameNum = sizeof(V200_REG_NAMES) / sizeof(V200_REG_NAMES[0]);
     701            8 :     return BuildErrorRegisterItems(V200_REG_NAMES, regNameNum, errReg, errRegLen);
     702              : }
     703              : 
     704           10 : std::string CloudV5PcFixer::GetModuleName(uint32_t moduleId) const
     705              : {
     706           10 :     switch (moduleId) {
     707            5 :         case V300_SU_ERROR_T0_0_IDX:
     708              :         case V300_SU_ERROR_T0_1_IDX:
     709           10 :             return "SU";
     710            2 :         case V300_MTE_ERROR_T0_0_IDX:
     711              :         case V300_MTE_ERROR_T1_0_IDX:
     712            4 :             return "MTE";
     713            1 :         case V300_VEC_ERROR_T0_0_IDX:
     714              :         case V300_VEC_ERROR_T0_2_IDX:
     715            2 :             return "VEC";
     716            1 :         case V300_CUBE_ERROR_T0_0_IDX:
     717              :         case V300_CUBE_ERROR_T0_1_IDX:
     718            2 :             return "CUBE";
     719            1 :         case V300_L1_ERROR_T0_0_IDX:
     720              :         case V300_L1_ERROR_T0_1_IDX:
     721            2 :             return "L1";
     722            0 :         default:
     723            0 :             return "UNKNOWN";
     724              :     }
     725              : }
     726              : 
     727              : std::unique_ptr<PcFixerInterface> PcFixerFactory::instance_;
     728              : 
     729           28 : PcFixerInterface* PcFixerFactory::GetInstance()
     730              : {
     731           28 :     std::lock_guard<std::mutex> lock(g_pcFixerMutex);
     732           28 :     if (!instance_) {
     733           15 :         auto* plat = CoredumpManager::Get();
     734           15 :         if (plat == nullptr) {
     735            5 :             IDE_LOGW("[Dump][Exception] Platform unavailable, PC fix skipped.");
     736            5 :             return nullptr;
     737              :         }
     738           10 :         instance_ = plat->CreatePcFixer();
     739           10 :         if (!instance_) {
     740            0 :             IDE_LOGW("[Dump][Exception] Unsupported platform for PC fix, PC fix skipped.");
     741            0 :             return nullptr;
     742              :         }
     743              :     }
     744           23 :     return instance_.get();
     745           28 : }
     746              : 
     747              : } // namespace Adx
        

Generated by: LCOV version 2.0-1