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 <sstream>
11 : #include <iomanip>
12 : #include "log/adx_log.h"
13 : #include "runtime/mem.h"
14 : #include "adump_platform_manager.h"
15 : #include "register_config.h"
16 : #include "exception_info_common.h"
17 : #include "dump_core.h"
18 :
19 : namespace Adx {
20 : constexpr int32_t REG_FIELD_WIDTH = 2;
21 :
22 90 : void DumpCore::DumpRegister(uint8_t coreType, uint16_t coreId)
23 : {
24 90 : auto* plat = CoredumpManager::Get();
25 90 : if (plat == nullptr) {
26 5 : IDE_LOGW("[DumpCore] Platform unavailable, register dump skipped.");
27 5 : return;
28 : }
29 85 : plat->DumpRegister(*this, coreType, coreId);
30 : }
31 :
32 51 : std::string DumpCore::FormatRegisterData(const uint8_t* valAddr, uint8_t valSize) const
33 : {
34 51 : std::stringstream ss;
35 51 : ss << std::hex << std::setfill('0');
36 255 : for (uint8_t i = 0; i < valSize; ++i) {
37 204 : ss << std::setw(REG_FIELD_WIDTH) << static_cast<uint32_t>(valAddr[i]);
38 : }
39 102 : return ss.str();
40 51 : }
41 :
42 18044 : bool DumpCore::DumpReadDebugAICoreRegister(
43 : uint8_t coreType, uint16_t coreId, RegisterType regType, const RegisterTable& table,
44 : std::vector<uint8_t>& data) const
45 : {
46 18044 : data.resize(table.num * table.byteWidth);
47 : rtDebugMemoryType_t memType;
48 18044 : if (regType == RegisterType::AIC || regType == RegisterType::AIV) {
49 512 : memType = RT_MEM_TYPE_REGISTER_DIRECT;
50 17532 : } else if (regType == RegisterType::AIC_DBG || regType == RegisterType::AIV_DBG) {
51 17532 : memType = RT_MEM_TYPE_REGISTER;
52 : } else {
53 0 : IDE_LOGE("Wrong regType. regType: %d", regType);
54 0 : return false;
55 : }
56 18044 : rtDebugMemoryParam_t param = {coreType, 0, coreId, memType, 0, 0, 0, 0, 0};
57 18044 : param.srcAddr = table.startAddr;
58 18044 : param.dstAddr = reinterpret_cast<uint64_t>(data.data());
59 18044 : param.memLen = table.num * table.byteWidth;
60 18044 : param.elementSize = table.byteWidth;
61 18044 : rtError_t ret = rtDebugReadAICore(¶m);
62 18044 : if (ret != RT_ERROR_NONE) {
63 15750 : IDE_LOGE(
64 : "Failed to read debug register data. coreType: %hhu, coreId: %hu, start addr: 0x%llx, "
65 : "num: %u, byteWidth: %hhu, ret: %d",
66 : coreType, coreId, param.srcAddr, table.num, table.byteWidth, static_cast<int32_t>(ret));
67 15750 : return false;
68 : }
69 2294 : return true;
70 : }
71 :
72 : template <typename T>
73 177 : void DumpCore::DumpDebugRegisterImpl(
74 : uint8_t coreType, uint16_t coreId, RegisterType regType, const std::vector<RegisterTable>& tables,
75 : std::vector<T>& regData) const
76 : {
77 177 : std::stringstream ss;
78 36442 : for (const RegisterTable& table : tables) {
79 18044 : std::vector<uint8_t> data;
80 18044 : bool dataValid = DumpReadDebugAICoreRegister(coreType, coreId, regType, table, data);
81 18044 : errno_t err = EOK;
82 18044 : const uint8_t* dataPtr = data.data();
83 345915 : for (uint32_t i = 0; i < table.num; ++i) {
84 327871 : T regInfo{table.startAddr + i, REG_DATA_VALID, {0}, table.byteWidth, {0}};
85 327871 : if (dataValid) {
86 41375 : err = memcpy_s(®Info.value, sizeof(regInfo.value), dataPtr, table.byteWidth);
87 41375 : if (err != EOK) {
88 20464 : IDE_LOGE(
89 : "Failed to copy debug register data from cache buffer. "
90 : "coreType: %hhu, coreId: %hu, addr: 0x%llx, ret: %d",
91 : coreType, coreId, regInfo.addr, err);
92 20464 : regInfo.validFlag = REG_DATA_INVALID;
93 : }
94 : } else {
95 286496 : regInfo.validFlag = REG_DATA_INVALID;
96 : }
97 327871 : dataPtr += table.byteWidth;
98 327871 : regData.emplace_back(regInfo);
99 : }
100 : }
101 177 : std::string dataStr = ss.str();
102 177 : if (!dataStr.empty()) {
103 0 : IDE_LOGW(
104 : "Debug register data. coreType=%d, coreId=%d.%s", static_cast<int32_t>(coreType), coreId, dataStr.c_str());
105 : }
106 177 : }
107 :
108 : template <typename T>
109 85 : void DumpCore::DumpErrorRegisterImpl(
110 : uint8_t coreType, uint16_t coreId, const std::vector<ErrorRegisterTable>& tables, std::vector<T>& regData) const
111 : {
112 85 : std::stringstream ss;
113 85 : std::vector<std::string> regLogs;
114 170 : for (uint32_t i = 0; i < exceptionRegInfo_.coreNum; i++) {
115 85 : rtExceptionErrRegInfo_t core = exceptionRegInfo_.errRegInfo[i];
116 85 : if (coreId != core.coreId || coreType != core.coreType) {
117 68 : continue;
118 : }
119 565 : for (const auto& table : tables) {
120 531 : T regInfo{table.offsetAddr, REG_DATA_VALID, {0}, table.byteWidth, {0}};
121 : errno_t err =
122 531 : memcpy_s(®Info.value, sizeof(regInfo.value), core.errReg + table.errIndex, table.byteWidth);
123 531 : if (err != EOK) {
124 480 : IDE_LOGE(
125 : "Failed to copy error register data from exception args. "
126 : "coreType: %hhu, coreId: %hu, addr: 0x%llx, ret: %d",
127 : coreType, coreId, regInfo.addr, err);
128 480 : regInfo.validFlag = REG_DATA_INVALID;
129 : } else {
130 51 : std::string value = FormatRegisterData(regInfo.value, regInfo.regSize);
131 51 : ss << table.name << "[0x" << std::hex << regInfo.addr << "]: " << value << ",";
132 51 : }
133 531 : regData.emplace_back(regInfo);
134 : }
135 : }
136 85 : std::string dataStr = ss.str();
137 85 : if (!dataStr.empty()) {
138 2 : IDE_LOGW(
139 : "Error register data. coreType=%d, coreId=%d. %s", static_cast<int32_t>(coreType), coreId, dataStr.c_str());
140 : }
141 85 : }
142 :
143 80 : void DumpCore::DumpV2Register(uint8_t coreType, uint16_t coreId)
144 : {
145 80 : std::vector<RegInfo> regData;
146 80 : std::string sectionName = ASCEND_SHNAME_REGS + "." + std::to_string(ConvertCoreId(coreType, coreId));
147 80 : std::shared_ptr<RegisterInterface> reg = RegisterManager::GetInstance().GetRegister();
148 80 : IDE_CTRL_VALUE_FAILED(reg != nullptr, return, "Get register failed, null register.");
149 327 : for (const auto& regType : reg->GetRegisterTypes(coreType)) {
150 167 : DumpV2DebugRegister(coreType, coreId, reg->GetRegisterTable(regType), regData);
151 : }
152 80 : DumpV2ErrorRegister(coreType, coreId, reg->GetErrorRegisterTable(), regData);
153 :
154 80 : size_t totalSize = regData.size() * sizeof(RegInfo);
155 80 : std::string data(reinterpret_cast<const char*>(regData.data()), totalSize);
156 80 : ELF::SectionPtr registerSection = coreFile_.AddSection(ASCEND_SHTYPE_REGS, sectionName);
157 80 : IDE_CTRL_VALUE_FAILED(registerSection != nullptr, return, "Create %s section failed.", sectionName.c_str());
158 80 : registerSection->SetData(data);
159 80 : registerSection->SetEntSize(sizeof(RegInfo));
160 80 : }
161 :
162 167 : void DumpCore::DumpV2DebugRegister(
163 : uint8_t coreType, uint16_t coreId, const std::vector<RegisterTable>& tables, std::vector<RegInfo>& regData) const
164 : {
165 : RegisterType regType;
166 167 : if (coreType == CORE_TYPE_AIC) {
167 68 : regType = RegisterType::AIC_DBG;
168 : } else {
169 99 : regType = RegisterType::AIV_DBG;
170 : }
171 167 : DumpDebugRegisterImpl(coreType, coreId, regType, tables, regData);
172 167 : }
173 :
174 80 : void DumpCore::DumpV2ErrorRegister(
175 : uint8_t coreType, uint16_t coreId, const std::vector<ErrorRegisterTable>& tables,
176 : std::vector<RegInfo>& regData) const
177 : {
178 80 : DumpErrorRegisterImpl(coreType, coreId, tables, regData);
179 80 : }
180 :
181 5 : void DumpCore::DumpV4Register(uint8_t coreType, uint16_t coreId)
182 : {
183 5 : std::vector<RegInfoWide> regData;
184 5 : std::string sectionName = ASCEND_SHNAME_REGS + "." + std::to_string(ConvertCoreId(coreType, coreId));
185 5 : std::shared_ptr<RegisterInterface> reg = RegisterManager::GetInstance().GetRegister();
186 5 : IDE_CTRL_VALUE_FAILED(reg != nullptr, return, "Get register failed, null register.");
187 20 : for (const auto& regType : reg->GetRegisterTypes(coreType)) {
188 10 : DumpV4DebugRegister(coreType, coreId, regType, reg->GetRegisterTable(regType), regData);
189 : }
190 5 : DumpV4ErrorRegister(coreType, coreId, reg->GetErrorRegisterTable(), regData);
191 :
192 5 : size_t totalSize = regData.size() * sizeof(RegInfoWide);
193 5 : IDE_LOGI("coreType=%d, coreId=%d, register num=%zu", static_cast<int32_t>(coreType), coreId, regData.size());
194 5 : std::string data(reinterpret_cast<const char*>(regData.data()), totalSize);
195 5 : ELF::SectionPtr registerSection = coreFile_.AddSection(ASCEND_SHTYPE_REGS, sectionName);
196 5 : IDE_CTRL_VALUE_FAILED(registerSection != nullptr, return, "Create %s section failed.", sectionName.c_str());
197 5 : registerSection->SetData(data);
198 5 : registerSection->SetEntSize(sizeof(RegInfoWide));
199 5 : }
200 :
201 10 : void DumpCore::DumpV4DebugRegister(
202 : uint8_t coreType, uint16_t coreId, RegisterType regType, const std::vector<RegisterTable>& tables,
203 : std::vector<RegInfoWide>& regData) const
204 : {
205 10 : DumpDebugRegisterImpl(coreType, coreId, regType, tables, regData);
206 10 : }
207 :
208 5 : void DumpCore::DumpV4ErrorRegister(
209 : uint8_t coreType, uint16_t coreId, const std::vector<ErrorRegisterTable>& tables,
210 : std::vector<RegInfoWide>& regData) const
211 : {
212 5 : DumpErrorRegisterImpl(coreType, coreId, tables, regData);
213 5 : }
214 :
215 235 : uint16_t DumpCore::ConvertCoreId(uint8_t coreType, uint16_t coreId) const
216 : {
217 235 : auto* plat = CoredumpManager::Get();
218 235 : if (plat == nullptr) {
219 15 : IDE_LOGW("[DumpCore] Platform unavailable, coreId not converted.");
220 15 : return coreId;
221 : }
222 220 : return plat->ConvertCoreId(coreType, coreId);
223 : }
224 : } // namespace Adx
|