blob: e74e2c0ee007bd8f4d65be3ec3bd649d6e35e56b [file] [log] [blame]
Jayanth Othayoth4d779b22021-06-03 05:45:13 -05001extern "C" {
2#include <libpdbg.h>
3}
4
5#include "fapi_data_process.hpp"
6
7#include <attributes_info.H>
8#include <fmt/format.h>
Jayanth Othayoth417b88e2021-11-17 00:28:09 -06009#include <libphal.H>
10#include <phal_exception.H>
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050011
12#include <algorithm>
13#include <cstdlib>
14#include <cstring>
15#include <iomanip>
16#include <list>
17#include <map>
18#include <phosphor-logging/elog.hpp>
19#include <sstream>
20#include <string>
21
22namespace openpower
23{
24namespace pels
25{
26namespace phal
27{
28
29using namespace phosphor::logging;
Jayanth Othayoth417b88e2021-11-17 00:28:09 -060030using namespace openpower::phal::exception;
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050031
32/**
33 * Used to pass buffer to pdbg callback api to get required target
34 * data (attributes) based on given data (attribute).
35 */
36struct TargetInfo
37{
38 ATTR_PHYS_BIN_PATH_Type physBinPath;
39 ATTR_LOCATION_CODE_Type locationCode;
40 ATTR_PHYS_DEV_PATH_Type physDevPath;
41 ATTR_MRU_ID_Type mruId;
42
43 bool deconfigure;
44
45 TargetInfo()
46 {
47 memset(&physBinPath, '\0', sizeof(physBinPath));
48 memset(&locationCode, '\0', sizeof(locationCode));
49 memset(&physDevPath, '\0', sizeof(physDevPath));
50 mruId = 0;
51 deconfigure = false;
52 }
53};
54
55/**
56 * Used to return in callback function which are used to get
57 * physical path value and it binary format value.
58 *
59 * The value for constexpr defined based on pdbg_target_traverse function usage.
60 */
61constexpr int continueTgtTraversal = 0;
62constexpr int requireAttrFound = 1;
63constexpr int requireAttrNotFound = 2;
64
65/**
66 * @brief Used to get target location code from phal device tree
67 *
68 * @param[in] target current device tree target
69 * @param[out] appPrivData used for accessing|storing from|to application
70 *
71 * @return 0 to continue traverse, non-zero to stop traverse
72 */
73int pdbgCallbackToGetTgtReqAttrsVal(struct pdbg_target* target,
74 void* appPrivData)
75{
Jayanth Othayoth417b88e2021-11-17 00:28:09 -060076 using namespace openpower::phal::pdbg;
77
Jayanth Othayoth4d779b22021-06-03 05:45:13 -050078 TargetInfo* targetInfo = static_cast<TargetInfo*>(appPrivData);
79
80 ATTR_PHYS_BIN_PATH_Type physBinPath;
81 /**
82 * TODO: Issue: phal/pdata#16
83 * Should not use direct pdbg api to read attribute. Need to use DT_GET_PROP
84 * macro for bmc app's and this will call libdt-api api but, it will print
85 * "pdbg_target_get_attribute failed" trace if attribute is not found and
86 * this callback will call recursively by using pdbg_target_traverse() until
87 * find expected attribute based on return code from this callback. Because,
88 * need to do target iteration to get actual attribute (ATTR_PHYS_BIN_PATH)
89 * value when device tree target info doesn't know to read attribute from
90 * device tree. So, Due to this error trace user will get confusion while
91 * looking traces. Hence using pdbg api to avoid trace until libdt-api
92 * provides log level setup.
93 */
94 if (!pdbg_target_get_attribute(
95 target, "ATTR_PHYS_BIN_PATH",
96 std::stoi(dtAttr::fapi2::ATTR_PHYS_BIN_PATH_Spec),
97 dtAttr::fapi2::ATTR_PHYS_BIN_PATH_ElementCount, physBinPath))
98 {
99 return continueTgtTraversal;
100 }
101
102 if (std::memcmp(physBinPath, targetInfo->physBinPath,
103 sizeof(physBinPath)) != 0)
104 {
105 return continueTgtTraversal;
106 }
107
Jayanth Othayoth417b88e2021-11-17 00:28:09 -0600108 try
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500109 {
Jayanth Othayoth417b88e2021-11-17 00:28:09 -0600110 // Get location code information
111 openpower::phal::pdbg::getLocationCode(target,
112 targetInfo->locationCode);
113 }
114 catch (const std::exception& e)
115 {
116 // log message and continue with default data
117 log<level::ERR>(fmt::format("getLocationCode({}): Exception({})",
118 pdbg_target_path(target), e.what())
119 .c_str());
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500120 }
121
122 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, target, targetInfo->physDevPath))
123 {
124 log<level::ERR>("Could not read PHYS_DEV_PATH attribute");
125 return requireAttrNotFound;
126 }
127
128 if (DT_GET_PROP(ATTR_MRU_ID, target, targetInfo->mruId))
129 {
130 log<level::ERR>("Could not read MRU_ID attribute");
131 return requireAttrNotFound;
132 }
133
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500134 return requireAttrFound;
135}
136
137/**
138 * @brief Used to get target info (attributes data)
139 *
140 * To get target required attributes value using another attribute value
141 * ("PHYS_BIN_PATH" which is present in same target attributes list) by using
142 * "ipdbg_target_traverse" api because, here we have attribute value only and
143 * doesn't have respective device tree target info to get required attributes
144 * values from it attributes list.
145 *
146 * @param[in] physBinPath to pass PHYS_BIN_PATH value
147 * @param[out] targetInfo to pas buufer to fill with required attributes
148 *
149 * @return true on success otherwise false
150 */
151bool getTgtReqAttrsVal(const std::vector<uint8_t>& physBinPath,
152 TargetInfo& targetInfo)
153{
154 std::memcpy(&targetInfo.physBinPath, physBinPath.data(),
155 sizeof(targetInfo.physBinPath));
156
157 int ret = pdbg_target_traverse(NULL, pdbgCallbackToGetTgtReqAttrsVal,
158 &targetInfo);
159 if (ret == 0)
160 {
161 log<level::ERR>(fmt::format("Given ATTR_PHYS_BIN_PATH value({}) "
162 "not found in phal device tree",
163 targetInfo.physBinPath)
164 .c_str());
165 return false;
166 }
167 else if (ret == requireAttrNotFound)
168 {
169 return false;
170 }
171
172 return true;
173}
174
175/**
176 * @brief GET PEL priority from pHAL priority
177 *
178 * The pHAL callout priority is in different format than PEL format
179 * so, this api is used to return current phal supported priority into
180 * PEL expected format.
181 *
182 * @param[in] phalPriority used to pass phal priority format string
183 *
184 * @return pel priority format string else empty if failure
185 *
186 * @note For "NONE" returning "L" (LOW)
187 */
188static std::string getPelPriority(const std::string& phalPriority)
189{
190 const std::map<std::string, std::string> priorityMap = {
191 {"HIGH", "H"}, {"MEDIUM", "M"}, {"LOW", "L"}, {"NONE", "L"}};
192
193 auto it = priorityMap.find(phalPriority);
194 if (it == priorityMap.end())
195 {
196 log<level::ERR>(fmt::format("Unsupported phal priority({}) is given "
197 "to get pel priority format",
198 phalPriority)
199 .c_str());
200 return "H";
201 }
202
203 return it->second;
204}
205
206void convertFAPItoPELformat(FFDC& ffdc, json& pelJSONFmtCalloutDataList,
207 FFDCData& ffdcUserData)
208{
209 if (ffdc.ffdc_type == FFDC_TYPE_HWP)
210 {
211 // Adding hardware procedures return code details
212 ffdcUserData.emplace_back("HWP_RC", ffdc.hwp_errorinfo.rc);
213 ffdcUserData.emplace_back("HWP_RC_DESC", ffdc.hwp_errorinfo.rc_desc);
214
215 // Adding hardware procedures required ffdc data for debug
216 for_each(
217 ffdc.hwp_errorinfo.ffdcs_data.begin(),
218 ffdc.hwp_errorinfo.ffdcs_data.end(),
219 [&ffdcUserData](std::pair<std::string, std::string>& ele) -> void {
220 std::string keyWithPrefix("HWP_FFDC_");
221 keyWithPrefix.append(ele.first);
222
223 ffdcUserData.emplace_back(keyWithPrefix, ele.second);
224 });
225
226 // Adding hardware callout details
227 int calloutCount = 0;
228 for_each(
229 ffdc.hwp_errorinfo.hwcallouts.begin(),
230 ffdc.hwp_errorinfo.hwcallouts.end(),
231 [&ffdcUserData, &calloutCount,
232 &pelJSONFmtCalloutDataList](const HWCallout& hwCallout) -> void {
233 calloutCount++;
234 std::stringstream keyPrefix;
235 keyPrefix << "HWP_HW_CO_" << std::setfill('0') << std::setw(2)
236 << calloutCount << "_";
237
238 ffdcUserData.emplace_back(
239 std::string(keyPrefix.str()).append("HW_ID"),
240 hwCallout.hwid);
241
242 ffdcUserData.emplace_back(
243 std::string(keyPrefix.str()).append("PRIORITY"),
244 hwCallout.callout_priority);
245
246 phal::TargetInfo targetInfo;
247 phal::getTgtReqAttrsVal(hwCallout.target_entity_path,
248 targetInfo);
249
250 std::string locationCode = std::string(targetInfo.locationCode);
251 ffdcUserData.emplace_back(
252 std::string(keyPrefix.str()).append("LOC_CODE"),
253 locationCode);
254
255 std::string physPath = std::string(targetInfo.physDevPath);
256 ffdcUserData.emplace_back(
257 std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);
258
259 ffdcUserData.emplace_back(
260 std::string(keyPrefix.str()).append("CLK_POS"),
261 std::to_string(hwCallout.clkPos));
262
263 json jsonCalloutData;
264 jsonCalloutData["LocationCode"] = locationCode;
265 std::string pelPriority =
266 getPelPriority(hwCallout.callout_priority);
267 jsonCalloutData["Priority"] = pelPriority;
268
269 if (targetInfo.mruId != 0)
270 {
271 jsonCalloutData["MRUs"] = json::array({
272 {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
273 });
274 }
275
276 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
277 });
278
279 // Adding CDG (callout, deconfigure and guard) targets details
280 calloutCount = 0;
281 for_each(
282 ffdc.hwp_errorinfo.cdg_targets.begin(),
283 ffdc.hwp_errorinfo.cdg_targets.end(),
284 [&ffdcUserData, &calloutCount,
285 &pelJSONFmtCalloutDataList](const CDG_Target& cdg_tgt) -> void {
286 calloutCount++;
287 std::stringstream keyPrefix;
288 keyPrefix << "HWP_CDG_TGT_" << std::setfill('0') << std::setw(2)
289 << calloutCount << "_";
290
291 phal::TargetInfo targetInfo;
292 targetInfo.deconfigure = cdg_tgt.deconfigure;
293
294 phal::getTgtReqAttrsVal(cdg_tgt.target_entity_path, targetInfo);
295
296 std::string locationCode = std::string(targetInfo.locationCode);
297 ffdcUserData.emplace_back(
298 std::string(keyPrefix.str()).append("LOC_CODE"),
299 locationCode);
300 std::string physPath = std::string(targetInfo.physDevPath);
301 ffdcUserData.emplace_back(
302 std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);
303
304 ffdcUserData.emplace_back(
305 std::string(keyPrefix.str()).append("CO_REQ"),
306 (cdg_tgt.callout == true ? "true" : "false"));
307
308 ffdcUserData.emplace_back(
309 std::string(keyPrefix.str()).append("CO_PRIORITY"),
310 cdg_tgt.callout_priority);
311
312 ffdcUserData.emplace_back(
313 std::string(keyPrefix.str()).append("DECONF_REQ"),
314 (cdg_tgt.deconfigure == true ? "true" : "false"));
315
316 ffdcUserData.emplace_back(
317 std::string(keyPrefix.str()).append("GUARD_REQ"),
318 (cdg_tgt.guard == true ? "true" : "false"));
319
320 ffdcUserData.emplace_back(
321 std::string(keyPrefix.str()).append("GUARD_TYPE"),
322 cdg_tgt.guard_type);
323
324 json jsonCalloutData;
325 jsonCalloutData["LocationCode"] = locationCode;
326 std::string pelPriority =
327 getPelPriority(cdg_tgt.callout_priority);
328 jsonCalloutData["Priority"] = pelPriority;
329
330 if (targetInfo.mruId != 0)
331 {
332 jsonCalloutData["MRUs"] = json::array({
333 {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
334 });
335 }
336 jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
337 jsonCalloutData["Guarded"] = cdg_tgt.guard;
Jayanth Othayoth95205eb2021-11-08 06:21:30 -0600338 jsonCalloutData["GuardType"] = cdg_tgt.guard_type;
339 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500340
341 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
342 });
343 }
344 else if ((ffdc.ffdc_type != FFDC_TYPE_NONE) &&
345 (ffdc.ffdc_type != FFDC_TYPE_UNSUPPORTED))
346 {
347 log<level::ERR>(fmt::format("Unsupported phal FFDC type to create PEL. "
348 "MSG: {}",
349 ffdc.message)
350 .c_str());
351 }
352}
353
354} // namespace phal
355} // namespace pels
356} // namespace openpower