blob: 58a34e727b0a91535c5bcfb5800b8ea4ca9b6b4c [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;
141
142 openpower::dump::pel::FFDCData pelAdditionalData = {
143 {"SRC6", std::format("{:X}{:X}", chipPos, (cmdClass | cmdType))}};
144
145 openpower::dump::pel::createSbeErrorPEL(event, sbeError,
146 pelAdditionalData);
147 }
148 catch (const std::out_of_range& e)
149 {
150 lg2::error("Unknown SBE Type({SBETYPE}) ErrorMsg({ERROR})", "SBETYPE",
151 sbeType, "ERROR", e);
152 }
153}
154
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -0500155void SbeDumpCollector::collectDumpFromSBE(struct pdbg_target* chip,
156 const std::filesystem::path& path,
157 uint32_t id, uint8_t type,
158 uint8_t clockState,
159 uint64_t failingUnit)
160{
161 auto chipPos = pdbg_target_index(chip);
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500162 SBETypes sbeType = getSBEType(chip);
163 auto chipName = sbeTypeAttributes.at(sbeType).chipName;
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -0500164 lg2::info(
165 "Collecting dump from proc({PROC}): path({PATH}) id({ID}) "
166 "type({TYPE}) clockState({CLOCKSTATE}) failingUnit({FAILINGUNIT})",
167 "PROC", chipPos, "PATH", path.string(), "ID", id, "TYPE", type,
168 "CLOCKSTATE", clockState, "FAILINGUNIT", failingUnit);
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500169
170 util::DumpDataPtr dataPtr;
171 uint32_t len = 0;
172 uint8_t collectFastArray =
173 checkFastarrayCollectionNeeded(clockState, type, failingUnit, chipPos);
174
175 try
176 {
177 openpower::phal::sbe::getDump(chip, type, clockState, collectFastArray,
178 dataPtr.getPtr(), &len);
179 }
180 catch (const openpower::phal::sbeError_t& sbeError)
181 {
182 if (sbeError.errType() ==
183 openpower::phal::exception::SBE_CHIPOP_NOT_ALLOWED)
184 {
185 // SBE is not ready to accept chip-ops,
186 // Skip the request, no additional error handling required.
187 lg2::info("Collect dump: Skipping ({ERROR}) dump({TYPE}) "
188 "on proc({PROC}) clock state({CLOCKSTATE})",
189 "ERROR", sbeError, "TYPE", type, "PROC", chipPos,
190 "CLOCKSTATE", clockState);
191 return;
192 }
193
194 lg2::error("Error in collecting dump dump type({TYPE}), "
195 "clockstate({CLOCKSTATE}), proc position({PROC}), "
196 "collectFastArray({COLLECTFASTARRAY}) error({ERROR})",
197 "TYPE", type, "CLOCKSTATE", clockState, "PROC", chipPos,
198 "COLLECTFASTARRAY", collectFastArray, "ERROR", sbeError);
199
200 return;
201 }
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500202 writeDumpFile(path, id, clockState, 0, chipName, chipPos, dataPtr, len);
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500203}
204
205void SbeDumpCollector::writeDumpFile(
206 const std::filesystem::path& path, const uint32_t id,
Dhruvaraj Subhashchandran6feeebd2021-10-19 05:03:59 -0500207 const uint8_t clockState, const uint8_t nodeNum,
208 const std::string& chipName, const uint8_t chipPos,
209 util::DumpDataPtr& dataPtr, const uint32_t len)
Dhruvaraj Subhashchandrana699e312021-10-27 07:20:34 -0500210{
211 using namespace sdbusplus::xyz::openbmc_project::Common::Error;
212 namespace fileError = sdbusplus::xyz::openbmc_project::Common::File::Error;
213
214 // Construct the filename
215 std::ostringstream filenameBuilder;
216 filenameBuilder << std::setw(8) << std::setfill('0') << id
217 << ".SbeDataClocks"
218 << (clockState == SBE_CLOCK_ON ? "On" : "Off") << ".node"
219 << static_cast<int>(nodeNum) << "." << chipName
220 << static_cast<int>(chipPos);
221
222 auto dumpPath = path / filenameBuilder.str();
223
224 // Attempt to open the file
225 std::ofstream outfile(dumpPath, std::ios::out | std::ios::binary);
226 if (!outfile)
227 {
228 using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
229 using metadata = xyz::openbmc_project::Common::File::Open;
230 // Unable to open the file for writing
231 auto err = errno;
232 lg2::error("Error opening file to write dump, "
233 "errno({ERRNO}), filepath({FILEPATH})",
234 "ERRNO", err, "FILEPATH", dumpPath.string());
235
236 report<Open>(metadata::ERRNO(err), metadata::PATH(dumpPath.c_str()));
237 // Just return here, so that the dumps collected from other
238 // SBEs can be packaged.
239 return;
240 }
241
242 // Write to the file
243 try
244 {
245 outfile.write(reinterpret_cast<const char*>(dataPtr.getData()), len);
246
247 lg2::info("Successfully wrote dump file "
248 "path=({PATH}) size=({SIZE})",
249 "PATH", dumpPath.string(), "SIZE", len);
250 }
251 catch (const std::ofstream::failure& oe)
252 {
253 using namespace sdbusplus::xyz::openbmc_project::Common::File::Error;
254 using metadata = xyz::openbmc_project::Common::File::Write;
255
256 lg2::error(
257 "Failed to write to dump file, "
258 "errorMsg({ERROR}), error({ERRORCODE}), filepath({FILEPATH})",
259 "ERROR", oe, "ERRORCODE", oe.code().value(), "FILEPATH",
260 dumpPath.string());
261 report<Write>(metadata::ERRNO(oe.code().value()),
262 metadata::PATH(dumpPath.c_str()));
263 // Just return here so dumps collected from other SBEs can be
264 // packaged.
265 }
Dhruvaraj Subhashchandran858d1aa2021-10-27 03:26:06 -0500266}
267
268} // namespace openpower::dump::sbe_chipop