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