blob: 8d420bfe10fe845d0df5bb9c8beed658af3857f6 [file] [log] [blame]
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -05001/**
2 * Copyright © 2021 IBM Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Patrick Williams2544b412022-10-04 08:41:06 -050017extern "C"
18{
Jayanth Othayoth66e186d2021-06-15 22:44:35 -050019#include <libpdbg.h>
20}
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050021
Jayanth Othayothc74c2202021-06-04 06:42:43 -050022#include "fapi_data_process.hpp"
23#include "pel.hpp"
Jayanth Othayoth66e186d2021-06-15 22:44:35 -050024#include "sbe_ffdc_handler.hpp"
Jayanth Othayothc74c2202021-06-04 06:42:43 -050025#include "temporary_file.hpp"
26
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050027#include <ekb/hwpf/fapi2/include/return_code_defs.H>
devenraoda876612024-02-16 18:48:27 +053028#include <ekb/hwpf/fapi2/include/target_types.H>
Jayanth Othayotheff307e2021-07-15 03:27:01 -050029#include <libekb.H>
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050030
31#include <phosphor-logging/log.hpp>
32
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -050033#include <format>
Patrick Williams2544b412022-10-04 08:41:06 -050034#include <new>
35
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050036namespace openpower
37{
38namespace pels
39{
40namespace sbe
41{
42
devenraob5693742024-02-16 18:33:32 +053043constexpr uint32_t sbeMaxFfdcPackets = 20;
devenraoda876612024-02-16 18:48:27 +053044constexpr uint16_t p10FfdcMagicCode = 0xFFDC;
45constexpr uint16_t pozFfdcMagicCode = 0xFBAD;
46constexpr uint16_t p10FfdcSkipWords = 2;
47constexpr uint16_t pozFfdcSkipWords = 3;
devenraob5693742024-02-16 18:33:32 +053048
devenraoda876612024-02-16 18:48:27 +053049struct p10FfdcHeader
devenraob5693742024-02-16 18:33:32 +053050{
51 uint32_t magic_bytes:16;
52 uint32_t lengthinWords:16;
53 uint32_t seqId:16;
54 uint32_t cmdClass:8;
55 uint32_t cmd:8;
56 uint32_t fapiRc;
devenraoda876612024-02-16 18:48:27 +053057} __attribute__((packed));
58
59struct pozFfdcHeader
60{
61 uint32_t magicByte:16;
62 uint32_t lengthinWords:16;
63 uint32_t seqId:16;
64 uint32_t cmdClass:8;
65 uint32_t cmd:8;
66 uint32_t slid:16;
67 uint32_t severity:8;
68 uint32_t chipId:8;
69 uint32_t fapiRc;
70} __attribute__((packed));
71
72using namespace phosphor::logging;
devenraob5693742024-02-16 18:33:32 +053073
Jayanth Othayoth742b00b2022-06-30 05:16:57 -050074SbeFFDC::SbeFFDC(const AdditionalData& aData, const PelFFDC& files) :
devenraoda876612024-02-16 18:48:27 +053075 ffdcType(FFDC_TYPE_NONE), chipType(fapi2::TARGET_TYPE_PROC_CHIP)
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050076{
77 log<level::INFO>("SBE FFDC processing requested");
78
79 // SRC6 field in the additional data contains Processor position
80 // associated to the SBE FFDC
81 //"[0:15] chip position"
82 auto src6 = aData.getValue("SRC6");
83 if (src6 == std::nullopt)
84 {
85 log<level::ERR>("Fail to extract SRC6 data: failing to get proc index");
86 return;
87 }
88 try
89 {
devenraoda876612024-02-16 18:48:27 +053090 chipPos = (std::stoi(src6.value()) & 0xFFFF0000) >> 16;
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050091 }
Patrick Williams66491c62021-10-06 12:23:37 -050092 catch (const std::exception& err)
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050093 {
94 log<level::ERR>(
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -050095 std::format("Conversion failure errormsg({})", err.what()).c_str());
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050096 return;
97 }
devenraoda876612024-02-16 18:48:27 +053098 auto type = aData.getValue("CHIP_TYPE");
99 if (type != std::nullopt)
100 {
101 try
102 {
103 chipType = std::stoi(type.value());
104 }
105 catch (const std::exception& err)
106 {
107 log<level::ERR>(
108 std::format("Conversion failure errormsg({})", err.what())
109 .c_str());
110 return;
111 }
112 }
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -0500113
114 if (files.empty())
115 {
116 log<level::INFO>("SbeFFDC : No files found, skipping ffdc processing");
117 return;
118 }
119
120 for (const auto& file : files)
121 {
122 if ((file.format == UserDataFormat::custom) &&
123 (file.subType == sbeFFDCSubType))
124 {
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500125 // Process SBE file.
126 parse(file.fd);
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -0500127 }
128 }
129}
130
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500131void SbeFFDC::parse(int fd)
132{
133 log<level::INFO>(
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500134 std::format("SBE FFDC file fd:({}), parsing started", fd).c_str());
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500135
136 uint32_t ffdcBufOffset = 0;
137 uint32_t pktCount = 0;
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500138
139 // get SBE FFDC data.
140 auto ffdcData = util::readFD(fd);
141 if (ffdcData.empty())
142 {
143 log<level::ERR>(
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500144 std::format("Empty SBE FFDC file fd:({}), skipping", fd).c_str());
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500145 return;
146 }
147
148 while ((ffdcBufOffset < ffdcData.size()) && (sbeMaxFfdcPackets != pktCount))
149 {
devenraoc1a0ff82024-02-16 18:36:20 +0530150 sbeFfdcPacketType ffdcPkt;
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500151 // Next un-extracted FFDC Packet
devenraoda876612024-02-16 18:48:27 +0530152 uint16_t magicBytes =
153 *(reinterpret_cast<uint16_t*>(ffdcData.data() + ffdcBufOffset));
154 magicBytes = ntohs(magicBytes);
155 uint32_t pktLenWords = 0;
156 uint16_t lenWords = 0;
157 if (magicBytes == p10FfdcMagicCode)
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500158 {
devenraoda876612024-02-16 18:48:27 +0530159 p10FfdcHeader* ffdc = reinterpret_cast<p10FfdcHeader*>(
160 ffdcData.data() + ffdcBufOffset);
161 lenWords = ntohs(ffdc->lengthinWords);
162 auto fapiRc = ntohl(ffdc->fapiRc);
163
164 auto msg =
165 std::format("P10 FFDC magic: {} length in words:{} Fapirc:{}",
166 magicBytes, lenWords, fapiRc);
167 log<level::INFO>(msg.c_str());
168
169 ffdcPkt.fapiRc = fapiRc;
170 // Not interested in the first 2 words (these are not ffdc)
171 pktLenWords = lenWords - p10FfdcSkipWords;
172 ffdcPkt.ffdcLengthInWords = pktLenWords;
173 if (pktLenWords)
174 {
175 ffdcPkt.ffdcData = new uint32_t[pktLenWords];
176 memcpy(ffdcPkt.ffdcData,
177 ((reinterpret_cast<uint32_t*>(ffdc)) + p10FfdcSkipWords),
178 (pktLenWords * sizeof(uint32_t)));
179 }
180 else
181 {
182 log<level::ERR>("FFDC packet size is zero skipping");
183 return;
184 }
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500185 }
devenraoda876612024-02-16 18:48:27 +0530186 else if (magicBytes == pozFfdcMagicCode)
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500187 {
devenraoda876612024-02-16 18:48:27 +0530188 pozFfdcHeader* ffdc = reinterpret_cast<pozFfdcHeader*>(
189 ffdcData.data() + ffdcBufOffset);
190 lenWords = ntohs(ffdc->lengthinWords);
191 auto fapiRc = ntohl(ffdc->fapiRc);
192
193 auto msg =
194 std::format("P0Z FFDC magic: {} length in words:{} Fapirc:{}",
195 magicBytes, lenWords, fapiRc);
196 log<level::INFO>(msg.c_str());
197
198 ffdcPkt.fapiRc = fapiRc;
199 // Not interested in the first 3 words (these are not ffdc)
200 pktLenWords = lenWords - pozFfdcSkipWords;
201 ffdcPkt.ffdcLengthInWords = pktLenWords;
202 if (pktLenWords)
203 {
204 ffdcPkt.ffdcData = new uint32_t[pktLenWords];
205 memcpy(ffdcPkt.ffdcData,
206 ((reinterpret_cast<uint32_t*>(ffdc)) + pozFfdcSkipWords),
207 (pktLenWords * sizeof(uint32_t)));
208 }
209 else
210 {
211 log<level::ERR>("FFDC packet size is zero skipping");
212 return;
213 }
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500214 }
215 else
216 {
devenraoda876612024-02-16 18:48:27 +0530217 log<level::ERR>("Invalid FFDC magic code in Header: Skipping ");
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500218 return;
219 }
220
221 // SBE FFDC processing is not required for SBE Plat errors RCs.
222 // Plat errors processing is driven by SBE provided user data
223 // plugins, which need to link with PEL tool infrastructure.
224 if (ffdcPkt.fapiRc != fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA)
225 {
226 process(ffdcPkt);
227 }
Jayanth Othayothfb9b8112021-10-07 04:10:18 -0500228 else
229 {
230 log<level::INFO>("SBE FFDC: Internal FFDC packet");
231 }
232
233 // Update Buffer offset in Bytes
234 ffdcBufOffset += lenWords * sizeof(uint32_t);
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500235 ++pktCount;
236 }
237 if (pktCount == sbeMaxFfdcPackets)
238 {
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500239 log<level::ERR>(std::format("Received more than the limit of ({})"
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500240 " FFDC packets, processing only ({})",
241 sbeMaxFfdcPackets, pktCount)
242 .c_str());
243 }
244}
245
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500246void SbeFFDC::process(const sbeFfdcPacketType& ffdcPkt)
247{
248 using json = nlohmann::json;
249
250 // formated FFDC data structure after FFDC packet processing
251 FFDC ffdc;
252
Jayanth Othayoth66e186d2021-06-15 22:44:35 -0500253 if (!pdbg_targets_init(NULL))
254 {
255 log<level::ERR>("pdbg_targets_init failed, skipping ffdc processing");
256 return;
257 }
258
Jayanth Othayotheff307e2021-07-15 03:27:01 -0500259 if (libekb_init())
260 {
261 log<level::ERR>("libekb_init failed, skipping ffdc processing");
262 return;
263 }
264
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500265 try
266 {
267 // libekb provided wrapper function to convert SBE FFDC
268 // in to known ffdc structure.
devenraoda876612024-02-16 18:48:27 +0530269 libekb_get_sbe_ffdc(ffdc, ffdcPkt, chipPos, chipType);
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500270 }
271 catch (...)
272 {
273 log<level::ERR>("libekb_get_sbe_ffdc failed, skipping ffdc processing");
274 return;
275 }
276
Jayanth Othayoth742b00b2022-06-30 05:16:57 -0500277 // update FFDC type class membeir for hwp specific packet
278 // Assumption SBE FFDC contains only one hwp FFDC packet.
279 ffdcType = ffdc.ffdc_type;
280
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500281 // To store callouts details in json format as per pel expectation.
282 json pelJSONFmtCalloutDataList;
283 pelJSONFmtCalloutDataList = json::array();
284
285 // To store other user data from FFDC.
286 openpower::pels::phal::FFDCData ffdcUserData;
287
288 // Get FFDC and required info to include in PEL
289 openpower::pels::phal::convertFAPItoPELformat(
290 ffdc, pelJSONFmtCalloutDataList, ffdcUserData);
291
292 // Get callout information and sore in to file.
293 auto calloutData = pelJSONFmtCalloutDataList.dump();
294 util::TemporaryFile ffdcFile(calloutData.c_str(), calloutData.size());
295
296 // Create json callout type pel FFDC file structre.
297 PelFFDCfile pf;
298 pf.format = openpower::pels::UserDataFormat::json;
299 pf.subType = openpower::pels::jsonCalloutSubtype;
300 pf.version = 0x01;
301 pf.fd = ffdcFile.getFd();
302 ffdcFiles.push_back(pf);
303
304 // save the file path to delete the file after usage.
Matt Spinler8c7bb862023-08-31 14:32:22 -0500305 paths.emplace_back(ffdcFile.getPath(), pf.fd);
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500306
307 // Format ffdc user data and create new file.
308 std::string data;
309 for (auto& d : ffdcUserData)
310 {
311 data += d.first + " = " + d.second + "\n";
312 }
313 util::TemporaryFile pelDataFile(data.c_str(), data.size());
314 PelFFDCfile pdf;
315 pdf.format = openpower::pels::UserDataFormat::text;
316 pdf.version = 0x01;
317 pdf.fd = pelDataFile.getFd();
Matt Spinlerbe952d22022-07-01 11:30:11 -0500318 pdf.subType = 0;
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500319 ffdcFiles.push_back(pdf);
320
Matt Spinler8c7bb862023-08-31 14:32:22 -0500321 paths.emplace_back(pelDataFile.getPath(), pdf.fd);
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500322}
323
Jayanth Othayoth742b00b2022-06-30 05:16:57 -0500324std::optional<LogSeverity> SbeFFDC::getSeverity()
325{
326 if (ffdcType == FFDC_TYPE_SPARE_CLOCK_INFO)
327 {
328 log<level::INFO>(
329 "Found spare clock error, changing severity to informational");
330 return LogSeverity::Informational;
331 }
332 return std::nullopt;
333}
334
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -0500335} // namespace sbe
336} // namespace pels
337} // namespace openpower