blob: 67f515c07f4673b1d32ebd83613b76d99f2c3d3f [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>
Jayanth Othayotheff307e2021-07-15 03:27:01 -050028#include <libekb.H>
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050029
30#include <phosphor-logging/log.hpp>
31
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -050032#include <format>
Patrick Williams2544b412022-10-04 08:41:06 -050033#include <new>
34
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050035namespace openpower
36{
37namespace pels
38{
39namespace sbe
40{
41
42using namespace phosphor::logging;
43
devenraob5693742024-02-16 18:33:32 +053044constexpr uint32_t sbeMaxFfdcPackets = 20;
45constexpr uint32_t ffdcPkgOneWord = 1;
46const uint16_t ffdcMagicCode = 0xFFDC;
47
48typedef struct
49{
50 uint32_t magic_bytes:16;
51 uint32_t lengthinWords:16;
52 uint32_t seqId:16;
53 uint32_t cmdClass:8;
54 uint32_t cmd:8;
55 uint32_t fapiRc;
56} __attribute__((packed)) fapiFfdcBufType;
57
Jayanth Othayoth742b00b2022-06-30 05:16:57 -050058SbeFFDC::SbeFFDC(const AdditionalData& aData, const PelFFDC& files) :
59 ffdcType(FFDC_TYPE_NONE)
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050060{
61 log<level::INFO>("SBE FFDC processing requested");
62
63 // SRC6 field in the additional data contains Processor position
64 // associated to the SBE FFDC
65 //"[0:15] chip position"
66 auto src6 = aData.getValue("SRC6");
67 if (src6 == std::nullopt)
68 {
69 log<level::ERR>("Fail to extract SRC6 data: failing to get proc index");
70 return;
71 }
72 try
73 {
Dhruvaraj Subhashchandran8edad2a2022-06-22 13:56:40 -050074 procPos = (std::stoi(src6.value()) & 0xFFFF0000) >> 16;
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050075 }
Patrick Williams66491c62021-10-06 12:23:37 -050076 catch (const std::exception& err)
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050077 {
78 log<level::ERR>(
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -050079 std::format("Conversion failure errormsg({})", err.what()).c_str());
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050080 return;
81 }
82
83 if (files.empty())
84 {
85 log<level::INFO>("SbeFFDC : No files found, skipping ffdc processing");
86 return;
87 }
88
89 for (const auto& file : files)
90 {
91 if ((file.format == UserDataFormat::custom) &&
92 (file.subType == sbeFFDCSubType))
93 {
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050094 // Process SBE file.
95 parse(file.fd);
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050096 }
97 }
98}
99
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500100void SbeFFDC::parse(int fd)
101{
102 log<level::INFO>(
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500103 std::format("SBE FFDC file fd:({}), parsing started", fd).c_str());
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500104
105 uint32_t ffdcBufOffset = 0;
106 uint32_t pktCount = 0;
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500107
108 // get SBE FFDC data.
109 auto ffdcData = util::readFD(fd);
110 if (ffdcData.empty())
111 {
112 log<level::ERR>(
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500113 std::format("Empty SBE FFDC file fd:({}), skipping", fd).c_str());
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500114 return;
115 }
116
117 while ((ffdcBufOffset < ffdcData.size()) && (sbeMaxFfdcPackets != pktCount))
118 {
devenraoc1a0ff82024-02-16 18:36:20 +0530119 sbeFfdcPacketType ffdcPkt;
120
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500121 // Next un-extracted FFDC Packet
122 fapiFfdcBufType* ffdc =
123 reinterpret_cast<fapiFfdcBufType*>(ffdcData.data() + ffdcBufOffset);
124 auto magicBytes = ntohs(ffdc->magic_bytes);
125 auto lenWords = ntohs(ffdc->lengthinWords);
126 auto fapiRc = ntohl(ffdc->fapiRc);
127
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500128 auto msg = std::format("FFDC magic: {} length in words:{} Fapirc:{}",
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500129 magicBytes, lenWords, fapiRc);
130 log<level::INFO>(msg.c_str());
131
132 if (magicBytes != ffdcMagicCode)
133 {
134 log<level::ERR>("Invalid FFDC magic code in Header: Skipping ");
135 return;
136 }
137 ffdcPkt.fapiRc = fapiRc;
138 // Not interested in the first 2 words (these are not ffdc)
139 auto pktLenWords = lenWords - (2 * ffdcPkgOneWord);
140 ffdcPkt.ffdcLengthInWords = pktLenWords;
141 if (pktLenWords)
142 {
143 // Memory freeing will be taking care by ffdcPkt structure
144 // destructor
145 ffdcPkt.ffdcData = new uint32_t[pktLenWords];
146 memcpy(ffdcPkt.ffdcData,
147 ((reinterpret_cast<uint32_t*>(ffdc)) +
148 (2 * ffdcPkgOneWord)), // skip first 2 words
149 (pktLenWords * sizeof(uint32_t)));
150 }
151 else
152 {
153 log<level::ERR>("FFDC packet size is zero skipping");
154 return;
155 }
156
157 // SBE FFDC processing is not required for SBE Plat errors RCs.
158 // Plat errors processing is driven by SBE provided user data
159 // plugins, which need to link with PEL tool infrastructure.
160 if (ffdcPkt.fapiRc != fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA)
161 {
162 process(ffdcPkt);
163 }
Jayanth Othayothfb9b8112021-10-07 04:10:18 -0500164 else
165 {
166 log<level::INFO>("SBE FFDC: Internal FFDC packet");
167 }
168
169 // Update Buffer offset in Bytes
170 ffdcBufOffset += lenWords * sizeof(uint32_t);
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500171 ++pktCount;
172 }
173 if (pktCount == sbeMaxFfdcPackets)
174 {
Jayanth Othayoth1aa90d42023-09-13 04:25:45 -0500175 log<level::ERR>(std::format("Received more than the limit of ({})"
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500176 " FFDC packets, processing only ({})",
177 sbeMaxFfdcPackets, pktCount)
178 .c_str());
179 }
180}
181
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500182void SbeFFDC::process(const sbeFfdcPacketType& ffdcPkt)
183{
184 using json = nlohmann::json;
185
186 // formated FFDC data structure after FFDC packet processing
187 FFDC ffdc;
188
Jayanth Othayoth66e186d2021-06-15 22:44:35 -0500189 if (!pdbg_targets_init(NULL))
190 {
191 log<level::ERR>("pdbg_targets_init failed, skipping ffdc processing");
192 return;
193 }
194
Jayanth Othayotheff307e2021-07-15 03:27:01 -0500195 if (libekb_init())
196 {
197 log<level::ERR>("libekb_init failed, skipping ffdc processing");
198 return;
199 }
200
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500201 try
202 {
203 // libekb provided wrapper function to convert SBE FFDC
204 // in to known ffdc structure.
205 libekb_get_sbe_ffdc(ffdc, ffdcPkt, procPos);
206 }
207 catch (...)
208 {
209 log<level::ERR>("libekb_get_sbe_ffdc failed, skipping ffdc processing");
210 return;
211 }
212
Jayanth Othayoth742b00b2022-06-30 05:16:57 -0500213 // update FFDC type class membeir for hwp specific packet
214 // Assumption SBE FFDC contains only one hwp FFDC packet.
215 ffdcType = ffdc.ffdc_type;
216
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500217 // To store callouts details in json format as per pel expectation.
218 json pelJSONFmtCalloutDataList;
219 pelJSONFmtCalloutDataList = json::array();
220
221 // To store other user data from FFDC.
222 openpower::pels::phal::FFDCData ffdcUserData;
223
224 // Get FFDC and required info to include in PEL
225 openpower::pels::phal::convertFAPItoPELformat(
226 ffdc, pelJSONFmtCalloutDataList, ffdcUserData);
227
228 // Get callout information and sore in to file.
229 auto calloutData = pelJSONFmtCalloutDataList.dump();
230 util::TemporaryFile ffdcFile(calloutData.c_str(), calloutData.size());
231
232 // Create json callout type pel FFDC file structre.
233 PelFFDCfile pf;
234 pf.format = openpower::pels::UserDataFormat::json;
235 pf.subType = openpower::pels::jsonCalloutSubtype;
236 pf.version = 0x01;
237 pf.fd = ffdcFile.getFd();
238 ffdcFiles.push_back(pf);
239
240 // save the file path to delete the file after usage.
Matt Spinler8c7bb862023-08-31 14:32:22 -0500241 paths.emplace_back(ffdcFile.getPath(), pf.fd);
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500242
243 // Format ffdc user data and create new file.
244 std::string data;
245 for (auto& d : ffdcUserData)
246 {
247 data += d.first + " = " + d.second + "\n";
248 }
249 util::TemporaryFile pelDataFile(data.c_str(), data.size());
250 PelFFDCfile pdf;
251 pdf.format = openpower::pels::UserDataFormat::text;
252 pdf.version = 0x01;
253 pdf.fd = pelDataFile.getFd();
Matt Spinlerbe952d22022-07-01 11:30:11 -0500254 pdf.subType = 0;
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500255 ffdcFiles.push_back(pdf);
256
Matt Spinler8c7bb862023-08-31 14:32:22 -0500257 paths.emplace_back(pelDataFile.getPath(), pdf.fd);
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500258}
259
Jayanth Othayoth742b00b2022-06-30 05:16:57 -0500260std::optional<LogSeverity> SbeFFDC::getSeverity()
261{
262 if (ffdcType == FFDC_TYPE_SPARE_CLOCK_INFO)
263 {
264 log<level::INFO>(
265 "Found spare clock error, changing severity to informational");
266 return LogSeverity::Informational;
267 }
268 return std::nullopt;
269}
270
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -0500271} // namespace sbe
272} // namespace pels
273} // namespace openpower