xref: /openbmc/phosphor-logging/extensions/openpower-pels/sbe_ffdc_handler.cpp (revision d8ae618a44c554c8e817833e466f773ee2f4ff88)
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