blob: ad2957cd0f4524f90745f36ea6aacfbe62c41e9f [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 Othayoth363ac762021-11-17 00:38:24 -0600108 // Found Target, now collect the required attributes associated to the
109 // target. Incase of any attribute read failure, initialize the data with
110 // default value.
111
Jayanth Othayoth417b88e2021-11-17 00:28:09 -0600112 try
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500113 {
Jayanth Othayoth417b88e2021-11-17 00:28:09 -0600114 // Get location code information
115 openpower::phal::pdbg::getLocationCode(target,
116 targetInfo->locationCode);
117 }
118 catch (const std::exception& e)
119 {
120 // log message and continue with default data
121 log<level::ERR>(fmt::format("getLocationCode({}): Exception({})",
122 pdbg_target_path(target), e.what())
123 .c_str());
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500124 }
125
126 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, target, targetInfo->physDevPath))
127 {
Jayanth Othayoth363ac762021-11-17 00:38:24 -0600128 log<level::ERR>(
129 fmt::format("Could not read({}) PHYS_DEV_PATH attribute",
130 pdbg_target_path(target))
131 .c_str());
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500132 }
133
134 if (DT_GET_PROP(ATTR_MRU_ID, target, targetInfo->mruId))
135 {
Jayanth Othayoth363ac762021-11-17 00:38:24 -0600136 log<level::ERR>(fmt::format("Could not read({}) ATTR_MRU_ID attribute",
137 pdbg_target_path(target))
138 .c_str());
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500139 }
140
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500141 return requireAttrFound;
142}
143
144/**
145 * @brief Used to get target info (attributes data)
146 *
147 * To get target required attributes value using another attribute value
148 * ("PHYS_BIN_PATH" which is present in same target attributes list) by using
149 * "ipdbg_target_traverse" api because, here we have attribute value only and
150 * doesn't have respective device tree target info to get required attributes
151 * values from it attributes list.
152 *
153 * @param[in] physBinPath to pass PHYS_BIN_PATH value
154 * @param[out] targetInfo to pas buufer to fill with required attributes
155 *
156 * @return true on success otherwise false
157 */
158bool getTgtReqAttrsVal(const std::vector<uint8_t>& physBinPath,
159 TargetInfo& targetInfo)
160{
161 std::memcpy(&targetInfo.physBinPath, physBinPath.data(),
162 sizeof(targetInfo.physBinPath));
163
164 int ret = pdbg_target_traverse(NULL, pdbgCallbackToGetTgtReqAttrsVal,
165 &targetInfo);
166 if (ret == 0)
167 {
168 log<level::ERR>(fmt::format("Given ATTR_PHYS_BIN_PATH value({}) "
169 "not found in phal device tree",
170 targetInfo.physBinPath)
171 .c_str());
172 return false;
173 }
174 else if (ret == requireAttrNotFound)
175 {
176 return false;
177 }
178
179 return true;
180}
181
182/**
183 * @brief GET PEL priority from pHAL priority
184 *
185 * The pHAL callout priority is in different format than PEL format
186 * so, this api is used to return current phal supported priority into
187 * PEL expected format.
188 *
189 * @param[in] phalPriority used to pass phal priority format string
190 *
191 * @return pel priority format string else empty if failure
192 *
193 * @note For "NONE" returning "L" (LOW)
194 */
195static std::string getPelPriority(const std::string& phalPriority)
196{
197 const std::map<std::string, std::string> priorityMap = {
198 {"HIGH", "H"}, {"MEDIUM", "M"}, {"LOW", "L"}, {"NONE", "L"}};
199
200 auto it = priorityMap.find(phalPriority);
201 if (it == priorityMap.end())
202 {
203 log<level::ERR>(fmt::format("Unsupported phal priority({}) is given "
204 "to get pel priority format",
205 phalPriority)
206 .c_str());
207 return "H";
208 }
209
210 return it->second;
211}
212
213void convertFAPItoPELformat(FFDC& ffdc, json& pelJSONFmtCalloutDataList,
214 FFDCData& ffdcUserData)
215{
216 if (ffdc.ffdc_type == FFDC_TYPE_HWP)
217 {
218 // Adding hardware procedures return code details
219 ffdcUserData.emplace_back("HWP_RC", ffdc.hwp_errorinfo.rc);
220 ffdcUserData.emplace_back("HWP_RC_DESC", ffdc.hwp_errorinfo.rc_desc);
221
222 // Adding hardware procedures required ffdc data for debug
223 for_each(
224 ffdc.hwp_errorinfo.ffdcs_data.begin(),
225 ffdc.hwp_errorinfo.ffdcs_data.end(),
226 [&ffdcUserData](std::pair<std::string, std::string>& ele) -> void {
227 std::string keyWithPrefix("HWP_FFDC_");
228 keyWithPrefix.append(ele.first);
229
230 ffdcUserData.emplace_back(keyWithPrefix, ele.second);
231 });
232
233 // Adding hardware callout details
234 int calloutCount = 0;
235 for_each(
236 ffdc.hwp_errorinfo.hwcallouts.begin(),
237 ffdc.hwp_errorinfo.hwcallouts.end(),
238 [&ffdcUserData, &calloutCount,
239 &pelJSONFmtCalloutDataList](const HWCallout& hwCallout) -> void {
240 calloutCount++;
241 std::stringstream keyPrefix;
242 keyPrefix << "HWP_HW_CO_" << std::setfill('0') << std::setw(2)
243 << calloutCount << "_";
244
245 ffdcUserData.emplace_back(
246 std::string(keyPrefix.str()).append("HW_ID"),
247 hwCallout.hwid);
248
249 ffdcUserData.emplace_back(
250 std::string(keyPrefix.str()).append("PRIORITY"),
251 hwCallout.callout_priority);
252
253 phal::TargetInfo targetInfo;
254 phal::getTgtReqAttrsVal(hwCallout.target_entity_path,
255 targetInfo);
256
257 std::string locationCode = std::string(targetInfo.locationCode);
258 ffdcUserData.emplace_back(
259 std::string(keyPrefix.str()).append("LOC_CODE"),
260 locationCode);
261
262 std::string physPath = std::string(targetInfo.physDevPath);
263 ffdcUserData.emplace_back(
264 std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);
265
266 ffdcUserData.emplace_back(
267 std::string(keyPrefix.str()).append("CLK_POS"),
268 std::to_string(hwCallout.clkPos));
269
270 json jsonCalloutData;
271 jsonCalloutData["LocationCode"] = locationCode;
272 std::string pelPriority =
273 getPelPriority(hwCallout.callout_priority);
274 jsonCalloutData["Priority"] = pelPriority;
275
276 if (targetInfo.mruId != 0)
277 {
278 jsonCalloutData["MRUs"] = json::array({
279 {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
280 });
281 }
282
283 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
284 });
285
286 // Adding CDG (callout, deconfigure and guard) targets details
287 calloutCount = 0;
288 for_each(
289 ffdc.hwp_errorinfo.cdg_targets.begin(),
290 ffdc.hwp_errorinfo.cdg_targets.end(),
291 [&ffdcUserData, &calloutCount,
292 &pelJSONFmtCalloutDataList](const CDG_Target& cdg_tgt) -> void {
293 calloutCount++;
294 std::stringstream keyPrefix;
295 keyPrefix << "HWP_CDG_TGT_" << std::setfill('0') << std::setw(2)
296 << calloutCount << "_";
297
298 phal::TargetInfo targetInfo;
299 targetInfo.deconfigure = cdg_tgt.deconfigure;
300
301 phal::getTgtReqAttrsVal(cdg_tgt.target_entity_path, targetInfo);
302
303 std::string locationCode = std::string(targetInfo.locationCode);
304 ffdcUserData.emplace_back(
305 std::string(keyPrefix.str()).append("LOC_CODE"),
306 locationCode);
307 std::string physPath = std::string(targetInfo.physDevPath);
308 ffdcUserData.emplace_back(
309 std::string(keyPrefix.str()).append("PHYS_PATH"), physPath);
310
311 ffdcUserData.emplace_back(
312 std::string(keyPrefix.str()).append("CO_REQ"),
313 (cdg_tgt.callout == true ? "true" : "false"));
314
315 ffdcUserData.emplace_back(
316 std::string(keyPrefix.str()).append("CO_PRIORITY"),
317 cdg_tgt.callout_priority);
318
319 ffdcUserData.emplace_back(
320 std::string(keyPrefix.str()).append("DECONF_REQ"),
321 (cdg_tgt.deconfigure == true ? "true" : "false"));
322
323 ffdcUserData.emplace_back(
324 std::string(keyPrefix.str()).append("GUARD_REQ"),
325 (cdg_tgt.guard == true ? "true" : "false"));
326
327 ffdcUserData.emplace_back(
328 std::string(keyPrefix.str()).append("GUARD_TYPE"),
329 cdg_tgt.guard_type);
330
331 json jsonCalloutData;
332 jsonCalloutData["LocationCode"] = locationCode;
333 std::string pelPriority =
334 getPelPriority(cdg_tgt.callout_priority);
335 jsonCalloutData["Priority"] = pelPriority;
336
337 if (targetInfo.mruId != 0)
338 {
339 jsonCalloutData["MRUs"] = json::array({
340 {{"ID", targetInfo.mruId}, {"Priority", pelPriority}},
341 });
342 }
343 jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
344 jsonCalloutData["Guarded"] = cdg_tgt.guard;
Jayanth Othayoth95205eb2021-11-08 06:21:30 -0600345 jsonCalloutData["GuardType"] = cdg_tgt.guard_type;
346 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
Jayanth Othayoth4d779b22021-06-03 05:45:13 -0500347
348 pelJSONFmtCalloutDataList.emplace_back(jsonCalloutData);
349 });
350 }
351 else if ((ffdc.ffdc_type != FFDC_TYPE_NONE) &&
352 (ffdc.ffdc_type != FFDC_TYPE_UNSUPPORTED))
353 {
354 log<level::ERR>(fmt::format("Unsupported phal FFDC type to create PEL. "
355 "MSG: {}",
356 ffdc.message)
357 .c_str());
358 }
359}
360
361} // namespace phal
362} // namespace pels
363} // namespace openpower