blob: 26ecc6fcd8c621f03d4ee3639532f18fafd41ebb [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 Othayothe8bdeea2021-06-03 03:01:16 -050028#include <fmt/format.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
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
Jayanth Othayoth742b00b2022-06-30 05:16:57 -050044SbeFFDC::SbeFFDC(const AdditionalData& aData, const PelFFDC& files) :
45 ffdcType(FFDC_TYPE_NONE)
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050046{
47 log<level::INFO>("SBE FFDC processing requested");
48
49 // SRC6 field in the additional data contains Processor position
50 // associated to the SBE FFDC
51 //"[0:15] chip position"
52 auto src6 = aData.getValue("SRC6");
53 if (src6 == std::nullopt)
54 {
55 log<level::ERR>("Fail to extract SRC6 data: failing to get proc index");
56 return;
57 }
58 try
59 {
Dhruvaraj Subhashchandran8edad2a2022-06-22 13:56:40 -050060 procPos = (std::stoi(src6.value()) & 0xFFFF0000) >> 16;
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050061 }
Patrick Williams66491c62021-10-06 12:23:37 -050062 catch (const std::exception& err)
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050063 {
64 log<level::ERR>(
65 fmt::format("Conversion failure errormsg({})", err.what()).c_str());
66 return;
67 }
68
69 if (files.empty())
70 {
71 log<level::INFO>("SbeFFDC : No files found, skipping ffdc processing");
72 return;
73 }
74
75 for (const auto& file : files)
76 {
77 if ((file.format == UserDataFormat::custom) &&
78 (file.subType == sbeFFDCSubType))
79 {
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050080 // Process SBE file.
81 parse(file.fd);
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -050082 }
83 }
84}
85
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -050086void SbeFFDC::parse(int fd)
87{
88 log<level::INFO>(
89 fmt::format("SBE FFDC file fd:({}), parsing started", fd).c_str());
90
91 uint32_t ffdcBufOffset = 0;
92 uint32_t pktCount = 0;
93 sbeFfdcPacketType ffdcPkt;
94
95 // get SBE FFDC data.
96 auto ffdcData = util::readFD(fd);
97 if (ffdcData.empty())
98 {
99 log<level::ERR>(
100 fmt::format("Empty SBE FFDC file fd:({}), skipping", fd).c_str());
101 return;
102 }
103
104 while ((ffdcBufOffset < ffdcData.size()) && (sbeMaxFfdcPackets != pktCount))
105 {
106 // Next un-extracted FFDC Packet
107 fapiFfdcBufType* ffdc =
108 reinterpret_cast<fapiFfdcBufType*>(ffdcData.data() + ffdcBufOffset);
109 auto magicBytes = ntohs(ffdc->magic_bytes);
110 auto lenWords = ntohs(ffdc->lengthinWords);
111 auto fapiRc = ntohl(ffdc->fapiRc);
112
113 auto msg = fmt::format("FFDC magic: {} length in words:{} Fapirc:{}",
114 magicBytes, lenWords, fapiRc);
115 log<level::INFO>(msg.c_str());
116
117 if (magicBytes != ffdcMagicCode)
118 {
119 log<level::ERR>("Invalid FFDC magic code in Header: Skipping ");
120 return;
121 }
122 ffdcPkt.fapiRc = fapiRc;
123 // Not interested in the first 2 words (these are not ffdc)
124 auto pktLenWords = lenWords - (2 * ffdcPkgOneWord);
125 ffdcPkt.ffdcLengthInWords = pktLenWords;
126 if (pktLenWords)
127 {
128 // Memory freeing will be taking care by ffdcPkt structure
129 // destructor
130 ffdcPkt.ffdcData = new uint32_t[pktLenWords];
131 memcpy(ffdcPkt.ffdcData,
132 ((reinterpret_cast<uint32_t*>(ffdc)) +
133 (2 * ffdcPkgOneWord)), // skip first 2 words
134 (pktLenWords * sizeof(uint32_t)));
135 }
136 else
137 {
138 log<level::ERR>("FFDC packet size is zero skipping");
139 return;
140 }
141
142 // SBE FFDC processing is not required for SBE Plat errors RCs.
143 // Plat errors processing is driven by SBE provided user data
144 // plugins, which need to link with PEL tool infrastructure.
145 if (ffdcPkt.fapiRc != fapi2::FAPI2_RC_PLAT_ERR_SEE_DATA)
146 {
147 process(ffdcPkt);
148 }
Jayanth Othayothfb9b8112021-10-07 04:10:18 -0500149 else
150 {
151 log<level::INFO>("SBE FFDC: Internal FFDC packet");
152 }
153
154 // Update Buffer offset in Bytes
155 ffdcBufOffset += lenWords * sizeof(uint32_t);
Jayanth Othayoth0866c3f2021-06-07 07:06:20 -0500156 ++pktCount;
157 }
158 if (pktCount == sbeMaxFfdcPackets)
159 {
160 log<level::ERR>(fmt::format("Received more than the limit of ({})"
161 " FFDC packets, processing only ({})",
162 sbeMaxFfdcPackets, pktCount)
163 .c_str());
164 }
165}
166
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500167void SbeFFDC::process(const sbeFfdcPacketType& ffdcPkt)
168{
169 using json = nlohmann::json;
170
171 // formated FFDC data structure after FFDC packet processing
172 FFDC ffdc;
173
Jayanth Othayoth66e186d2021-06-15 22:44:35 -0500174 if (!pdbg_targets_init(NULL))
175 {
176 log<level::ERR>("pdbg_targets_init failed, skipping ffdc processing");
177 return;
178 }
179
Jayanth Othayotheff307e2021-07-15 03:27:01 -0500180 if (libekb_init())
181 {
182 log<level::ERR>("libekb_init failed, skipping ffdc processing");
183 return;
184 }
185
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500186 try
187 {
188 // libekb provided wrapper function to convert SBE FFDC
189 // in to known ffdc structure.
190 libekb_get_sbe_ffdc(ffdc, ffdcPkt, procPos);
191 }
192 catch (...)
193 {
194 log<level::ERR>("libekb_get_sbe_ffdc failed, skipping ffdc processing");
195 return;
196 }
197
Jayanth Othayoth742b00b2022-06-30 05:16:57 -0500198 // update FFDC type class membeir for hwp specific packet
199 // Assumption SBE FFDC contains only one hwp FFDC packet.
200 ffdcType = ffdc.ffdc_type;
201
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500202 // To store callouts details in json format as per pel expectation.
203 json pelJSONFmtCalloutDataList;
204 pelJSONFmtCalloutDataList = json::array();
205
206 // To store other user data from FFDC.
207 openpower::pels::phal::FFDCData ffdcUserData;
208
209 // Get FFDC and required info to include in PEL
210 openpower::pels::phal::convertFAPItoPELformat(
211 ffdc, pelJSONFmtCalloutDataList, ffdcUserData);
212
213 // Get callout information and sore in to file.
214 auto calloutData = pelJSONFmtCalloutDataList.dump();
215 util::TemporaryFile ffdcFile(calloutData.c_str(), calloutData.size());
216
217 // Create json callout type pel FFDC file structre.
218 PelFFDCfile pf;
219 pf.format = openpower::pels::UserDataFormat::json;
220 pf.subType = openpower::pels::jsonCalloutSubtype;
221 pf.version = 0x01;
222 pf.fd = ffdcFile.getFd();
223 ffdcFiles.push_back(pf);
224
225 // save the file path to delete the file after usage.
Matt Spinler8c7bb862023-08-31 14:32:22 -0500226 paths.emplace_back(ffdcFile.getPath(), pf.fd);
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500227
228 // Format ffdc user data and create new file.
229 std::string data;
230 for (auto& d : ffdcUserData)
231 {
232 data += d.first + " = " + d.second + "\n";
233 }
234 util::TemporaryFile pelDataFile(data.c_str(), data.size());
235 PelFFDCfile pdf;
236 pdf.format = openpower::pels::UserDataFormat::text;
237 pdf.version = 0x01;
238 pdf.fd = pelDataFile.getFd();
Matt Spinlerbe952d22022-07-01 11:30:11 -0500239 pdf.subType = 0;
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500240 ffdcFiles.push_back(pdf);
241
Matt Spinler8c7bb862023-08-31 14:32:22 -0500242 paths.emplace_back(pelDataFile.getPath(), pdf.fd);
Jayanth Othayothc74c2202021-06-04 06:42:43 -0500243}
244
Jayanth Othayoth742b00b2022-06-30 05:16:57 -0500245std::optional<LogSeverity> SbeFFDC::getSeverity()
246{
247 if (ffdcType == FFDC_TYPE_SPARE_CLOCK_INFO)
248 {
249 log<level::INFO>(
250 "Found spare clock error, changing severity to informational");
251 return LogSeverity::Informational;
252 }
253 return std::nullopt;
254}
255
Jayanth Othayothe8bdeea2021-06-03 03:01:16 -0500256} // namespace sbe
257} // namespace pels
258} // namespace openpower