LCOV - code coverage report
Current view: top level - adump/exception - kernel_pc_fixer.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 94.5 % 271 256
Test Date: 2026-08-12 11:04:53 Functions: 100.0 % 31 31

            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         1708 : constexpr uint64_t GenPcMask64(uint64_t start, uint64_t end)
      29              : {
      30         1708 :     return static_cast<uint64_t>(((1ULL << (end - start + 1ULL)) - 1ULL) << start);
      31              : }
      32              : 
      33          160 : constexpr uint32_t GenPcMask32(uint32_t start, uint32_t end)
      34              : {
      35          160 :     return static_cast<uint32_t>(((1ULL << (end - start + 1ULL)) - 1ULL) << start);
      36              : }
      37              : 
      38          854 : PcFixEntry MakePcFixEntry(uint32_t errInfoRegNum, uint64_t srcMask, uint64_t dstMask)
      39              : {
      40          854 :     return {errInfoRegNum, srcMask, dstMask};
      41              : }
      42              : 
      43          490 : void AddPcFixGroup(
      44              :     std::vector<PcFixGroup>& groups, uint32_t moduleId, uint32_t aicErrMask,
      45              :     std::initializer_list<PcFixEntry> entries)
      46              : {
      47          490 :     if (aicErrMask == 0) {
      48          143 :         return;
      49              :     }
      50          347 :     PcFixGroup group;
      51          347 :     group.moduleId = moduleId;
      52          347 :     group.aicErrMask = aicErrMask;
      53          347 :     group.entries.insert(group.entries.end(), entries.begin(), entries.end());
      54          347 :     groups.push_back(group);
      55          347 : }
      56              : 
      57              : } // namespace
      58              : 
      59           42 : void PcFixerInterface::ReplacePcBits(uint64_t& pc, uint32_t regValue, uint64_t srcMask, uint64_t dstMask)
      60              : {
      61           42 :     if (srcMask == 0 || dstMask == 0 || __builtin_popcountll(srcMask) != __builtin_popcountll(dstMask)) {
      62            0 :         IDE_LOGW("[Dump][Exception] Invalid PC fix mask, srcMask=%lu, dstMask=%lu.", srcMask, dstMask);
      63            0 :         return;
      64              :     }
      65           42 :     int srcShift = __builtin_ctzll(srcMask);
      66           42 :     int dstShift = __builtin_ctzll(dstMask);
      67           42 :     uint64_t extracted = (static_cast<uint64_t>(regValue) & srcMask) >> srcShift;
      68           42 :     pc = (pc & ~dstMask) | ((extracted << dstShift) & dstMask);
      69              : }
      70              : 
      71           44 : uint64_t PcFixerInterface::FixPc(uint64_t pc, const uint32_t errReg[], size_t errRegLen)
      72              : {
      73           44 :     if (errReg == nullptr || errRegLen == 0) {
      74            6 :         IDE_LOGW("[Dump][Exception] Invalid error register info, skip fix PC.");
      75            6 :         return pc;
      76              :     }
      77              : 
      78           38 :     std::vector<const PcFixGroup*> matchedGroups = GetMatchedGroups(errReg, errRegLen);
      79           38 :     if (matchedGroups.empty()) {
      80           10 :         IDE_LOGI("[Dump][Exception] No matched PC fix module, skip fix PC.");
      81           10 :         return pc;
      82              :     }
      83              : 
      84           28 :     std::vector<uint64_t> fixedPcs;
      85           28 :     fixedPcs.reserve(matchedGroups.size());
      86           59 :     for (const auto* matchedGroup : matchedGroups) {
      87           31 :         uint64_t moduleFixedPc = pc;
      88           75 :         for (const auto& entry : matchedGroup->entries) {
      89           44 :             if (entry.errInfoRegNum >= errRegLen) {
      90            2 :                 continue;
      91              :             }
      92           42 :             uint32_t regValue = errReg[entry.errInfoRegNum];
      93           42 :             ReplacePcBits(moduleFixedPc, regValue, entry.srcMask, entry.dstMask);
      94              :         }
      95           31 :         fixedPcs.push_back(moduleFixedPc);
      96           31 :         std::string moduleName = GetModuleName(matchedGroup->moduleId);
      97           31 :         IDE_LOGE("[Dump][Exception] Fix PC with module=%s, originalPC=0x%lx, fixedPC=0x%lx.",
      98              :             moduleName.c_str(), pc, fixedPcs.back());
      99           31 :     }
     100           28 :     return fixedPcs.front();
     101           38 : }
     102              : 
     103           38 : std::vector<const PcFixGroup*> PcFixerInterface::GetMatchedGroups(const uint32_t errReg[], size_t errRegLen) const
     104              : {
     105           38 :     std::vector<const PcFixGroup*> matchedGroups;
     106          688 :     for (uint32_t i = 0; i < errCount_; i++) {
     107          650 :         uint32_t errIdx = errStartIdx_ + i;
     108          650 :         if (errIdx >= errRegLen) {
     109           11 :             continue;
     110              :         }
     111          639 :         uint32_t errVal = errReg[errIdx];
     112          639 :         if (errVal == 0) {
     113          587 :             continue;
     114              :         }
     115           52 :         if (i >= table_.size() || table_[i].empty()) {
     116           18 :             continue;
     117              :         }
     118           86 :         for (const auto& group : table_[i]) {
     119           52 :             if ((errVal & group.aicErrMask) == 0) {
     120           17 :                 continue;
     121              :             }
     122           35 :             bool moduleExists = std::any_of(matchedGroups.begin(), matchedGroups.end(),
     123            7 :                 [&group](const auto* matchedGroup) {
     124            7 :                     return matchedGroup->moduleId == group.moduleId;
     125              :                 });
     126           35 :             if (moduleExists) {
     127            4 :                 continue;
     128              :             }
     129           31 :             matchedGroups.push_back(&group);
     130              :         }
     131              :     }
     132           38 :     return matchedGroups;
     133            0 : }
     134              : 
     135              : // ===== V100(CloudV2)错误位名称表 =====
     136              : 
     137              : namespace {
     138              : const char* const AIC_ERROR_0_BIT_NAMES[UINT32_BIT_NUM] = {
     139              :     "biu_l2_read_oob", "biu_l2_write_oob", "ccu_call_depth_ovrflw", "ccu_div0",
     140              :     "ccu_illegal_instr", "ccu_loop_cnt_err", "ccu_loop_err", "ccu_neg_sqrt",
     141              :     "ccu_ub_ecc", "cube_invld_input", "cube_l0a_ecc", "cube_l0a_rdwr_cflt",
     142              :     "cube_l0a_wrap_around", "cube_l0b_ecc", "cube_l0b_rdwr_cflt", "cube_l0b_wrap_around",
     143              :     "cube_l0c_ecc", "cube_l0c_rdwr_cflt", "cube_l0c_self_rdwr_cflt", "cube_l0c_wrap_around",
     144              :     "ifu_bus_err", "mte_aipp_illegal_param", "mte_bas_raddr_obound", "mte_biu_rdwr_resp",
     145              :     "mte_cidx_overflow", "mte_decomp", "mte_f1wpos_larger_fsize", "mte_fmap_less_kernel",
     146              :     "mte_fmapwh_larger_l1size", "mte_fpos_larger_fsize", "mte_gdma_illegal_burst_len", "mte_gdma_illegal_burst_num",
     147              : };
     148              : 
     149              : const char* const AIC_ERROR_1_BIT_NAMES[UINT32_BIT_NUM] = {
     150              :     "mte_gdma_read_overflow", "mte_gdma_write_overflow", "mte_comp", "mte_illegal_fm_size",
     151              :     "mte_illegal_l1_3d_size", "mte_illegal_stride", "mte_l0a_rdwr_cflt", "mte_l0b_rdwr_cflt",
     152              :     "mte_l1_ecc", "mte_padding_cfg", "mte_read_overflow", "mte_rob_ecc",
     153              :     "mte_tlu_ecc", "mte_ub_ecc", "mte_unzip", "mte_write_3d_overflow",
     154              :     "mte_write_overflow", "vec_data_excp_ccu", "vec_data_excp_mte", "vec_data_excp_vec",
     155              :     "vec_div0", "vec_illegal_mask", "vec_inf_nan", "vec_l0c_ecc",
     156              :     "vec_l0c_rdwr_cflt", "vec_neg_ln", "vec_neg_sqrt", "vec_same_blk_addr",
     157              :     "vec_ub_ecc", "vec_ub_self_rdwr_cflt", "vec_ub_wrap_around", "biu_dfx_err",
     158              : };
     159              : 
     160              : const char* const AIC_ERROR_2_BIT_NAMES[UINT32_BIT_NUM] = {
     161              :     "ccu_sbuf_ecc", "vec_col2img_rd_fm_addr_ovflow",
     162              :     "vec_col2img_rd_dfm_addr_ovfflow", "vec_col2img_illegal_fm_size",
     163              :     "vec_col2img_illegal_stride", "vec_col2img_illegal_1st_win_pos",
     164              :     "vec_col2img_illegal_fetch_pos", "vec_col2img_illegal_k_size",
     165              :     "ccu_inf_nan", "mte_illegal_schn_cfg", "mte_atm_addr_misalg",
     166              :     "vec_instr_addr_misalign", "vec_instr_illegal_cfg", "vec_instr_undef",
     167              :     "ccu_addr_err",
     168              :     "reserved_ccu_bus_err", "mte_err_addr_misalign", "mte_err_dw_pad_conf_err",
     169              :     "mte_err_dw_fmap_h_illegal", "mte_err_wino_l0b_write_overflow",
     170              :     "mte_err_wino_l0b_read_overflow", "mte_err_illegal_v_cov_pad_ctl",
     171              :     "mte_err_illegal_h_cov_pad_ctl", "mte_err_illegal_w_size",
     172              :     "mte_err_illegal_h_size", "mte_err_illegal_chn_size",
     173              :     "mte_err_illegal_k_m_ext_step", "mte_err_illegal_k_m_start_pos",
     174              :     "mte_err_illegal_smallk_cfg", "mte_err_read_3d_overflow", "ccu_veciq_ecc",
     175              :     "ccu_dc_data_ecc",
     176              : };
     177              : 
     178              : const char* const AIC_ERROR_3_BIT_NAMES[UINT32_BIT_NUM] = {
     179              :     "ccu_dc_tag_ecc", "ccu_div0_fp", "ccu_neg_sqrt_fp", "cnt_sw_bus_err",
     180              :     "fixp_err_instr_addr_misal", "fixp_err_illegal_cfg", "fixp_err_read_l0c_ovflw",
     181              :     "fixp_err_read_l1_ovflw", "fixp_err_read_ub_ovflw", "fixp_err_write_l1_ovflw",
     182              :     "fixp_err_write_ub_ovflw", "fixp_err_fbuf_write_ovflw", "fixp_err_fbuf_read_ovflw",
     183              :     "sc_reg_parity_err", "mte_err_fifo_parity", "mte_err_waitset",
     184              :     "ccu_err_parity_err", "mte_err_cache_ecc", "cube_err_hset_cnt_unf",
     185              :     "cube_err_hset_cnt_ovf", "mte_err_instr_illegal_cfg", "mte_err_hebcd",
     186              :     "mte_err_hebce", "mte_err_waipp", "ccu_seq_err", "ccu_mpu_err",
     187              :     "ccu_lsu_err", "ccu_pb_ecc_err", "mte_ub_wr_ovflw", "mte_ub_rd_ovflw",
     188              :     "cube_illegal_instr", "ccu_safety_crc_err",
     189              : };
     190              : 
     191              : const char* const AIC_ERROR_4_BIT_NAMES[UINT32_BIT_NUM] = {
     192              :     "mte_timeout", "mte_ub_rd_cflt", "mte_ub_wr_cflt", "mte_ktable_wr_addr_overflow",
     193              :     "mte_ktable_rd_addr_overflow", "ccu_ub_rd_cflt", "ccu_ub_wr_cflt", "ccu_ub_overflow_err",
     194              :     "biu_unsplit_err", "mte_stb_ecc_err", "mte_aipp_ecc_err", "ccu_lsu_atomic_err",
     195              :     "ccu_cross_core_set_ovfl_err", "fixp_err_out_write_overflow", "cube_err_pbuf_wrap_around", "fixp_l0c_ecc",
     196              :     "mte_err_l0c_rdwr_cflt", "reserved", "reserved", "reserved",
     197              :     "reserved", "reserved", "reserved", "reserved",
     198              :     "reserved", "reserved", "reserved", "reserved",
     199              :     "reserved", "reserved", "reserved", "reserved",
     200              : };
     201              : 
     202              : const char* const AIC_ERROR_5_BIT_NAMES[UINT32_BIT_NUM] = {
     203              :     "vec_data_excpt_mte", "vec_data_excpt_su", "vec_data_excpt_vec", "vec_instr_timeout",
     204              :     "vec_instrs_undef", "vec_instr_ill_cfg", "vec_instr_misalign", "vec_instr_ill_mask",
     205              :     "vec_instr_ill_sqzn", "vec_ub_addr_wrap_around", "vec_ub_ecc_mberr", "vec_idata_inf_nan",
     206              :     "vec_div_by_zero", "vec_valu_neg_ln", "vec_valu_neg_sqrt", "vec_vci_idata_out_range",
     207              :     "vec_ill_vloop_op", "vec_ill_vloop_sreg", "vec_ld_num_mismatch", "vec_st_num_mismatch",
     208              :     "vec_ex_num_mismatch", "vec_ld_num_exceed_limit", "vec_st_num_exceed_limit", "vec_ill_instr_padding",
     209              :     "vec_ill_vga_vpd_order", "vec_ic_ecc_err", "vec_biu_resp_err", "vec_pb_ecc_mberr",
     210              :     "vec_pb_read_no_resp", "vec_valu_ill_issue", "vec_err_parity_err", "reserved",
     211              : };
     212              : 
     213              : const char* const* const AIC_ERROR_BIT_NAMES[V100_AIC_ERR_NUM] = {
     214              :     AIC_ERROR_0_BIT_NAMES, AIC_ERROR_1_BIT_NAMES, AIC_ERROR_2_BIT_NAMES,
     215              :     AIC_ERROR_3_BIT_NAMES, AIC_ERROR_4_BIT_NAMES, AIC_ERROR_5_BIT_NAMES,
     216              : };
     217              : 
     218              : enum V100ModuleIdx {
     219              :     V100_CUBE_INFO_IDX,
     220              :     V100_CCU_INFO_IDX,
     221              :     V100_IFU_INFO_IDX,
     222              :     V100_MTE_INFO_IDX,
     223              :     V100_VEC_INFO_IDX,
     224              :     V100_FIXP_INFO_IDX,
     225              :     V100_MODULE_ID_NUM
     226              : };
     227              : 
     228              : enum V200ErrorIdx {
     229              :     V200_SC_ERROR_T0_IDX,
     230              :     V200_SU_ERROR_T0_IDX,
     231              :     V200_MTE_ERROR_T0_IDX,
     232              :     V200_MTE_ERROR_T1_IDX,
     233              :     V200_VEC_ERROR_T0_IDX,
     234              :     V200_VEC_ERROR_T2_IDX,
     235              :     V200_CUBE_ERROR_T0_IDX,
     236              :     V200_CUBE_ERROR_T1_IDX,
     237              :     V200_L1_ERROR_T0_IDX,
     238              :     V200_L1_ERROR_T1_IDX,
     239              :     V200_ERROR_IDX_NUM
     240              : };
     241              : 
     242              : // V100 errReg 下标对应的 RTS 寄存器枚举名称,与 rtErrRegInfoIdxV100_t 顺序一致。
     243              : const char* const V100_REG_NAMES[] = {
     244              :     "AIC_ERR_0", "AIC_ERR_1", "AIC_ERR_2", "AIC_ERR_3",
     245              :     "AIC_ERR_4", "AIC_ERR_5", "BIU_ERR_0", "BIU_ERR_1",
     246              :     "CCU_ERR_0", "CCU_ERR_1", "CUBE_ERR_0", "CUBE_ERR_1",
     247              :     "IFU_ERR_0", "IFU_ERR_1", "MTE_ERR_0", "MTE_ERR_1",
     248              :     "VEC_ERR_0", "VEC_ERR_1", "FIXP_ERR_0", "FIXP_ERR_1",
     249              :     "AIC_COND_0", "AIC_COND_1",
     250              : };
     251              : 
     252              : // V200 errReg 下标对应的 RTS 寄存器枚举名称,与 rtErrRegInfoIdxV200_t 顺序一致。
     253              : const char* const V200_REG_NAMES[] = {
     254              :     "SU_ERR_INFO_T0_0", "SU_ERR_INFO_T0_1", "SU_ERR_INFO_T0_2",
     255              :     "SU_ERR_INFO_T0_3", "MTE_ERR_INFO_T0_0", "MTE_ERR_INFO_T0_1",
     256              :     "MTE_ERR_INFO_T0_2", "MTE_ERR_INFO_T1_0", "MTE_ERR_INFO_T1_1",
     257              :     "MTE_ERR_INFO_T1_2", "VEC_ERR_INFO_T0_0", "VEC_ERR_INFO_T0_1",
     258              :     "VEC_ERR_INFO_T0_2", "VEC_ERR_INFO_T0_3", "VEC_ERR_INFO_T0_4",
     259              :     "VEC_ERR_INFO_T0_5", "CUBE_ERR_INFO_T0_0", "CUBE_ERR_INFO_T0_1",
     260              :     "L1_ERR_INFO_T0_0", "L1_ERR_INFO_T0_1", "SC_ERROR_T0_0",
     261              :     "SU_ERROR_T0_0", "MTE_ERROR_T0_0", "MTE_ERROR_T1_0",
     262              :     "VEC_ERROR_T0_0", "VEC_ERROR_T0_2", "CUBE_ERROR_T0_0",
     263              :     "CUBE_ERROR_T0_1", "L1_ERROR_T0_0", "L1_ERROR_T0_1",
     264              :     "SC_ERR_INFO_T0_0", "SC_ERR_INFO_T0_1", "SU_SPR_CONDITION_0",
     265              :     "SU_SPR_CONDITION_1", "SU_ERR_INFO_T0_4", "SU_ERR_INFO_T0_5",
     266              :     "SU_ERR_INFO_T0_6", "SU_ERR_INFO_T0_7", "VEC_ERR_INFO_T0_6",
     267              :     "SU_ERROR_T0_1",
     268              : };
     269              : 
     270         2112 : std::string GetV100BitName(uint32_t aicErrorIdx, uint32_t bit)
     271              : {
     272         2112 :     if (aicErrorIdx >= V100_AIC_ERR_NUM || bit >= UINT32_BIT_NUM) {
     273            0 :         return "";
     274              :     }
     275         4224 :     return std::string(AIC_ERROR_BIT_NAMES[aicErrorIdx][bit]);
     276              : }
     277              : 
     278         2112 : bool IsCubeErrorBitName(const std::string& bitName)
     279              : {
     280         2112 :     return bitName.find("cube_") == 0 || bitName.find("cube_err_") == 0 || bitName.find("cube_invld_") == 0;
     281              : }
     282              : 
     283         1947 : bool IsCcuErrorBitName(const std::string& bitName)
     284              : {
     285         5269 :     return bitName.find("ccu_") == 0 || bitName.find("ccu_err_") == 0 || bitName.find("ccu_inf_") == 0 ||
     286         4983 :            bitName.find("ccu_addr_") == 0 || bitName.find("ccu_div0_fp") == 0 ||
     287         4983 :            bitName.find("ccu_neg_sqrt_fp") == 0 || bitName.find("ccu_dc_") == 0 ||
     288         4983 :            bitName.find("ccu_sbuf_") == 0 || bitName.find("ccu_veciq_") == 0 ||
     289         4983 :            bitName.find("ccu_pb_ecc_err") == 0 || bitName.find("ccu_seq_") == 0 ||
     290         6930 :            bitName.find("ccu_mpu_") == 0 || bitName.find("ccu_lsu_") == 0 ||
     291         3608 :            bitName.find("ccu_safety_") == 0;
     292              : }
     293              : 
     294          990 : bool IsVecErrorBitName(const std::string& bitName)
     295              : {
     296         1760 :     return bitName.find("vec_") == 0 || bitName.find("vec_data_excp_") == 0 ||
     297         2145 :            bitName.find("vec_col2img_") == 0 || bitName.find("vec_instr_") == 0 ||
     298         1375 :            bitName.find("vec_err_parity_") == 0;
     299              : }
     300              : 
     301           66 : void BuildV100ModuleMasks(uint32_t aicErrorIdx, uint32_t moduleMasks[])
     302              : {
     303         2178 :     for (uint32_t bit = 0; bit < UINT32_BIT_NUM; bit++) {
     304         2112 :         std::string bitName = GetV100BitName(aicErrorIdx, bit);
     305         2112 :         if (IsCubeErrorBitName(bitName)) {
     306          165 :             moduleMasks[V100_CUBE_INFO_IDX] |= (1U << bit);
     307         1947 :         } else if (IsCcuErrorBitName(bitName)) {
     308          286 :             moduleMasks[V100_CCU_INFO_IDX] |= (1U << bit);
     309         1661 :         } else if (bitName.find("mte_") == 0 || bitName.find("mte_err_") == 0) {
     310          671 :             moduleMasks[V100_MTE_INFO_IDX] |= (1U << bit);
     311          990 :         } else if (IsVecErrorBitName(bitName)) {
     312          605 :             moduleMasks[V100_VEC_INFO_IDX] |= (1U << bit);
     313          385 :         } else if (bitName.find("fixp_") == 0 || bitName.find("fixp_err_") == 0) {
     314          121 :             moduleMasks[V100_FIXP_INFO_IDX] |= (1U << bit);
     315              :         }
     316         2112 :     }
     317           66 : }
     318              : 
     319           66 : void AppendV100PcFixGroups(const uint32_t moduleMasks[], std::vector<PcFixGroup>& groups)
     320              : {
     321           66 :     AddPcFixGroup(groups, V100_CUBE_INFO_IDX, moduleMasks[V100_CUBE_INFO_IDX],
     322           66 :         {MakePcFixEntry(RT_V100_CUBE_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     323           66 :             MakePcFixEntry(RT_V100_CUBE_ERR_0, GenPcMask64(24, 31), GenPcMask64(10, 17))});
     324           66 :     AddPcFixGroup(groups, V100_CCU_INFO_IDX, moduleMasks[V100_CCU_INFO_IDX],
     325           66 :         {MakePcFixEntry(RT_V100_CCU_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     326           66 :             MakePcFixEntry(RT_V100_CCU_ERR_0, GenPcMask64(23, 30), GenPcMask64(10, 17))});
     327           66 :     AddPcFixGroup(groups, V100_MTE_INFO_IDX, moduleMasks[V100_MTE_INFO_IDX],
     328           66 :         {MakePcFixEntry(RT_V100_MTE_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     329           66 :             MakePcFixEntry(RT_V100_MTE_ERR_1, GenPcMask64(0, 7), GenPcMask64(10, 17))});
     330           66 :     AddPcFixGroup(groups, V100_VEC_INFO_IDX, moduleMasks[V100_VEC_INFO_IDX],
     331           66 :         {MakePcFixEntry(RT_V100_VEC_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     332           66 :             MakePcFixEntry(RT_V100_VEC_ERR_1, GenPcMask64(0, 7), GenPcMask64(10, 17))});
     333           66 :     AddPcFixGroup(groups, V100_FIXP_INFO_IDX, moduleMasks[V100_FIXP_INFO_IDX],
     334           66 :         {MakePcFixEntry(RT_V100_FIXP_ERR_0, GenPcMask64(0, 7), GenPcMask64(2, 9)),
     335           66 :             MakePcFixEntry(RT_V100_FIXP_ERR_1, GenPcMask64(0, 7), GenPcMask64(10, 17))});
     336           66 : }
     337              : 
     338           10 : void InitV200CommonPcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     339              : {
     340           10 :     AddPcFixGroup(table[V200_SU_ERROR_T0_IDX], V200_SU_ERROR_T0_IDX, GenPcMask32(0, 31),
     341           10 :         {MakePcFixEntry(RT_V200_SU_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     342           10 :     AddPcFixGroup(table[V200_MTE_ERROR_T0_IDX], V200_MTE_ERROR_T0_IDX, GenPcMask32(0, 31),
     343           10 :         {MakePcFixEntry(RT_V200_MTE_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     344              :     // MTE_ERR_INFO_T1_0值废弃,使用MTE_ERR_INFO_T0_0
     345           10 :     AddPcFixGroup(table[V200_MTE_ERROR_T1_IDX], V200_MTE_ERROR_T0_IDX, GenPcMask32(0, 31),
     346           10 :         {MakePcFixEntry(RT_V200_MTE_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     347           10 : }
     348              : 
     349           10 : void InitV200VecPcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     350              : {
     351           10 :     AddPcFixGroup(table[V200_VEC_ERROR_T0_IDX], V200_VEC_ERROR_T0_IDX, GenPcMask32(0, 25),
     352           10 :         {MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_1, GenPcMask64(0, 31), GenPcMask64(0, 31)),
     353           10 :             MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_2, GenPcMask64(0, 16), GenPcMask64(32, 48))});
     354           10 :     AddPcFixGroup(table[V200_VEC_ERROR_T2_IDX], V200_VEC_ERROR_T0_IDX, GenPcMask32(0, 1),
     355           10 :         {MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_1, GenPcMask64(0, 31), GenPcMask64(0, 31)),
     356           10 :             MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_2, GenPcMask64(0, 16), GenPcMask64(32, 48))});
     357           10 : }
     358              : 
     359           10 : void InitV200CubeAndL1PcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     360              : {
     361           10 :     AddPcFixGroup(table[V200_CUBE_ERROR_T0_IDX], V200_CUBE_ERROR_T0_IDX, GenPcMask32(0, 15),
     362           10 :         {MakePcFixEntry(RT_V200_CUBE_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     363           10 :     AddPcFixGroup(table[V200_CUBE_ERROR_T1_IDX], V200_CUBE_ERROR_T0_IDX, GenPcMask32(0, 9),
     364           10 :         {MakePcFixEntry(RT_V200_CUBE_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     365           10 :     AddPcFixGroup(table[V200_L1_ERROR_T0_IDX], V200_L1_ERROR_T0_IDX, GenPcMask32(0, 30),
     366           10 :         {MakePcFixEntry(RT_V200_L1_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     367           10 :     AddPcFixGroup(table[V200_L1_ERROR_T1_IDX], V200_L1_ERROR_T0_IDX, GenPcMask32(0, 21),
     368           10 :         {MakePcFixEntry(RT_V200_L1_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     369           10 : }
     370              : 
     371            9 : std::string BuildErrorRegistersStr(
     372              :     const char* const regNames[], size_t regNameNum, const uint32_t errReg[], size_t errRegLen)
     373              : {
     374            9 :     constexpr size_t REG_ITEM_BUF_LEN = 128U;
     375            9 :     std::string result;
     376          261 :     for (size_t i = 0; i < regNameNum && i < errRegLen; i++) {
     377          252 :         char item[REG_ITEM_BUF_LEN] = {0};
     378          252 :         int len = snprintf_s(item, sizeof(item), sizeof(item) - 1, "%s=0x%x ", regNames[i], errReg[i]);
     379          252 :         if (len < 0) {
     380            0 :             continue;
     381              :         }
     382          252 :         result += item;
     383              :     }
     384            9 :     return result;
     385            0 : }
     386              : } // namespace
     387              : 
     388              : // ===== CloudV2 PC 修正 =====
     389              : 
     390           11 : CloudV2PcFixer::CloudV2PcFixer()
     391              : {
     392           11 :     errStartIdx_ = static_cast<uint32_t>(RT_V100_AIC_ERR_0);
     393           11 :     errCount_ = V100_AIC_ERR_NUM;
     394           11 :     table_.resize(V100_AIC_ERR_NUM);
     395              : 
     396           77 :     for (uint32_t i = 0; i < V100_AIC_ERR_NUM; i++) {
     397           66 :         uint32_t moduleMasks[V100_MODULE_ID_NUM] = {0};
     398           66 :         BuildV100ModuleMasks(i, moduleMasks);
     399           66 :         AppendV100PcFixGroups(moduleMasks, table_[i]);
     400              :     }
     401           11 : }
     402              : 
     403            6 : std::string CloudV2PcFixer::GetErrorRegisters(const uint32_t errReg[], size_t errRegLen) const
     404              : {
     405            6 :     if (errReg == nullptr || errRegLen == 0) {
     406            0 :         return "";
     407              :     }
     408            6 :     constexpr size_t regNameNum = sizeof(V100_REG_NAMES) / sizeof(V100_REG_NAMES[0]);
     409            6 :     return BuildErrorRegistersStr(V100_REG_NAMES, regNameNum, errReg, errRegLen);
     410              : }
     411              : 
     412           10 : std::string CloudV2PcFixer::GetModuleName(uint32_t moduleId) const
     413              : {
     414           10 :     const char* const moduleNames[V100_MODULE_ID_NUM] = {"CUBE", "CCU", "IFU", "MTE", "VEC", "FIXP"};
     415           10 :     if (moduleId >= V100_MODULE_ID_NUM) {
     416            0 :         return "UNKNOWN";
     417              :     }
     418           20 :     return moduleNames[moduleId];
     419              : }
     420              : 
     421              : // ===== CloudV4 PC 修正 =====
     422              : 
     423           10 : CloudV4PcFixer::CloudV4PcFixer()
     424              : {
     425           10 :     errStartIdx_ = static_cast<uint32_t>(RT_V200_SC_ERROR_T0_0);
     426           10 :     errCount_ = V200_ERROR_IDX_NUM;
     427           10 :     table_.resize(errCount_);
     428              : 
     429              :     // SC_ERROR_T0_0 没有 PC 映射规则。
     430           10 :     table_[V200_SC_ERROR_T0_IDX] = {};
     431           10 :     InitV200CommonPcFixGroups(table_);
     432           10 :     InitV200VecPcFixGroups(table_);
     433           10 :     InitV200CubeAndL1PcFixGroups(table_);
     434           10 : }
     435              : 
     436            1 : std::string CloudV4PcFixer::GetErrorRegisters(const uint32_t errReg[], size_t errRegLen) const
     437              : {
     438            1 :     if (errReg == nullptr || errRegLen == 0) {
     439            0 :         return "";
     440              :     }
     441            1 :     constexpr size_t regNameNum = sizeof(V200_REG_NAMES) / sizeof(V200_REG_NAMES[0]);
     442            1 :     return BuildErrorRegistersStr(V200_REG_NAMES, regNameNum, errReg, errRegLen);
     443              : }
     444              : 
     445           11 : std::string CloudV4PcFixer::GetModuleName(uint32_t moduleId) const
     446              : {
     447           11 :     switch (moduleId) {
     448            4 :         case V200_SU_ERROR_T0_IDX:
     449            8 :             return "SU";
     450            3 :         case V200_MTE_ERROR_T0_IDX:
     451            6 :             return "MTE";
     452            2 :         case V200_VEC_ERROR_T0_IDX:
     453            4 :             return "VEC";
     454            1 :         case V200_CUBE_ERROR_T0_IDX:
     455            2 :             return "CUBE";
     456            1 :         case V200_L1_ERROR_T0_IDX:
     457            2 :             return "L1";
     458            0 :         default:
     459            0 :             return "UNKNOWN";
     460              :     }
     461              : }
     462              : 
     463              : 
     464              : // === CloudV5 PC Fixer ====
     465              : namespace {
     466              : // V5 errReg 采用 V200 布局,各寄存器下标沿用 rtErrRegInfoIdxV200_t 的绝对值。
     467              : // 其中 SU_ERROR_T0_1 复用 RT_V200_SU_ERROR_T0_1,在 V200 布局下位于离群下标处。
     468              : enum V300ErrorIdx {
     469              :     V300_SC_ERROR_T0_0_IDX = RT_V200_SC_ERROR_T0_0,
     470              :     V300_SU_ERROR_T0_0_IDX = RT_V200_SU_ERROR_T0_0,
     471              :     V300_SU_ERROR_T0_1_IDX = RT_V200_SU_ERROR_T0_1,
     472              :     V300_MTE_ERROR_T0_0_IDX = RT_V200_MTE_ERROR_T0_0,
     473              :     V300_MTE_ERROR_T1_0_IDX = RT_V200_MTE_ERROR_T1_0,
     474              :     V300_VEC_ERROR_T0_0_IDX = RT_V200_VEC_ERROR_T0_0,
     475              :     V300_VEC_ERROR_T0_2_IDX = RT_V200_VEC_ERROR_T0_2,
     476              :     V300_CUBE_ERROR_T0_0_IDX = RT_V200_CUBE_ERROR_T0_0,
     477              :     V300_CUBE_ERROR_T0_1_IDX = RT_V200_CUBE_ERROR_T0_1,
     478              :     V300_L1_ERROR_T0_0_IDX = RT_V200_L1_ERROR_T0_0,
     479              :     V300_L1_ERROR_T0_1_IDX = RT_V200_L1_ERROR_T0_1,
     480              :     V300_ERROR_IDX_NUM = RT_V200_SU_ERROR_T0_1 + 1
     481              : };
     482              : 
     483            7 : void InitV300CommonPcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     484              : {
     485            7 :     AddPcFixGroup(table[V300_SU_ERROR_T0_0_IDX], V300_SU_ERROR_T0_0_IDX, GenPcMask32(0, 31),
     486            7 :         {MakePcFixEntry(RT_V200_SU_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     487            7 :     AddPcFixGroup(table[V300_SU_ERROR_T0_1_IDX], V300_SU_ERROR_T0_0_IDX, GenPcMask32(0, 3),
     488            7 :         {MakePcFixEntry(RT_V200_SU_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     489            7 :     AddPcFixGroup(table[V300_MTE_ERROR_T0_0_IDX], V300_MTE_ERROR_T0_0_IDX, GenPcMask32(0, 31),
     490            7 :         {MakePcFixEntry(RT_V200_MTE_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     491              :     // MTE_ERR_INFO_T1_0值废弃,使用MTE_ERR_INFO_T0_0
     492            7 :     AddPcFixGroup(table[V300_MTE_ERROR_T1_0_IDX], V300_MTE_ERROR_T0_0_IDX, GenPcMask32(0, 31),
     493            7 :         {MakePcFixEntry(RT_V200_MTE_ERR_INFO_T0_0, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     494            7 : }
     495              : 
     496            7 : void InitV300VecPcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     497              : {
     498            7 :     AddPcFixGroup(table[V300_VEC_ERROR_T0_0_IDX], V300_VEC_ERROR_T0_0_IDX, GenPcMask32(0, 29),
     499            7 :         {MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_1, GenPcMask64(0, 31), GenPcMask64(0, 31)),
     500            7 :             MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_2, GenPcMask64(0, 16), GenPcMask64(32, 48))});
     501            7 :     AddPcFixGroup(table[V300_VEC_ERROR_T0_2_IDX], V300_VEC_ERROR_T0_0_IDX, GenPcMask32(0, 12),
     502            7 :         {MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_1, GenPcMask64(0, 31), GenPcMask64(0, 31)),
     503            7 :             MakePcFixEntry(RT_V200_VEC_ERR_INFO_T0_2, GenPcMask64(0, 16), GenPcMask64(32, 48))});
     504            7 : }
     505              : 
     506            7 : void InitV300CubeAndL1PcFixGroups(std::vector<std::vector<PcFixGroup>>& table)
     507              : {
     508            7 :     AddPcFixGroup(table[V300_CUBE_ERROR_T0_0_IDX], V300_CUBE_ERROR_T0_0_IDX, GenPcMask32(0, 18),
     509            7 :         {MakePcFixEntry(RT_V200_CUBE_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     510            7 :     AddPcFixGroup(table[V300_CUBE_ERROR_T0_1_IDX], V300_CUBE_ERROR_T0_0_IDX, GenPcMask32(0, 9),
     511            7 :         {MakePcFixEntry(RT_V200_CUBE_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     512            7 :     AddPcFixGroup(table[V300_L1_ERROR_T0_0_IDX], V300_L1_ERROR_T0_0_IDX, GenPcMask32(0, 30),
     513            7 :         {MakePcFixEntry(RT_V200_L1_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     514            7 :     AddPcFixGroup(table[V300_L1_ERROR_T0_1_IDX], V300_L1_ERROR_T0_0_IDX, GenPcMask32(0, 22),
     515            7 :         {MakePcFixEntry(RT_V200_L1_ERR_INFO_T0_1, GenPcMask64(0, 15), GenPcMask64(2, 17))});
     516            7 : }
     517              : }
     518              : 
     519            7 : CloudV5PcFixer::CloudV5PcFixer()
     520              : {
     521              :     // V5 errReg 为 V200 布局,table_ 按 errReg 绝对下标寻址,故 errStartIdx_ 从 0 起,
     522              :     // errCount_ 覆盖到最大用到的下标;未使用的位置留空并在扫描时跳过。
     523              :     // 最大下标为 RT_V200_SU_ERROR_T0_1(值 39),故 errCount_ = 40;SU_ERROR_T0_1
     524              :     // 与常规错误下标(0~29)之间的 30~38 为 ERR_INFO 类寄存器,非空洞,table_ 空条目占比很低,
     525              :     // 连续 vector 寻址 O(1)、无需哈希映射。
     526            7 :     errStartIdx_ = 0;
     527            7 :     errCount_ = V300_ERROR_IDX_NUM;
     528            7 :     table_.resize(errCount_);
     529              : 
     530              :     // SC_ERROR_T0_0 没有 PC 映射规则。
     531            7 :     table_[V300_SC_ERROR_T0_0_IDX] = {};
     532            7 :     InitV300CommonPcFixGroups(table_);
     533            7 :     InitV300VecPcFixGroups(table_);
     534            7 :     InitV300CubeAndL1PcFixGroups(table_);
     535            7 : }
     536              : 
     537            4 : std::string CloudV5PcFixer::GetErrorRegisters(const uint32_t errReg[], size_t errRegLen) const
     538              : {
     539            4 :     if (errReg == nullptr || errRegLen == 0) {
     540            4 :         return "";
     541              :     }
     542              :     // V5 errReg 为 V200 布局,寄存器名沿用 V200_REG_NAMES。
     543            2 :     constexpr size_t regNameNum = sizeof(V200_REG_NAMES) / sizeof(V200_REG_NAMES[0]);
     544            2 :     return BuildErrorRegistersStr(V200_REG_NAMES, regNameNum, errReg, errRegLen);
     545              : }
     546              : 
     547           10 : std::string CloudV5PcFixer::GetModuleName(uint32_t moduleId) const
     548              : {
     549           10 :     switch (moduleId) {
     550            5 :         case V300_SU_ERROR_T0_0_IDX:
     551              :         case V300_SU_ERROR_T0_1_IDX:
     552           10 :             return "SU";
     553            2 :         case V300_MTE_ERROR_T0_0_IDX:
     554              :         case V300_MTE_ERROR_T1_0_IDX:
     555            4 :             return "MTE";
     556            1 :         case V300_VEC_ERROR_T0_0_IDX:
     557              :         case V300_VEC_ERROR_T0_2_IDX:
     558            2 :             return "VEC";
     559            1 :         case V300_CUBE_ERROR_T0_0_IDX:
     560              :         case V300_CUBE_ERROR_T0_1_IDX:
     561            2 :             return "CUBE";
     562            1 :         case V300_L1_ERROR_T0_0_IDX:
     563              :         case V300_L1_ERROR_T0_1_IDX:
     564            2 :             return "L1";
     565            0 :         default:
     566            0 :             return "UNKNOWN";
     567              :     }
     568              : }
     569              : 
     570              : std::unique_ptr<PcFixerInterface> PcFixerFactory::instance_;
     571              : 
     572           22 : PcFixerInterface* PcFixerFactory::GetInstance()
     573              : {
     574           22 :     std::lock_guard<std::mutex> lock(g_pcFixerMutex);
     575           22 :     if (!instance_) {
     576           11 :         auto *plat = CoredumpManager::Get();
     577           11 :         if (plat == nullptr) {
     578            3 :             IDE_LOGW("[Dump][Exception] Platform unavailable, PC fix skipped.");
     579            3 :             return nullptr;
     580              :         }
     581            8 :         instance_ = plat->CreatePcFixer();
     582            8 :         if (!instance_) {
     583            0 :             IDE_LOGW("[Dump][Exception] Unsupported platform for PC fix, PC fix skipped.");
     584            0 :             return nullptr;
     585              :         }
     586              :     }
     587           19 :     return instance_.get();
     588           22 : }
     589              : 
     590              : } // namespace Adx
        

Generated by: LCOV version 2.0-1