1b1ebfcb1SBen Tyner #include <unistd.h>
2b1ebfcb1SBen Tyner
3135793a8SBen Tyner #include <analyzer/analyzer_main.hpp>
45c5db65aSBen Tyner #include <attn/attn_common.hpp>
5188f1096SBen Tyner #include <attn/attn_dbus.hpp>
67029e525SBen Tyner #include <attn/attn_dump.hpp>
7b797b3e1SBen Tyner #include <attn/attn_logging.hpp>
8f5210bb6SBen Tyner #include <attn/pel/pel_minimal.hpp>
9b1ebfcb1SBen Tyner #include <phosphor-logging/log.hpp>
101315968cSBen Tyner #include <util/dbus.hpp>
11faf33367SBen Tyner #include <util/ffdc.hpp>
12bfa831a8Saustinfcui #include <util/trace.hpp>
13f5210bb6SBen Tyner
14b1ebfcb1SBen Tyner namespace attn
15b1ebfcb1SBen Tyner {
16f5210bb6SBen Tyner /** @brief Tuple containing information about ffdc files */
17f5210bb6SBen Tyner using FFDCTuple =
18f5210bb6SBen Tyner std::tuple<util::FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>;
19f5210bb6SBen Tyner
20f5210bb6SBen Tyner /**
21f5210bb6SBen Tyner * Create FFDCTuple objects corresponding to the specified FFDC files.
22f5210bb6SBen Tyner *
23f5210bb6SBen Tyner * The D-Bus method to create an error log requires a vector of tuples to
24f5210bb6SBen Tyner * pass in the FFDC file information.
25f5210bb6SBen Tyner *
26f5210bb6SBen Tyner * @param files - FFDC files
27f5210bb6SBen Tyner * @return vector of FFDCTuple objects
28f5210bb6SBen Tyner */
createFFDCTuples(const std::vector<util::FFDCFile> & files)29*85d42b14SPatrick Williams std::vector<FFDCTuple> createFFDCTuples(
30*85d42b14SPatrick Williams const std::vector<util::FFDCFile>& files)
31f5210bb6SBen Tyner {
32f5210bb6SBen Tyner std::vector<FFDCTuple> ffdcTuples{};
33a79f6c8fSZane Shelley util::transformFFDC(files, ffdcTuples);
34f5210bb6SBen Tyner
35f5210bb6SBen Tyner return ffdcTuples;
36f5210bb6SBen Tyner }
37f5210bb6SBen Tyner
38f5210bb6SBen Tyner /**
39f5210bb6SBen Tyner * @brief Create an FFDCFile object containing raw data
40f5210bb6SBen Tyner *
41f5210bb6SBen Tyner * Throws an exception if an error occurs.
42f5210bb6SBen Tyner *
43f5210bb6SBen Tyner * @param i_buffer - raw data to add to ffdc faw data file
44f5210bb6SBen Tyner * @param i_size - size of the raw data
45f5210bb6SBen Tyner * @return FFDCFile object
46f5210bb6SBen Tyner */
createFFDCRawFile(void * i_buffer,size_t i_size)47f5210bb6SBen Tyner util::FFDCFile createFFDCRawFile(void* i_buffer, size_t i_size)
48f5210bb6SBen Tyner {
49f5210bb6SBen Tyner util::FFDCFile file{util::FFDCFormat::Custom};
50f5210bb6SBen Tyner
51f5210bb6SBen Tyner // Write buffer to file and then reset file description file offset
52f5210bb6SBen Tyner int fd = file.getFileDescriptor();
53d700609cSBen Tyner size_t numBytes = write(fd, static_cast<char*>(i_buffer), i_size);
54d700609cSBen Tyner if (i_size != numBytes)
55d700609cSBen Tyner {
56bfa831a8Saustinfcui trace::err("%s only %u of %u bytes written", file.getPath().c_str(),
57bfa831a8Saustinfcui numBytes, i_size);
58d700609cSBen Tyner }
59d700609cSBen Tyner
60f5210bb6SBen Tyner lseek(fd, 0, SEEK_SET);
61f5210bb6SBen Tyner
62f5210bb6SBen Tyner return file;
63f5210bb6SBen Tyner }
64f5210bb6SBen Tyner
65f5210bb6SBen Tyner /**
66f5210bb6SBen Tyner * Create FFDCFile objects containing debug data to store in the error log.
67f5210bb6SBen Tyner *
68f5210bb6SBen Tyner * If an error occurs, the error is written to the journal but an exception
69f5210bb6SBen Tyner * is not thrown.
70f5210bb6SBen Tyner *
71f5210bb6SBen Tyner * @param i_buffer - raw data (if creating raw dump ffdc entry in log)
72f5210bb6SBen Tyner * @return vector of FFDCFile objects
73f5210bb6SBen Tyner */
createFFDCFiles(char * i_buffer=nullptr,size_t i_size=0)74*85d42b14SPatrick Williams std::vector<util::FFDCFile> createFFDCFiles(char* i_buffer = nullptr,
75*85d42b14SPatrick Williams size_t i_size = 0)
76f5210bb6SBen Tyner {
77f5210bb6SBen Tyner std::vector<util::FFDCFile> files{};
78f5210bb6SBen Tyner
79f5210bb6SBen Tyner // Create raw dump file
80f5210bb6SBen Tyner if ((nullptr != i_buffer) && (0 != i_size))
81f5210bb6SBen Tyner {
82f5210bb6SBen Tyner files.emplace_back(createFFDCRawFile(i_buffer, i_size));
83f5210bb6SBen Tyner }
84f5210bb6SBen Tyner
85f5210bb6SBen Tyner // Create trace dump file
86faf33367SBen Tyner util::createFFDCTraceFiles(files);
87f5210bb6SBen Tyner
8821cc6270SBen Tyner // Add PRD scratch registers
8921cc6270SBen Tyner addPrdScratchRegs(files);
9021cc6270SBen Tyner
91f5210bb6SBen Tyner return files;
92f5210bb6SBen Tyner }
93f5210bb6SBen Tyner
94f5210bb6SBen Tyner /**
95f5210bb6SBen Tyner * Create a PEL from an existing PEL
96f5210bb6SBen Tyner *
97f5210bb6SBen Tyner * Create a new PEL based on the specified raw PEL and submit the new PEL
98f5210bb6SBen Tyner * to the backend logging code as a raw PEL. Note that additional data map
99f5210bb6SBen Tyner * here contains data to be committed to the PEL and it can also be used to
100f5210bb6SBen Tyner * create the PEL as it contains needed information.
101f5210bb6SBen Tyner *
102135793a8SBen Tyner * @param i_rawPel - buffer containing a raw PEL
103f5210bb6SBen Tyner * @param i_additional - additional data to be added to the new PEL
104f5210bb6SBen Tyner */
createPelCustom(std::vector<uint8_t> & i_rawPel,std::map<std::string,std::string> i_additional)105f5210bb6SBen Tyner void createPelCustom(std::vector<uint8_t>& i_rawPel,
106f5210bb6SBen Tyner std::map<std::string, std::string> i_additional)
107f5210bb6SBen Tyner {
108f5210bb6SBen Tyner // create PEL object from buffer
109f5210bb6SBen Tyner auto tiPel = std::make_unique<pel::PelMinimal>(i_rawPel);
110f5210bb6SBen Tyner
111f5210bb6SBen Tyner // The additional data contains the TI info as well as the value for the
112f5210bb6SBen Tyner // subystem that provided the TI info. Get the subystem from additional
113c49d20b9Saustinfcui // data and then populate the primary SRC and SRC words for the custom PEL
114c49d20b9Saustinfcui // based on the subsystem's TI info.
115c49d20b9Saustinfcui std::map<std::string, std::string>::iterator it;
116c49d20b9Saustinfcui uint8_t subsystem;
117c49d20b9Saustinfcui
118c49d20b9Saustinfcui it = i_additional.find("Subsystem");
119c49d20b9Saustinfcui if (it != i_additional.end())
120c49d20b9Saustinfcui {
121c49d20b9Saustinfcui subsystem = std::stoi(it->second);
122f5210bb6SBen Tyner tiPel->setSubsystem(subsystem);
123c49d20b9Saustinfcui }
124c49d20b9Saustinfcui else
125c49d20b9Saustinfcui {
126c49d20b9Saustinfcui // The entry with key "Subsystem" does not exist in the additional map.
127c49d20b9Saustinfcui // Log the error, create failure event, and return.
12867b8229bSZane Shelley trace::err("Error the key Subsystem does not exist in the map.");
129c49d20b9Saustinfcui eventAttentionFail((int)AttnSection::attnLogging | ATTN_INVALID_KEY);
130c49d20b9Saustinfcui return;
131c49d20b9Saustinfcui }
132f5210bb6SBen Tyner
133135793a8SBen Tyner // If recoverable attentions are active we will call the analyzer and
134135793a8SBen Tyner // then link the custom pel to analyzer pel.
135135793a8SBen Tyner it = i_additional.find("recoverables");
136135793a8SBen Tyner if (it != i_additional.end() && "true" == it->second)
137135793a8SBen Tyner {
138135793a8SBen Tyner DumpParameters dumpParameters;
139ebff0d37SZane Shelley auto plid = analyzer::analyzeHardware(
140ebff0d37SZane Shelley analyzer::AnalysisType::TERMINATE_IMMEDIATE, dumpParameters);
141611b3442SZane Shelley if (0 != plid)
142135793a8SBen Tyner {
143611b3442SZane Shelley // Link the PLID if an attention was found and a PEL was generated.
144611b3442SZane Shelley tiPel->setPlid(plid);
145135793a8SBen Tyner }
146135793a8SBen Tyner }
147135793a8SBen Tyner
148f5210bb6SBen Tyner if (static_cast<uint8_t>(pel::SubsystemID::hypervisor) == subsystem)
149f5210bb6SBen Tyner {
150f5210bb6SBen Tyner // populate hypervisor SRC words
151f5210bb6SBen Tyner tiPel->setSrcWords(std::array<uint32_t, pel::numSrcWords>{
152f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x10 SRC Word 12"], 0, 16),
153f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x14 SRC Word 13"], 0, 16),
154f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x18 SRC Word 14"], 0, 16),
155f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x1c SRC Word 15"], 0, 16),
156f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x20 SRC Word 16"], 0, 16),
157f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x24 SRC Word 17"], 0, 16),
158f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x28 SRC Word 18"], 0, 16),
159f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x2c SRC Word 19"], 0, 16)});
160f5210bb6SBen Tyner
1619d4f91cdSBen Tyner // Populate phyp primary SRC
1629d4f91cdSBen Tyner
1639d4f91cdSBen Tyner // char array for raw pel src
164f5210bb6SBen Tyner std::array<char, pel::asciiStringSize> srcChars{'0'};
165c49d20b9Saustinfcui std::string srcString;
1669d4f91cdSBen Tyner
1679d4f91cdSBen Tyner // src from TI info
168c49d20b9Saustinfcui it = i_additional.find("SrcAscii");
169c49d20b9Saustinfcui if (it != i_additional.end())
170c49d20b9Saustinfcui {
171c49d20b9Saustinfcui srcString = it->second;
172c49d20b9Saustinfcui }
173c49d20b9Saustinfcui else
174c49d20b9Saustinfcui {
175c49d20b9Saustinfcui // The entry with key "Subsystem" does not exist in the additional
176c49d20b9Saustinfcui // map. Log the error, create failure event, and return.
17767b8229bSZane Shelley trace::err("Error the key SrcAscii does not exist in the map.");
178a0c724d3SPatrick Williams eventAttentionFail(
179a0c724d3SPatrick Williams (int)AttnSection::attnLogging | ATTN_INVALID_KEY);
180c49d20b9Saustinfcui return;
181c49d20b9Saustinfcui }
1829d4f91cdSBen Tyner
1839d4f91cdSBen Tyner // copy from string to char array
184f5210bb6SBen Tyner srcString.copy(srcChars.data(),
185f5210bb6SBen Tyner std::min(srcString.size(), pel::asciiStringSize), 0);
1869d4f91cdSBen Tyner
1879d4f91cdSBen Tyner tiPel->setAsciiString(srcChars); // pel object src is char array
188feeea83bSBen Tyner
189feeea83bSBen Tyner // set symptom-id
190c49d20b9Saustinfcui auto symptomId = (srcString.substr(0, 8) + '_');
191feeea83bSBen Tyner
192feeea83bSBen Tyner symptomId += (i_additional["0x10 SRC Word 12"]);
193feeea83bSBen Tyner symptomId += (i_additional["0x14 SRC Word 13"] + '_');
194feeea83bSBen Tyner symptomId += (i_additional["0x18 SRC Word 14"]);
195feeea83bSBen Tyner symptomId += (i_additional["0x1c SRC Word 15"] + '_');
196feeea83bSBen Tyner symptomId += (i_additional["0x20 SRC Word 16"]);
197feeea83bSBen Tyner symptomId += (i_additional["0x24 SRC Word 17"] + '_');
198feeea83bSBen Tyner symptomId += (i_additional["0x28 SRC Word 18"]);
199feeea83bSBen Tyner symptomId += (i_additional["0x2c SRC Word 19"]);
200feeea83bSBen Tyner
201feeea83bSBen Tyner // setSymptomId will take care of required null-terminate and padding
202feeea83bSBen Tyner tiPel->setSymptomId(symptomId);
203f5210bb6SBen Tyner }
204f5210bb6SBen Tyner else
205f5210bb6SBen Tyner {
206f5210bb6SBen Tyner // Populate hostboot SRC words - note HB word 0 from the shared info
207f5210bb6SBen Tyner // data (additional data "0x10 HB Word") is reflected in the PEL as
208f5210bb6SBen Tyner // "reason code" so we zero it here. Also note that the first word
209f5210bb6SBen Tyner // in this group of words starts at word 0 and word 1 does not exits.
210f5210bb6SBen Tyner tiPel->setSrcWords(std::array<uint32_t, pel::numSrcWords>{
211f5210bb6SBen Tyner (uint32_t)0x00000000,
212f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x14 HB Word 2"], 0, 16),
213f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x18 HB Word 3"], 0, 16),
214f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x1c HB Word 4"], 0, 16),
215f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x20 HB Word 5"], 0, 16),
216f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x24 HB Word 6"], 0, 16),
217f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x28 HB Word 7"], 0, 16),
218f5210bb6SBen Tyner (uint32_t)std::stoul(i_additional["0x2c HB Word 8"], 0, 16)});
219f5210bb6SBen Tyner
2209d4f91cdSBen Tyner // Populate hostboot primary SRC
2219d4f91cdSBen Tyner
2229d4f91cdSBen Tyner // char array for raw pel src
223f5210bb6SBen Tyner std::array<char, pel::asciiStringSize> srcChars{'0'};
224c49d20b9Saustinfcui std::string srcString;
2259d4f91cdSBen Tyner
2269d4f91cdSBen Tyner // src from TI info
227c49d20b9Saustinfcui it = i_additional.find("SrcAscii");
228c49d20b9Saustinfcui if (it != i_additional.end())
229c49d20b9Saustinfcui {
230c49d20b9Saustinfcui srcString = it->second;
231c49d20b9Saustinfcui }
232c49d20b9Saustinfcui else
233c49d20b9Saustinfcui {
234c49d20b9Saustinfcui // The entry with key "Subsystem" does not exist in the additional
235c49d20b9Saustinfcui // map. Log the error, create failure event, and return.
23667b8229bSZane Shelley trace::err("Error the key SrcAscii does not exist in the map.");
237a0c724d3SPatrick Williams eventAttentionFail(
238a0c724d3SPatrick Williams (int)AttnSection::attnLogging | ATTN_INVALID_KEY);
239c49d20b9Saustinfcui return;
240c49d20b9Saustinfcui }
2419d4f91cdSBen Tyner
2429d4f91cdSBen Tyner // copy from string to char array
243f5210bb6SBen Tyner srcString.copy(srcChars.data(),
244f5210bb6SBen Tyner std::min(srcString.size(), pel::asciiStringSize), 0);
2459d4f91cdSBen Tyner
2469d4f91cdSBen Tyner tiPel->setAsciiString(srcChars); // pel object src is char array
247feeea83bSBen Tyner
248feeea83bSBen Tyner // set symptom-id
249c49d20b9Saustinfcui auto symptomId = (srcString.substr(0, 8) + '_');
250feeea83bSBen Tyner
251feeea83bSBen Tyner symptomId += (i_additional["0x10 HB Word 0"]); // note: word 1
252feeea83bSBen Tyner symptomId += (i_additional["0x14 HB Word 2"] + '_'); // does not exist
253feeea83bSBen Tyner symptomId += (i_additional["0x18 HB Word 3"]);
254feeea83bSBen Tyner symptomId += (i_additional["0x1c HB Word 4"] + '_');
255feeea83bSBen Tyner symptomId += (i_additional["0x20 HB Word 5"]);
256feeea83bSBen Tyner symptomId += (i_additional["0x24 HB Word 6"] + '_');
257feeea83bSBen Tyner symptomId += (i_additional["0x28 HB Word 7"]);
258feeea83bSBen Tyner symptomId += (i_additional["0x2c HB Word 8"]);
259feeea83bSBen Tyner
260feeea83bSBen Tyner // setSymptomId will take care of required null-terminate and padding
261feeea83bSBen Tyner tiPel->setSymptomId(symptomId);
262f5210bb6SBen Tyner }
263f5210bb6SBen Tyner
264f5210bb6SBen Tyner // set severity, event type and action flags
265f5210bb6SBen Tyner tiPel->setSeverity(static_cast<uint8_t>(pel::Severity::termination));
266f5210bb6SBen Tyner tiPel->setType(static_cast<uint8_t>(pel::EventType::na));
267ac5bd05cSBen Tyner
268ac5bd05cSBen Tyner auto actionFlags = pel::ActionFlags::service | pel::ActionFlags::report |
269ac5bd05cSBen Tyner pel::ActionFlags::call;
270ac5bd05cSBen Tyner
271ac5bd05cSBen Tyner it = i_additional.find("hidden");
272ac5bd05cSBen Tyner if (it != i_additional.end() && "true" == it->second)
273ac5bd05cSBen Tyner {
274ac5bd05cSBen Tyner trace::inf("making HB TI PEL hidden");
275ac5bd05cSBen Tyner actionFlags = actionFlags | pel::ActionFlags::hidden;
276ac5bd05cSBen Tyner }
277ac5bd05cSBen Tyner
278ac5bd05cSBen Tyner tiPel->setAction(static_cast<uint16_t>(actionFlags));
279f5210bb6SBen Tyner
28021cc6270SBen Tyner // The raw PEL that we used as the basis for this custom PEL contains some
28121cc6270SBen Tyner // user data sections that do not need to be in this PEL. However we do
28221cc6270SBen Tyner // want to include the raw TI information.
28321cc6270SBen Tyner int ffdcCount = 0;
28421cc6270SBen Tyner it = i_additional.find("FFDC count");
28521cc6270SBen Tyner if (it != i_additional.end())
28621cc6270SBen Tyner {
28721cc6270SBen Tyner // remove all sections except 1 (raw Ti info)
28821cc6270SBen Tyner ffdcCount = std::stoi(it->second) - 1;
28921cc6270SBen Tyner }
29021cc6270SBen Tyner tiPel->setSectionCount(tiPel->getSectionCount() - ffdcCount);
291f5210bb6SBen Tyner
292f5210bb6SBen Tyner // Update the raw PEL with the new custom PEL data
293f5210bb6SBen Tyner tiPel->raw(i_rawPel);
294f5210bb6SBen Tyner
295f5210bb6SBen Tyner // create PEL from raw data
296f5210bb6SBen Tyner createPelRaw(i_rawPel);
297f5210bb6SBen Tyner }
298f5210bb6SBen Tyner
299f5210bb6SBen Tyner /**
300f5210bb6SBen Tyner * Log an event handled by the attention handler
301f5210bb6SBen Tyner *
302f5210bb6SBen Tyner * Basic (non TI) events will generate a standard message-registry based PEL
303f5210bb6SBen Tyner *
304f5210bb6SBen Tyner * TI events will create two PEL's. One PEL will be informational and will
305f5210bb6SBen Tyner * contain trace information relevent to attention handler. The second PEL
306f5210bb6SBen Tyner * will be specific to the TI type (including the primary SRC) and will be
307f5210bb6SBen Tyner * based off of the TI information provided to the attention handler through
308f5210bb6SBen Tyner * shared TI info data area.
309f5210bb6SBen Tyner *
310f5210bb6SBen Tyner * @param i_event - The event type
311f5210bb6SBen Tyner * @param i_additional - Additional PEL data
312f5210bb6SBen Tyner * @param i_ffdc - FFDC PEL data
31390516851SBen Tyner * @param i_severity - Severity level
3147f6ce6acSBen Tyner * @return Event log Id (0 if no event log generated)
315f5210bb6SBen Tyner */
event(EventType i_event,std::map<std::string,std::string> & i_additional,const std::vector<util::FFDCFile> & i_ffdc,std::string i_severity=levelPelError)3167f6ce6acSBen Tyner uint32_t event(EventType i_event,
3177f6ce6acSBen Tyner std::map<std::string, std::string>& i_additional,
31890516851SBen Tyner const std::vector<util::FFDCFile>& i_ffdc,
31990516851SBen Tyner std::string i_severity = levelPelError)
320b1ebfcb1SBen Tyner {
3217f6ce6acSBen Tyner uint32_t pelId = 0; // assume no event log generated
3227f6ce6acSBen Tyner
323b1ebfcb1SBen Tyner bool eventValid = false; // assume no event created
324f5210bb6SBen Tyner bool tiEvent = false; // assume not a terminate event
325b1ebfcb1SBen Tyner
32621cc6270SBen Tyner // count user data sections so we can fixup custom PEL
32721cc6270SBen Tyner i_additional["FFDC count"] = std::to_string(i_ffdc.size());
32821cc6270SBen Tyner
329b1ebfcb1SBen Tyner std::string eventName;
330b1ebfcb1SBen Tyner
331b1ebfcb1SBen Tyner switch (i_event)
332b1ebfcb1SBen Tyner {
333b1ebfcb1SBen Tyner case EventType::Checkstop:
334b1ebfcb1SBen Tyner eventName = "org.open_power.HwDiags.Error.Checkstop";
335b1ebfcb1SBen Tyner eventValid = true;
336b1ebfcb1SBen Tyner break;
337b1ebfcb1SBen Tyner case EventType::Terminate:
338b1ebfcb1SBen Tyner eventName = "org.open_power.Attn.Error.Terminate";
339b1ebfcb1SBen Tyner eventValid = true;
340f5210bb6SBen Tyner tiEvent = true;
341b1ebfcb1SBen Tyner break;
342b1ebfcb1SBen Tyner case EventType::Vital:
343b1ebfcb1SBen Tyner eventName = "org.open_power.Attn.Error.Vital";
344b1ebfcb1SBen Tyner eventValid = true;
345b1ebfcb1SBen Tyner break;
346b1ebfcb1SBen Tyner case EventType::HwDiagsFail:
347b1ebfcb1SBen Tyner case EventType::AttentionFail:
348b1ebfcb1SBen Tyner eventName = "org.open_power.Attn.Error.Fail";
349b1ebfcb1SBen Tyner eventValid = true;
350b1ebfcb1SBen Tyner break;
351b1ebfcb1SBen Tyner default:
352b1ebfcb1SBen Tyner eventValid = false;
353b1ebfcb1SBen Tyner break;
354b1ebfcb1SBen Tyner }
355b1ebfcb1SBen Tyner
356b1ebfcb1SBen Tyner if (true == eventValid)
357b1ebfcb1SBen Tyner {
358f5210bb6SBen Tyner // Create PEL with additional data and FFDC data. The newly created
359f5210bb6SBen Tyner // PEL's platform log-id will be returned.
36090516851SBen Tyner pelId = util::dbus::createPel(eventName, i_severity, i_additional,
3611315968cSBen Tyner createFFDCTuples(i_ffdc));
362b1ebfcb1SBen Tyner
363f5210bb6SBen Tyner // If this is a TI event we will create an additional PEL that is
364f5210bb6SBen Tyner // specific to the subsystem that generated the TI.
365135793a8SBen Tyner if ((0 != pelId) && (true == tiEvent))
366f5210bb6SBen Tyner {
367f5210bb6SBen Tyner // get file descriptor and size of information PEL
368188f1096SBen Tyner int pelFd = getPel(pelId);
3691b1915efSBen Tyner
370f5210bb6SBen Tyner // if PEL found, read into buffer
371f5210bb6SBen Tyner if (-1 != pelFd)
372f5210bb6SBen Tyner {
373f5210bb6SBen Tyner auto pelSize = lseek(pelFd, 0, SEEK_END);
374f5210bb6SBen Tyner lseek(pelFd, 0, SEEK_SET);
3751b1915efSBen Tyner
376f5210bb6SBen Tyner // read information PEL into buffer
377f5210bb6SBen Tyner std::vector<uint8_t> buffer(pelSize);
378d700609cSBen Tyner size_t numBytes = read(pelFd, buffer.data(), buffer.size());
379d700609cSBen Tyner if (buffer.size() != numBytes)
380d700609cSBen Tyner {
381bfa831a8Saustinfcui trace::err("Error reading event log: %u of %u bytes read",
382bfa831a8Saustinfcui numBytes, buffer.size());
383d700609cSBen Tyner }
384d700609cSBen Tyner else
385d700609cSBen Tyner {
386f5210bb6SBen Tyner // create PEL from buffer
387f5210bb6SBen Tyner createPelCustom(buffer, i_additional);
388f5210bb6SBen Tyner }
389d700609cSBen Tyner
390d700609cSBen Tyner close(pelFd);
391d700609cSBen Tyner }
3925c5db65aSBen Tyner
393c49d20b9Saustinfcui std::map<std::string, std::string>::iterator it;
394c49d20b9Saustinfcui uint8_t subsystem;
395c49d20b9Saustinfcui
396c49d20b9Saustinfcui it = i_additional.find("Subsystem");
397c49d20b9Saustinfcui if (it != i_additional.end())
398c49d20b9Saustinfcui {
399c49d20b9Saustinfcui subsystem = std::stoi(it->second);
400c49d20b9Saustinfcui }
401c49d20b9Saustinfcui else
402c49d20b9Saustinfcui {
403c49d20b9Saustinfcui // The entry with key "Subsystem" does not exist in the
404c49d20b9Saustinfcui // additional map. Log the error, create failure event, and
405c49d20b9Saustinfcui // return.
40667b8229bSZane Shelley trace::err(
40767b8229bSZane Shelley "Error the key Subsystem does not exist in the map.");
408a0c724d3SPatrick Williams eventAttentionFail(
409a0c724d3SPatrick Williams (int)AttnSection::attnLogging | ATTN_INVALID_KEY);
410c49d20b9Saustinfcui return 0;
411c49d20b9Saustinfcui }
4125c5db65aSBen Tyner
4135c5db65aSBen Tyner // If not hypervisor TI
4145c5db65aSBen Tyner if (static_cast<uint8_t>(pel::SubsystemID::hypervisor) != subsystem)
4155c5db65aSBen Tyner {
4165c5db65aSBen Tyner // Request a dump and transition the host
4175c5db65aSBen Tyner if ("true" == i_additional["Dump"])
4185c5db65aSBen Tyner {
4196bc43c9bSBen Tyner // will not return until dump is complete
420611b3442SZane Shelley requestDump(pelId, DumpParameters{0, DumpType::Hostboot});
4216bc43c9bSBen Tyner }
4225c5db65aSBen Tyner }
4235c5db65aSBen Tyner }
424b1ebfcb1SBen Tyner }
4257f6ce6acSBen Tyner return pelId;
426b1ebfcb1SBen Tyner }
427b1ebfcb1SBen Tyner
428f5210bb6SBen Tyner /**
429f5210bb6SBen Tyner * Commit special attention TI event to log
430f5210bb6SBen Tyner *
431f5210bb6SBen Tyner * Create a event log with provided additional information and standard
432f5210bb6SBen Tyner * FFDC data plus TI FFDC data
433f5210bb6SBen Tyner *
434f5210bb6SBen Tyner * @param i_additional - Additional log data
435f5210bb6SBen Tyner * @param i_ti_InfoData - TI FFDC data
436f5210bb6SBen Tyner */
eventTerminate(std::map<std::string,std::string> i_additionalData,char * i_tiInfoData)437f5210bb6SBen Tyner void eventTerminate(std::map<std::string, std::string> i_additionalData,
438f5210bb6SBen Tyner char* i_tiInfoData)
439b1ebfcb1SBen Tyner {
44029651ef8SBen Tyner uint32_t tiInfoSize = 0; // assume TI info was not available
44129651ef8SBen Tyner
44229651ef8SBen Tyner if (nullptr != i_tiInfoData)
44329651ef8SBen Tyner {
44429651ef8SBen Tyner tiInfoSize = 56; // assume not hypervisor TI
445b6401edfSBen Tyner
446c49d20b9Saustinfcui std::map<std::string, std::string>::iterator it;
447c49d20b9Saustinfcui uint8_t subsystem;
448c49d20b9Saustinfcui
449c49d20b9Saustinfcui it = i_additionalData.find("Subsystem");
450c49d20b9Saustinfcui if (it != i_additionalData.end())
451c49d20b9Saustinfcui {
452c49d20b9Saustinfcui subsystem = std::stoi(it->second);
453c49d20b9Saustinfcui }
454c49d20b9Saustinfcui else
455c49d20b9Saustinfcui {
456c49d20b9Saustinfcui // The entry with key "Subsystem" does not exist in the additional
457c49d20b9Saustinfcui // map. Log the error, create failure event, and return.
45867b8229bSZane Shelley trace::err("Error the key Subsystem does not exist in the map.");
459a0c724d3SPatrick Williams eventAttentionFail(
460a0c724d3SPatrick Williams (int)AttnSection::attnLogging | ATTN_INVALID_KEY);
461c49d20b9Saustinfcui return;
462c49d20b9Saustinfcui }
463b6401edfSBen Tyner
464b6401edfSBen Tyner // If hypervisor
465b6401edfSBen Tyner if (static_cast<uint8_t>(pel::SubsystemID::hypervisor) == subsystem)
466b6401edfSBen Tyner {
467b6401edfSBen Tyner tiInfoSize = 1024; // assume hypervisor max
468b6401edfSBen Tyner
469b6401edfSBen Tyner // hypervisor may just want some of the data
470b6401edfSBen Tyner if (0 == (*(i_tiInfoData + 0x09) & 0x01))
471b6401edfSBen Tyner {
472b6401edfSBen Tyner uint32_t* additionalLength = (uint32_t*)(i_tiInfoData + 0x50);
473b6401edfSBen Tyner uint32_t tiAdditional = be32toh(*additionalLength);
474b6401edfSBen Tyner tiInfoSize = std::min(tiInfoSize, (84 + tiAdditional));
475b6401edfSBen Tyner }
476b6401edfSBen Tyner }
47729651ef8SBen Tyner }
478b6401edfSBen Tyner
479bfa831a8Saustinfcui trace::inf("TI info size = %u", tiInfoSize);
480b6401edfSBen Tyner
4814d3f093aSZane Shelley event(EventType::Terminate, i_additionalData,
4824d3f093aSZane Shelley createFFDCFiles(i_tiInfoData, tiInfoSize));
483b1ebfcb1SBen Tyner }
484b1ebfcb1SBen Tyner
4857f6ce6acSBen Tyner /** @brief Commit SBE vital event to log, returns event log ID */
eventVital(std::string severity)48690516851SBen Tyner uint32_t eventVital(std::string severity)
487b1ebfcb1SBen Tyner {
488f5210bb6SBen Tyner // Additional data for log
489b1ebfcb1SBen Tyner std::map<std::string, std::string> additionalData;
490b1ebfcb1SBen Tyner
491f5210bb6SBen Tyner // Create log event with additional data and FFDC data
49290516851SBen Tyner return event(EventType::Vital, additionalData, createFFDCFiles(nullptr, 0),
49390516851SBen Tyner severity);
494b1ebfcb1SBen Tyner }
495b1ebfcb1SBen Tyner
496f5210bb6SBen Tyner /**
497f5210bb6SBen Tyner * Commit attention handler failure event to log
498f5210bb6SBen Tyner *
499f5210bb6SBen Tyner * Create an event log containing the specified error code.
500f5210bb6SBen Tyner *
501f5210bb6SBen Tyner * @param i_error - Error code
502f5210bb6SBen Tyner */
eventAttentionFail(int i_error)503f5210bb6SBen Tyner void eventAttentionFail(int i_error)
504f5210bb6SBen Tyner {
505f5210bb6SBen Tyner // Additional data for log
506f5210bb6SBen Tyner std::map<std::string, std::string> additionalData;
507f5210bb6SBen Tyner additionalData["ERROR_CODE"] = std::to_string(i_error);
508f5210bb6SBen Tyner
509f5210bb6SBen Tyner // Create log event with additional data and FFDC data
510f5210bb6SBen Tyner event(EventType::AttentionFail, additionalData,
511f5210bb6SBen Tyner createFFDCFiles(nullptr, 0));
512f5210bb6SBen Tyner }
513f5210bb6SBen Tyner
514b1ebfcb1SBen Tyner } // namespace attn
515