1e8bdeeaaSJayanth Othayoth /**
2e8bdeeaaSJayanth Othayoth * Copyright © 2021 IBM Corporation
3e8bdeeaaSJayanth Othayoth *
4e8bdeeaaSJayanth Othayoth * Licensed under the Apache License, Version 2.0 (the "License");
5e8bdeeaaSJayanth Othayoth * you may not use this file except in compliance with the License.
6e8bdeeaaSJayanth Othayoth * You may obtain a copy of the License at
7e8bdeeaaSJayanth Othayoth *
8e8bdeeaaSJayanth Othayoth * http://www.apache.org/licenses/LICENSE-2.0
9e8bdeeaaSJayanth Othayoth *
10e8bdeeaaSJayanth Othayoth * Unless required by applicable law or agreed to in writing, software
11e8bdeeaaSJayanth Othayoth * distributed under the License is distributed on an "AS IS" BASIS,
12e8bdeeaaSJayanth Othayoth * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e8bdeeaaSJayanth Othayoth * See the License for the specific language governing permissions and
14e8bdeeaaSJayanth Othayoth * limitations under the License.
15e8bdeeaaSJayanth Othayoth */
16e8bdeeaaSJayanth Othayoth
172544b419SPatrick Williams extern "C"
182544b419SPatrick Williams {
1966e186ddSJayanth Othayoth #include <libpdbg.h>
2066e186ddSJayanth Othayoth }
21e8bdeeaaSJayanth Othayoth
22c74c2202SJayanth Othayoth #include "fapi_data_process.hpp"
23c74c2202SJayanth Othayoth #include "pel.hpp"
2466e186ddSJayanth Othayoth #include "sbe_ffdc_handler.hpp"
25c74c2202SJayanth Othayoth #include "temporary_file.hpp"
26c74c2202SJayanth Othayoth
270866c3fcSJayanth Othayoth #include <ekb/hwpf/fapi2/include/return_code_defs.H>
28da876617Sdevenrao #include <ekb/hwpf/fapi2/include/target_types.H>
29eff307e3SJayanth Othayoth #include <libekb.H>
30e8bdeeaaSJayanth Othayoth
31*5bc26533SArya K Padman #include <phosphor-logging/lg2.hpp>
32e8bdeeaaSJayanth Othayoth
331aa90d49SJayanth Othayoth #include <format>
342544b419SPatrick Williams #include <new>
352544b419SPatrick Williams
36e8bdeeaaSJayanth Othayoth namespace openpower
37e8bdeeaaSJayanth Othayoth {
38e8bdeeaaSJayanth Othayoth namespace pels
39e8bdeeaaSJayanth Othayoth {
40e8bdeeaaSJayanth Othayoth namespace sbe
41e8bdeeaaSJayanth Othayoth {
42e8bdeeaaSJayanth Othayoth
43b5693746Sdevenrao constexpr uint32_t sbeMaxFfdcPackets = 20;
44da876617Sdevenrao constexpr uint16_t p10FfdcMagicCode = 0xFFDC;
45da876617Sdevenrao constexpr uint16_t pozFfdcMagicCode = 0xFBAD;
46da876617Sdevenrao constexpr uint16_t p10FfdcSkipWords = 2;
47da876617Sdevenrao constexpr uint16_t pozFfdcSkipWords = 3;
48b5693746Sdevenrao
49da876617Sdevenrao struct p10FfdcHeader
50b5693746Sdevenrao {
51b5693746Sdevenrao uint32_t magic_bytes:16;
52b5693746Sdevenrao uint32_t lengthinWords:16;
53b5693746Sdevenrao uint32_t seqId:16;
54b5693746Sdevenrao uint32_t cmdClass:8;
55b5693746Sdevenrao uint32_t cmd:8;
56b5693746Sdevenrao uint32_t fapiRc;
57da876617Sdevenrao } __attribute__((packed));
58da876617Sdevenrao
59da876617Sdevenrao struct pozFfdcHeader
60da876617Sdevenrao {
61da876617Sdevenrao uint32_t magicByte:16;
62da876617Sdevenrao uint32_t lengthinWords:16;
63da876617Sdevenrao uint32_t seqId:16;
64da876617Sdevenrao uint32_t cmdClass:8;
65da876617Sdevenrao uint32_t cmd:8;
66da876617Sdevenrao uint32_t slid:16;
67da876617Sdevenrao uint32_t severity:8;
68da876617Sdevenrao uint32_t chipId:8;
69da876617Sdevenrao uint32_t fapiRc;
70da876617Sdevenrao } __attribute__((packed));
71da876617Sdevenrao
72da876617Sdevenrao using namespace phosphor::logging;
73b5693746Sdevenrao
SbeFFDC(const AdditionalData & aData,const PelFFDC & files)74742b00b9SJayanth Othayoth SbeFFDC::SbeFFDC(const AdditionalData& aData, const PelFFDC& files) :
75da876617Sdevenrao ffdcType(FFDC_TYPE_NONE), chipType(fapi2::TARGET_TYPE_PROC_CHIP)
76e8bdeeaaSJayanth Othayoth {
77*5bc26533SArya K Padman lg2::info("SBE FFDC processing requested");
78e8bdeeaaSJayanth Othayoth
79e8bdeeaaSJayanth Othayoth // SRC6 field in the additional data contains Processor position
80e8bdeeaaSJayanth Othayoth // associated to the SBE FFDC
81e8bdeeaaSJayanth Othayoth //"[0:15] chip position"
82e8bdeeaaSJayanth Othayoth auto src6 = aData.getValue("SRC6");
83e8bdeeaaSJayanth Othayoth if (src6 == std::nullopt)
84e8bdeeaaSJayanth Othayoth {
85*5bc26533SArya K Padman lg2::error("Fail to extract SRC6 data: failing to get proc index");
86e8bdeeaaSJayanth Othayoth return;
87e8bdeeaaSJayanth Othayoth }
88e8bdeeaaSJayanth Othayoth try
89e8bdeeaaSJayanth Othayoth {
90da876617Sdevenrao chipPos = (std::stoi(src6.value()) & 0xFFFF0000) >> 16;
91e8bdeeaaSJayanth Othayoth }
9266491c61SPatrick Williams catch (const std::exception& err)
93e8bdeeaaSJayanth Othayoth {
94*5bc26533SArya K Padman lg2::error("Conversion failure errormsg({ERR})", "ERR", err);
95e8bdeeaaSJayanth Othayoth return;
96e8bdeeaaSJayanth Othayoth }
97da876617Sdevenrao auto type = aData.getValue("CHIP_TYPE");
98da876617Sdevenrao if (type != std::nullopt)
99da876617Sdevenrao {
100da876617Sdevenrao try
101da876617Sdevenrao {
102da876617Sdevenrao chipType = std::stoi(type.value());
103da876617Sdevenrao }
104da876617Sdevenrao catch (const std::exception& err)
105da876617Sdevenrao {
106*5bc26533SArya K Padman lg2::error("Conversion failure errormsg({ERR})", "ERR", err);
107da876617Sdevenrao return;
108da876617Sdevenrao }
109da876617Sdevenrao }
110e8bdeeaaSJayanth Othayoth
111e8bdeeaaSJayanth Othayoth if (files.empty())
112e8bdeeaaSJayanth Othayoth {
113*5bc26533SArya K Padman lg2::info("SbeFFDC : No files found, skipping ffdc processing");
114e8bdeeaaSJayanth Othayoth return;
115e8bdeeaaSJayanth Othayoth }
116e8bdeeaaSJayanth Othayoth
117e8bdeeaaSJayanth Othayoth for (const auto& file : files)
118e8bdeeaaSJayanth Othayoth {
119e8bdeeaaSJayanth Othayoth if ((file.format == UserDataFormat::custom) &&
120e8bdeeaaSJayanth Othayoth (file.subType == sbeFFDCSubType))
121e8bdeeaaSJayanth Othayoth {
1220866c3fcSJayanth Othayoth // Process SBE file.
1230866c3fcSJayanth Othayoth parse(file.fd);
124e8bdeeaaSJayanth Othayoth }
125e8bdeeaaSJayanth Othayoth }
126e8bdeeaaSJayanth Othayoth }
127e8bdeeaaSJayanth Othayoth
parse(int fd)1280866c3fcSJayanth Othayoth void SbeFFDC::parse(int fd)
1290866c3fcSJayanth Othayoth {
130*5bc26533SArya K Padman lg2::info("SBE FFDC file fd:({FD}), parsing started", "FD", fd);
1310866c3fcSJayanth Othayoth
1320866c3fcSJayanth Othayoth uint32_t ffdcBufOffset = 0;
1330866c3fcSJayanth Othayoth uint32_t pktCount = 0;
1340866c3fcSJayanth Othayoth
1350866c3fcSJayanth Othayoth // get SBE FFDC data.
1360866c3fcSJayanth Othayoth auto ffdcData = util::readFD(fd);
1370866c3fcSJayanth Othayoth if (ffdcData.empty())
1380866c3fcSJayanth Othayoth {
139*5bc26533SArya K Padman lg2::error("Empty SBE FFDC file fd:({FD}), skipping", "FD", fd);
1400866c3fcSJayanth Othayoth return;
1410866c3fcSJayanth Othayoth }
1420866c3fcSJayanth Othayoth
1430866c3fcSJayanth Othayoth while ((ffdcBufOffset < ffdcData.size()) && (sbeMaxFfdcPackets != pktCount))
1440866c3fcSJayanth Othayoth {
145c1a0ff88Sdevenrao sbeFfdcPacketType ffdcPkt;
1460866c3fcSJayanth Othayoth // Next un-extracted FFDC Packet
147da876617Sdevenrao uint16_t magicBytes =
148da876617Sdevenrao *(reinterpret_cast<uint16_t*>(ffdcData.data() + ffdcBufOffset));
149da876617Sdevenrao magicBytes = ntohs(magicBytes);
150da876617Sdevenrao uint32_t pktLenWords = 0;
151da876617Sdevenrao uint16_t lenWords = 0;
152da876617Sdevenrao if (magicBytes == p10FfdcMagicCode)
153da876617Sdevenrao {
154da876617Sdevenrao p10FfdcHeader* ffdc = reinterpret_cast<p10FfdcHeader*>(
155da876617Sdevenrao ffdcData.data() + ffdcBufOffset);
156da876617Sdevenrao lenWords = ntohs(ffdc->lengthinWords);
1570866c3fcSJayanth Othayoth auto fapiRc = ntohl(ffdc->fapiRc);
1580866c3fcSJayanth Othayoth
159*5bc26533SArya K Padman lg2::info(
160*5bc26533SArya K Padman "P10 FFDC magic: {MAGIC_BYTES} length in words:{LEN_WORDS} "
161*5bc26533SArya K Padman "Fapirc:{FAPI_RC}",
162*5bc26533SArya K Padman "MAGIC_BYTES", magicBytes, "LEN_WORDS", lenWords, "FAPI_RC",
163*5bc26533SArya K Padman fapiRc);
1640866c3fcSJayanth Othayoth
1650866c3fcSJayanth Othayoth ffdcPkt.fapiRc = fapiRc;
1660866c3fcSJayanth Othayoth // Not interested in the first 2 words (these are not ffdc)
167da876617Sdevenrao pktLenWords = lenWords - p10FfdcSkipWords;
1680866c3fcSJayanth Othayoth ffdcPkt.ffdcLengthInWords = pktLenWords;
1690866c3fcSJayanth Othayoth if (pktLenWords)
1700866c3fcSJayanth Othayoth {
1710866c3fcSJayanth Othayoth ffdcPkt.ffdcData = new uint32_t[pktLenWords];
1720866c3fcSJayanth Othayoth memcpy(ffdcPkt.ffdcData,
173da876617Sdevenrao ((reinterpret_cast<uint32_t*>(ffdc)) + p10FfdcSkipWords),
1740866c3fcSJayanth Othayoth (pktLenWords * sizeof(uint32_t)));
1750866c3fcSJayanth Othayoth }
1760866c3fcSJayanth Othayoth else
1770866c3fcSJayanth Othayoth {
178*5bc26533SArya K Padman lg2::error("FFDC packet size is zero skipping");
1790866c3fcSJayanth Othayoth return;
1800866c3fcSJayanth Othayoth }
1814fdb31aaSdevenrao pktCount++;
182da876617Sdevenrao }
183da876617Sdevenrao else if (magicBytes == pozFfdcMagicCode)
184da876617Sdevenrao {
185da876617Sdevenrao pozFfdcHeader* ffdc = reinterpret_cast<pozFfdcHeader*>(
186da876617Sdevenrao ffdcData.data() + ffdcBufOffset);
187da876617Sdevenrao lenWords = ntohs(ffdc->lengthinWords);
188da876617Sdevenrao auto fapiRc = ntohl(ffdc->fapiRc);
189da876617Sdevenrao
190*5bc26533SArya K Padman lg2::info(
191*5bc26533SArya K Padman "P0Z FFDC magic: {MAGIC_BYTES} length in words:{LEN_WORDS} "
192*5bc26533SArya K Padman "Fapirc:{FAPI_RC}",
193*5bc26533SArya K Padman "MAGIC_BYTES", magicBytes, "LEN_WORDS", lenWords, "FAPI_RC",
194*5bc26533SArya K Padman fapiRc);
195da876617Sdevenrao
196da876617Sdevenrao ffdcPkt.fapiRc = fapiRc;
197da876617Sdevenrao // Not interested in the first 3 words (these are not ffdc)
198da876617Sdevenrao pktLenWords = lenWords - pozFfdcSkipWords;
199da876617Sdevenrao ffdcPkt.ffdcLengthInWords = pktLenWords;
200da876617Sdevenrao if (pktLenWords)
201da876617Sdevenrao {
202da876617Sdevenrao ffdcPkt.ffdcData = new uint32_t[pktLenWords];
203da876617Sdevenrao memcpy(ffdcPkt.ffdcData,
204da876617Sdevenrao ((reinterpret_cast<uint32_t*>(ffdc)) + pozFfdcSkipWords),
205da876617Sdevenrao (pktLenWords * sizeof(uint32_t)));
206da876617Sdevenrao }
207da876617Sdevenrao else
208da876617Sdevenrao {
209*5bc26533SArya K Padman lg2::error("FFDC packet size is zero skipping");
210da876617Sdevenrao return;
211da876617Sdevenrao }
212da876617Sdevenrao }
213da876617Sdevenrao else
214da876617Sdevenrao {
215*5bc26533SArya K Padman lg2::error("Invalid FFDC magic code in Header: Skipping ");
216da876617Sdevenrao return;
217da876617Sdevenrao }
2180866c3fcSJayanth Othayoth
2190866c3fcSJayanth Othayoth // SBE FFDC processing is not required for SBE Plat errors RCs.
2200866c3fcSJayanth Othayoth // Plat errors processing is driven by SBE provided user data
2210866c3fcSJayanth Othayoth // plugins, which need to link with PEL tool infrastructure.
2220866c3fcSJayanth Othayoth if (ffdcPkt.fapiRc != fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA)
2230866c3fcSJayanth Othayoth {
2240866c3fcSJayanth Othayoth process(ffdcPkt);
2250866c3fcSJayanth Othayoth }
226fb9b811eSJayanth Othayoth else
227fb9b811eSJayanth Othayoth {
228*5bc26533SArya K Padman lg2::info("SBE FFDC: Internal FFDC packet");
229fb9b811eSJayanth Othayoth }
230fb9b811eSJayanth Othayoth
231fb9b811eSJayanth Othayoth // Update Buffer offset in Bytes
232fb9b811eSJayanth Othayoth ffdcBufOffset += lenWords * sizeof(uint32_t);
2330866c3fcSJayanth Othayoth }
2340866c3fcSJayanth Othayoth if (pktCount == sbeMaxFfdcPackets)
2350866c3fcSJayanth Othayoth {
236*5bc26533SArya K Padman lg2::error("Received more than the limit of ({SBEMAXFFDCPACKETS}) FFDC "
237*5bc26533SArya K Padman "packets, processing only ({PKTCOUNT})",
238*5bc26533SArya K Padman "SBEMAXFFDCPACKETS", sbeMaxFfdcPackets, "PKTCOUNT",
239*5bc26533SArya K Padman pktCount);
2400866c3fcSJayanth Othayoth }
2410866c3fcSJayanth Othayoth }
2420866c3fcSJayanth Othayoth
process(const sbeFfdcPacketType & ffdcPkt)243c74c2202SJayanth Othayoth void SbeFFDC::process(const sbeFfdcPacketType& ffdcPkt)
244c74c2202SJayanth Othayoth {
245c74c2202SJayanth Othayoth using json = nlohmann::json;
246c74c2202SJayanth Othayoth
247c74c2202SJayanth Othayoth // formated FFDC data structure after FFDC packet processing
248c74c2202SJayanth Othayoth FFDC ffdc;
249c74c2202SJayanth Othayoth
250c74c2202SJayanth Othayoth try
251c74c2202SJayanth Othayoth {
252c74c2202SJayanth Othayoth // libekb provided wrapper function to convert SBE FFDC
253c74c2202SJayanth Othayoth // in to known ffdc structure.
254da876617Sdevenrao libekb_get_sbe_ffdc(ffdc, ffdcPkt, chipPos, chipType);
255c74c2202SJayanth Othayoth }
256c74c2202SJayanth Othayoth catch (...)
257c74c2202SJayanth Othayoth {
258*5bc26533SArya K Padman lg2::error("libekb_get_sbe_ffdc failed, skipping ffdc processing");
259c74c2202SJayanth Othayoth return;
260c74c2202SJayanth Othayoth }
261c74c2202SJayanth Othayoth
262742b00b9SJayanth Othayoth // update FFDC type class membeir for hwp specific packet
263742b00b9SJayanth Othayoth // Assumption SBE FFDC contains only one hwp FFDC packet.
264742b00b9SJayanth Othayoth ffdcType = ffdc.ffdc_type;
265742b00b9SJayanth Othayoth
266c74c2202SJayanth Othayoth // To store callouts details in json format as per pel expectation.
267c74c2202SJayanth Othayoth json pelJSONFmtCalloutDataList;
268c74c2202SJayanth Othayoth pelJSONFmtCalloutDataList = json::array();
269c74c2202SJayanth Othayoth
270c74c2202SJayanth Othayoth // To store other user data from FFDC.
271c74c2202SJayanth Othayoth openpower::pels::phal::FFDCData ffdcUserData;
272c74c2202SJayanth Othayoth
273c74c2202SJayanth Othayoth // Get FFDC and required info to include in PEL
274c74c2202SJayanth Othayoth openpower::pels::phal::convertFAPItoPELformat(
275c74c2202SJayanth Othayoth ffdc, pelJSONFmtCalloutDataList, ffdcUserData);
276c74c2202SJayanth Othayoth
277c74c2202SJayanth Othayoth // Get callout information and sore in to file.
278c74c2202SJayanth Othayoth auto calloutData = pelJSONFmtCalloutDataList.dump();
279c74c2202SJayanth Othayoth util::TemporaryFile ffdcFile(calloutData.c_str(), calloutData.size());
280c74c2202SJayanth Othayoth
281c74c2202SJayanth Othayoth // Create json callout type pel FFDC file structre.
282c74c2202SJayanth Othayoth PelFFDCfile pf;
283c74c2202SJayanth Othayoth pf.format = openpower::pels::UserDataFormat::json;
284c74c2202SJayanth Othayoth pf.subType = openpower::pels::jsonCalloutSubtype;
285c74c2202SJayanth Othayoth pf.version = 0x01;
286c74c2202SJayanth Othayoth pf.fd = ffdcFile.getFd();
287c74c2202SJayanth Othayoth ffdcFiles.push_back(pf);
288c74c2202SJayanth Othayoth
289c74c2202SJayanth Othayoth // save the file path to delete the file after usage.
2908c7bb86aSMatt Spinler paths.emplace_back(ffdcFile.getPath(), pf.fd);
291c74c2202SJayanth Othayoth
292c74c2202SJayanth Othayoth // Format ffdc user data and create new file.
293c74c2202SJayanth Othayoth std::string data;
294c74c2202SJayanth Othayoth for (auto& d : ffdcUserData)
295c74c2202SJayanth Othayoth {
296c74c2202SJayanth Othayoth data += d.first + " = " + d.second + "\n";
297c74c2202SJayanth Othayoth }
298c74c2202SJayanth Othayoth util::TemporaryFile pelDataFile(data.c_str(), data.size());
299c74c2202SJayanth Othayoth PelFFDCfile pdf;
300c74c2202SJayanth Othayoth pdf.format = openpower::pels::UserDataFormat::text;
301c74c2202SJayanth Othayoth pdf.version = 0x01;
302c74c2202SJayanth Othayoth pdf.fd = pelDataFile.getFd();
303be952d2eSMatt Spinler pdf.subType = 0;
304c74c2202SJayanth Othayoth ffdcFiles.push_back(pdf);
305c74c2202SJayanth Othayoth
3068c7bb86aSMatt Spinler paths.emplace_back(pelDataFile.getPath(), pdf.fd);
307c74c2202SJayanth Othayoth }
308c74c2202SJayanth Othayoth
getSeverity()309742b00b9SJayanth Othayoth std::optional<LogSeverity> SbeFFDC::getSeverity()
310742b00b9SJayanth Othayoth {
311742b00b9SJayanth Othayoth if (ffdcType == FFDC_TYPE_SPARE_CLOCK_INFO)
312742b00b9SJayanth Othayoth {
313*5bc26533SArya K Padman lg2::info(
314742b00b9SJayanth Othayoth "Found spare clock error, changing severity to informational");
315742b00b9SJayanth Othayoth return LogSeverity::Informational;
316742b00b9SJayanth Othayoth }
317742b00b9SJayanth Othayoth return std::nullopt;
318742b00b9SJayanth Othayoth }
319742b00b9SJayanth Othayoth
320e8bdeeaaSJayanth Othayoth } // namespace sbe
321e8bdeeaaSJayanth Othayoth } // namespace pels
322e8bdeeaaSJayanth Othayoth } // namespace openpower
323