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
|