blob: 9e7801cb8426e4a4fb97dd501137187e671d3e83 [file] [log] [blame]
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -05001extern "C"
2{
3#include <libpdbg.h>
4#include <libpdbg_sbe.h>
5}
6
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -05007#include "create_pel.hpp"
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -05008#include "sbe_consts.hpp"
9#include "sbe_dump_collector.hpp"
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050010#include "sbe_type.hpp"
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -050011
12#include <libphal.H>
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -050013#include <phal_exception.H>
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -050014
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -050015#include <phosphor-logging/elog-errors.hpp>
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -050016#include <phosphor-logging/lg2.hpp>
17#include <phosphor-logging/log.hpp>
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -050018#include <sbe_consts.hpp>
19#include <xyz/openbmc_project/Common/File/error.hpp>
20#include <xyz/openbmc_project/Common/error.hpp>
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -050021
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -050022#include <cstdint>
23#include <filesystem>
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -050024#include <format>
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -050025#include <fstream>
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -050026#include <stdexcept>
27
28namespace openpower::dump::sbe_chipop
29{
30
31using namespace phosphor::logging;
32using namespace openpower::dump::SBE;
33
34void SbeDumpCollector::collectDump(uint8_t type, uint32_t id,
35 uint64_t failingUnit,
36 const std::filesystem::path& path)
37{
38 lg2::error("Starting dump collection: type:{TYPE} id:{ID} "
39 "failingUnit:{FAILINGUNIT}, path:{PATH}",
40 "TYPE", type, "ID", id, "FAILINGUNIT", failingUnit, "PATH",
41 path.string());
42
43 initializePdbg();
44
45 std::vector<struct pdbg_target*> targets;
46
47 struct pdbg_target* target = nullptr;
48 pdbg_for_each_class_target("proc", target)
49 {
50 if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED ||
51 !openpower::phal::pdbg::isTgtFunctional(target))
52 {
53 continue;
54 }
55
56 targets.push_back(target);
57 }
58
59 std::vector<uint8_t> clockStates = {SBE_CLOCK_ON, SBE_CLOCK_OFF};
60 for (auto cstate : clockStates)
61 {
62 auto futures = spawnDumpCollectionProcesses(type, id, path, failingUnit,
63 cstate, targets);
64
65 // Wait for all asynchronous tasks to complete
66 for (auto& future : futures)
67 {
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -050068 try
69 {
70 future.wait();
71 }
72 catch (const std::exception& e)
73 {
74 lg2::error("Failed to collect dump from SBE ErrorMsg({ERROR})",
75 "ERROR", e);
76 }
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -050077 }
78 lg2::info(
79 "Dump collection completed for clock state({CSTATE}): type({TYPE}) "
80 "id({ID}) failingUnit({FAILINGUNIT}), path({PATH})",
81 "CSTATE", cstate, "TYPE", type, "ID", id, "FAILINGUNIT",
82 failingUnit, "PATH", path.string());
83 }
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -050084 if (std::filesystem::is_empty(path))
85 {
86 lg2::error("Failed to collect the dump");
87 throw std::runtime_error("Failed to collect the dump");
88 }
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -050089 lg2::info("Dump collection completed");
90}
91
92void SbeDumpCollector::initializePdbg()
93{
94 openpower::phal::pdbg::init();
95}
96
97std::vector<std::future<void>> SbeDumpCollector::spawnDumpCollectionProcesses(
98 uint8_t type, uint32_t id, const std::filesystem::path& path,
99 uint64_t failingUnit, uint8_t cstate,
100 const std::vector<struct pdbg_target*>& targets)
101{
102 std::vector<std::future<void>> futures;
103
104 for (auto target : targets)
105 {
106 if (pdbg_target_probe(target) != PDBG_TARGET_ENABLED ||
107 !openpower::phal::pdbg::isTgtFunctional(target))
108 {
109 continue;
110 }
111
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -0500112 auto future =
113 std::async(std::launch::async,
114 [this, target, path, id, type, cstate, failingUnit]() {
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500115 try
116 {
117 this->collectDumpFromSBE(target, path, id, type, cstate,
118 failingUnit);
119 }
120 catch (const std::exception& e)
121 {
122 lg2::error(
123 "Failed to collect dump from SBE on Proc-({PROCINDEX})",
124 "PROCINDEX", pdbg_target_index(target));
125 }
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -0500126 });
127
128 futures.push_back(std::move(future));
129 }
130
131 return futures;
132}
133
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500134void SbeDumpCollector::logErrorAndCreatePEL(
135 const openpower::phal::sbeError_t& sbeError, uint64_t chipPos,
136 SBETypes sbeType, uint32_t cmdClass, uint32_t cmdType)
137{
138 try
139 {
140 std::string event = sbeTypeAttributes.at(sbeType).chipOpFailure;
Dhruvaraj Subhashchandran5f5c94d2021-10-19 07:18:30 -0500141 auto dumpIsRequired = false;
142
143 if (sbeError.errType() == openpower::phal::exception::SBE_CMD_TIMEOUT)
144 {
145 event = sbeTypeAttributes.at(sbeType).chipOpTimeout;
146 dumpIsRequired = true;
147 }
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500148
149 openpower::dump::pel::FFDCData pelAdditionalData = {
150 {"SRC6", std::format("{:X}{:X}", chipPos, (cmdClass | cmdType))}};
151
152 openpower::dump::pel::createSbeErrorPEL(event, sbeError,
153 pelAdditionalData);
Dhruvaraj Subhashchandran5f5c94d2021-10-19 07:18:30 -0500154 auto logId = openpower::dump::pel::createSbeErrorPEL(event, sbeError,
155 pelAdditionalData);
156
157 // Request SBE Dump if required
158 if (dumpIsRequired)
159 {
160 util::requestSBEDump(chipPos, logId, sbeType);
161 }
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500162 }
163 catch (const std::out_of_range& e)
164 {
165 lg2::error("Unknown SBE Type({SBETYPE}) ErrorMsg({ERROR})", "SBETYPE",
166 sbeType, "ERROR", e);
167 }
Dhruvaraj Subhashchandran5f5c94d2021-10-19 07:18:30 -0500168 catch (const std::exception& e)
169 {
170 lg2::error("SBE Dump request failed, chip position({CHIPPOS}), "
171 "Error: {ERROR}",
172 "CHIPPOS", chipPos, "ERROR", e);
173 }
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500174}
175
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -0500176void SbeDumpCollector::collectDumpFromSBE(struct pdbg_target* chip,
177 const std::filesystem::path& path,
178 uint32_t id, uint8_t type,
179 uint8_t clockState,
180 uint64_t failingUnit)
181{
182 auto chipPos = pdbg_target_index(chip);
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500183 SBETypes sbeType = getSBEType(chip);
184 auto chipName = sbeTypeAttributes.at(sbeType).chipName;
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -0500185 lg2::info(
186 "Collecting dump from proc({PROC}): path({PATH}) id({ID}) "
187 "type({TYPE}) clockState({CLOCKSTATE}) failingUnit({FAILINGUNIT})",
188 "PROC", chipPos, "PATH", path.string(), "ID", id, "TYPE", type,
189 "CLOCKSTATE", clockState, "FAILINGUNIT", failingUnit);
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500190
191 util::DumpDataPtr dataPtr;
192 uint32_t len = 0;
193 uint8_t collectFastArray =
194 checkFastarrayCollectionNeeded(clockState, type, failingUnit, chipPos);
195
196 try
197 {
198 openpower::phal::sbe::getDump(chip, type, clockState, collectFastArray,
199 dataPtr.getPtr(), &len);
200 }
201 catch (const openpower::phal::sbeError_t& sbeError)
202 {
203 if (sbeError.errType() ==
204 openpower::phal::exception::SBE_CHIPOP_NOT_ALLOWED)
205 {
206 // SBE is not ready to accept chip-ops,
207 // Skip the request, no additional error handling required.
208 lg2::info("Collect dump: Skipping ({ERROR}) dump({TYPE}) "
209 "on proc({PROC}) clock state({CLOCKSTATE})",
210 "ERROR", sbeError, "TYPE", type, "PROC", chipPos,
211 "CLOCKSTATE", clockState);
212 return;
213 }
214
215 lg2::error("Error in collecting dump dump type({TYPE}), "
Dhruvaraj Subhashchandran5f5c94d2021-10-19 07:18:30 -0500216 "clockstate({CLOCKSTATE}), chip type({CHIPTYPE}) "
217 "position({POSITION}), "
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500218 "collectFastArray({COLLECTFASTARRAY}) error({ERROR})",
Dhruvaraj Subhashchandran5f5c94d2021-10-19 07:18:30 -0500219 "TYPE", type, "CLOCKSTATE", clockState, "CHIPTYPE", chipName,
220 "POSITION", chipPos, "COLLECTFASTARRAY", collectFastArray,
221 "ERROR", sbeError);
222 logErrorAndCreatePEL(sbeError, chipPos, sbeType, SBEFIFO_CMD_CLASS_DUMP,
223 SBEFIFO_CMD_GET_DUMP);
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500224 return;
225 }
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500226 writeDumpFile(path, id, clockState, 0, chipName, chipPos, dataPtr, len);
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500227}
228
229void SbeDumpCollector::writeDumpFile(
230 const std::filesystem::path& path, const uint32_t id,
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500231 const uint8_t clockState, const uint8_t nodeNum,
232 const std::string& chipName, const uint8_t chipPos,
233 util::DumpDataPtr& dataPtr, const uint32_t len)
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500234{
235 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
236 namespace fileError = sdbusplus::xyz::openbmc_project::Common::File::Error;
237
238 // Construct the filename
239 std::ostringstream filenameBuilder;
240 filenameBuilder << std::setw(8) << std::setfill('0') << id
241 << ".SbeDataClocks"
242 << (clockState == SBE_CLOCK_ON ? "On" : "Off") << ".node"
243 << static_cast<int>(nodeNum) << "." << chipName
244 << static_cast<int>(chipPos);
245
246 auto dumpPath = path / filenameBuilder.str();
247
248 // Attempt to open the file
249 std::ofstream outfile(dumpPath, std::ios::out | std::ios::binary);
250 if (!outfile)
251 {
252 using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
253 using metadata = xyz::openbmc_project::Common::File::Open;
254 // Unable to open the file for writing
255 auto err = errno;
256 lg2::error("Error opening file to write dump, "
257 "errno({ERRNO}), filepath({FILEPATH})",
258 "ERRNO", err, "FILEPATH", dumpPath.string());
259
260 report<Open>(metadata::ERRNO(err), metadata::PATH(dumpPath.c_str()));
261 // Just return here, so that the dumps collected from other
262 // SBEs can be packaged.
263 return;
264 }
265
266 // Write to the file
267 try
268 {
269 outfile.write(reinterpret_cast<const char*>(dataPtr.getData()), len);
270
271 lg2::info("Successfully wrote dump file "
272 "path=({PATH}) size=({SIZE})",
273 "PATH", dumpPath.string(), "SIZE", len);
274 }
275 catch (const std::ofstream::failure& oe)
276 {
277 using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
278 using metadata = xyz::openbmc_project::Common::File::Write;
279
280 lg2::error(
281 "Failed to write to dump file, "
282 "errorMsg({ERROR}), error({ERRORCODE}), filepath({FILEPATH})",
283 "ERROR", oe, "ERRORCODE", oe.code().value(), "FILEPATH",
284 dumpPath.string());
285 report<Write>(metadata::ERRNO(oe.code().value()),
286 metadata::PATH(dumpPath.c_str()));
287 // Just return here so dumps collected from other SBEs can be
288 // packaged.
289 }
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -0500290}
291
292} // namespace openpower::dump::sbe_chipop