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, std::vector<uint8_t>& data) const
44 : {
45 18044 : data.resize(table.num * table.byteWidth);
46 : rtDebugMemoryType_t memType;
47 18044 : if (regType == RegisterType::AIC || regType == RegisterType::AIV) {
48 512 : memType = RT_MEM_TYPE_REGISTER_DIRECT;
49 17532 : } else if (regType == RegisterType::AIC_DBG || regType == RegisterType::AIV_DBG) {
50 17532 : memType = RT_MEM_TYPE_REGISTER;
51 : } else {
52 0 : IDE_LOGE(
53 : "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, std::vector<T>& regData) const
75 : {
76 177 : std::stringstream ss;
77 18221 : for (const RegisterTable& table : tables) {
78 18044 : std::vector<uint8_t> data;
79 18044 : bool dataValid = DumpReadDebugAICoreRegister(coreType, coreId, regType, table, data);
80 18044 : errno_t err = EOK;
81 18044 : const uint8_t* dataPtr = data.data();
82 345915 : for (uint32_t i = 0; i < table.num; ++i) {
83 327871 : T regInfo{table.startAddr + i, REG_DATA_VALID, {0}, table.byteWidth, {0}};
84 327871 : if (dataValid) {
85 41375 : err = memcpy_s(®Info.value, sizeof(regInfo.value), dataPtr, table.byteWidth);
86 41375 : if (err != EOK) {
87 20464 : IDE_LOGE("Failed to copy debug register data from cache buffer. "
88 : "coreType: %hhu, coreId: %hu, addr: 0x%llx, ret: %d",
89 : coreType, coreId, regInfo.addr, err);
90 20464 : regInfo.validFlag = REG_DATA_INVALID;
91 : }
92 : } else {
93 286496 : regInfo.validFlag = REG_DATA_INVALID;
94 : }
95 327871 : dataPtr += table.byteWidth;
96 327871 : regData.emplace_back(regInfo);
97 : }
98 : }
99 177 : std::string dataStr = ss.str();
100 177 : if (!dataStr.empty()) {
101 0 : IDE_LOGW("Debug register data. coreType=%d, coreId=%d.%s",
102 : static_cast<int32_t>(coreType), coreId, dataStr.c_str());
103 : }
104 177 : }
105 :
106 : template <typename T>
107 85 : void DumpCore::DumpErrorRegisterImpl(
108 : uint8_t coreType, uint16_t coreId, const std::vector<ErrorRegisterTable>& tables, std::vector<T>& regData) const
109 : {
110 85 : std::stringstream ss;
111 85 : std::vector<std::string> regLogs;
112 170 : for (uint32_t i = 0; i < exceptionRegInfo_.coreNum; i++) {
113 85 : rtExceptionErrRegInfo_t core = exceptionRegInfo_.errRegInfo[i];
114 85 : if (coreId != core.coreId || coreType != core.coreType) {
115 68 : continue;
116 : }
117 548 : for (const auto& table : tables) {
118 531 : T regInfo{table.offsetAddr, REG_DATA_VALID, {0}, table.byteWidth, {0}};
119 531 : errno_t err = memcpy_s(®Info.value, sizeof(regInfo.value), core.errReg + table.errIndex, table.byteWidth);
120 531 : if (err != EOK) {
121 480 : IDE_LOGE("Failed to copy error register data from exception args. "
122 : "coreType: %hhu, coreId: %hu, addr: 0x%llx, ret: %d",
123 : coreType, coreId, regInfo.addr, err);
124 480 : regInfo.validFlag = REG_DATA_INVALID;
125 : } else {
126 51 : std::string value = FormatRegisterData(regInfo.value, regInfo.regSize);
127 51 : ss << table.name << "[0x" << std::hex << regInfo.addr << "]: " << value << ",";
128 51 : }
129 531 : regData.emplace_back(regInfo);
130 : }
131 : }
132 85 : std::string dataStr = ss.str();
133 85 : if (!dataStr.empty()) {
134 2 : IDE_LOGW("Error register data. coreType=%d, coreId=%d. %s",
135 : static_cast<int32_t>(coreType), coreId, dataStr.c_str());
136 : }
137 85 : }
138 :
139 80 : void DumpCore::DumpV2Register(uint8_t coreType, uint16_t coreId)
140 : {
141 80 : std::vector<RegInfo> regData;
142 80 : std::string sectionName = ASCEND_SHNAME_REGS + "." + std::to_string(ConvertCoreId(coreType, coreId));
143 80 : std::shared_ptr<RegisterInterface> reg = RegisterManager::GetInstance().GetRegister();
144 80 : IDE_CTRL_VALUE_FAILED(reg != nullptr, return, "Get register failed, null register.");
145 247 : for (const auto& regType : reg->GetRegisterTypes(coreType)) {
146 167 : DumpV2DebugRegister(coreType, coreId, reg->GetRegisterTable(regType), regData);
147 : }
148 80 : DumpV2ErrorRegister(coreType, coreId, reg->GetErrorRegisterTable(), regData);
149 :
150 80 : size_t totalSize = regData.size() * sizeof(RegInfo);
151 80 : std::string data(reinterpret_cast<const char*>(regData.data()), totalSize);
152 80 : ELF::SectionPtr registerSection = coreFile_.AddSection(ASCEND_SHTYPE_REGS, sectionName);
153 80 : IDE_CTRL_VALUE_FAILED(registerSection != nullptr, return, "Create %s section failed.", sectionName.c_str());
154 80 : registerSection->SetData(data);
155 80 : registerSection->SetEntSize(sizeof(RegInfo));
156 80 : }
157 :
158 167 : void DumpCore::DumpV2DebugRegister(
159 : uint8_t coreType, uint16_t coreId, const std::vector<RegisterTable>& tables, std::vector<RegInfo>& regData) const
160 : {
161 : RegisterType regType;
162 167 : if (coreType == CORE_TYPE_AIC) {
163 68 : regType = RegisterType::AIC_DBG;
164 : } else {
165 99 : regType = RegisterType::AIV_DBG;
166 : }
167 167 : DumpDebugRegisterImpl(coreType, coreId, regType, tables, regData);
168 167 : }
169 :
170 80 : void DumpCore::DumpV2ErrorRegister(
171 : uint8_t coreType, uint16_t coreId, const std::vector<ErrorRegisterTable>& tables,
172 : std::vector<RegInfo>& regData) const
173 : {
174 80 : DumpErrorRegisterImpl(coreType, coreId, tables, regData);
175 80 : }
176 :
177 5 : void DumpCore::DumpV4Register(uint8_t coreType, uint16_t coreId)
178 : {
179 5 : std::vector<RegInfoWide> regData;
180 5 : std::string sectionName = ASCEND_SHNAME_REGS + "." + std::to_string(ConvertCoreId(coreType, coreId));
181 5 : std::shared_ptr<RegisterInterface> reg = RegisterManager::GetInstance().GetRegister();
182 5 : IDE_CTRL_VALUE_FAILED(reg != nullptr, return, "Get register failed, null register.");
183 15 : for (const auto& regType : reg->GetRegisterTypes(coreType)) {
184 10 : DumpV4DebugRegister(coreType, coreId, regType, reg->GetRegisterTable(regType), regData);
185 : }
186 5 : DumpV4ErrorRegister(coreType, coreId, reg->GetErrorRegisterTable(), regData);
187 :
188 5 : size_t totalSize = regData.size() * sizeof(RegInfoWide);
189 5 : IDE_LOGI("coreType=%d, coreId=%d, register num=%zu", static_cast<int32_t>(coreType), coreId, regData.size());
190 5 : std::string data(reinterpret_cast<const char*>(regData.data()), totalSize);
191 5 : ELF::SectionPtr registerSection = coreFile_.AddSection(ASCEND_SHTYPE_REGS, sectionName);
192 5 : IDE_CTRL_VALUE_FAILED(registerSection != nullptr, return, "Create %s section failed.", sectionName.c_str());
193 5 : registerSection->SetData(data);
194 5 : registerSection->SetEntSize(sizeof(RegInfoWide));
195 5 : }
196 :
197 10 : void DumpCore::DumpV4DebugRegister(
198 : uint8_t coreType, uint16_t coreId, RegisterType regType, const std::vector<RegisterTable>& tables,
199 : std::vector<RegInfoWide>& regData) const
200 : {
201 10 : DumpDebugRegisterImpl(coreType, coreId, regType, tables, regData);
202 10 : }
203 :
204 5 : void DumpCore::DumpV4ErrorRegister(
205 : uint8_t coreType, uint16_t coreId, const std::vector<ErrorRegisterTable>& tables,
206 : std::vector<RegInfoWide>& regData) const
207 : {
208 5 : DumpErrorRegisterImpl(coreType, coreId, tables, regData);
209 5 : }
210 :
211 235 : uint16_t DumpCore::ConvertCoreId(uint8_t coreType, uint16_t coreId) const
212 : {
213 235 : auto *plat = CoredumpManager::Get();
214 235 : if (plat == nullptr) {
215 15 : IDE_LOGW("[DumpCore] Platform unavailable, coreId not converted.");
216 15 : return coreId;
217 : }
218 220 : return plat->ConvertCoreId(coreType, coreId);
219 : }
220 : } // namespace Adx
|