1d84ed6e9SZane Shelley #include <assert.h>
287eabc65SBen Tyner #include <libpdbg.h>
39fb7393eSZane Shelley #include <unistd.h>
487eabc65SBen Tyner 
50205f3b3SBen Tyner #include <hei_main.hpp>
69fb7393eSZane Shelley #include <phosphor-logging/log.hpp>
7f4bd5ff6SZane Shelley #include <util/pdbg.hpp>
8d84ed6e9SZane Shelley #include <util/trace.hpp>
90205f3b3SBen Tyner 
10d84ed6e9SZane Shelley #include <algorithm>
1187eabc65SBen Tyner #include <fstream>
1287eabc65SBen Tyner #include <iostream>
13b1ebfcb1SBen Tyner #include <map>
14b1ebfcb1SBen Tyner #include <string>
15b1ebfcb1SBen Tyner 
160205f3b3SBen Tyner namespace analyzer
170205f3b3SBen Tyner {
180205f3b3SBen Tyner 
19f4bd5ff6SZane Shelley //------------------------------------------------------------------------------
20b1ebfcb1SBen Tyner 
21f4bd5ff6SZane Shelley // Forward references for externally defined functions.
2287eabc65SBen Tyner 
23d3b9bac9SZane Shelley /**
24d3b9bac9SZane Shelley  * @brief Will get the list of active chip and initialize the isolator.
25d3b9bac9SZane Shelley  * @param o_chips The returned list of active chips.
26d3b9bac9SZane Shelley  */
27171a2e04SZane Shelley void initializeIsolator(std::vector<libhei::Chip>& o_chips);
2887eabc65SBen Tyner 
29d3b9bac9SZane Shelley /**
30d3b9bac9SZane Shelley  * @brief Will create and submit a PEL using the given data.
31d3b9bac9SZane Shelley  * @param i_rootCause A signature defining the attention root cause.
32d3b9bac9SZane Shelley  * @param i_isoData   The data gathered during isolation (for FFDC).
33d3b9bac9SZane Shelley  */
34d3b9bac9SZane Shelley void createPel(const libhei::Signature& i_rootCause,
35d3b9bac9SZane Shelley                const libhei::IsolationData& i_isoData);
36d3b9bac9SZane Shelley 
37d84ed6e9SZane Shelley //------------------------------------------------------------------------------
38d84ed6e9SZane Shelley 
392f263181SZane Shelley const char* __attn(libhei::AttentionType_t i_attnType)
402f263181SZane Shelley {
412f263181SZane Shelley     const char* str = "";
422f263181SZane Shelley     switch (i_attnType)
432f263181SZane Shelley     {
442f263181SZane Shelley         case libhei::ATTN_TYPE_CHECKSTOP:
452f263181SZane Shelley             str = "CHECKSTOP";
462f263181SZane Shelley             break;
472f263181SZane Shelley         case libhei::ATTN_TYPE_UNIT_CS:
482f263181SZane Shelley             str = "UNIT_CS";
492f263181SZane Shelley             break;
502f263181SZane Shelley         case libhei::ATTN_TYPE_RECOVERABLE:
512f263181SZane Shelley             str = "RECOVERABLE";
522f263181SZane Shelley             break;
532f263181SZane Shelley         case libhei::ATTN_TYPE_SP_ATTN:
542f263181SZane Shelley             str = "SP_ATTN";
552f263181SZane Shelley             break;
562f263181SZane Shelley         case libhei::ATTN_TYPE_HOST_ATTN:
572f263181SZane Shelley             str = "HOST_ATTN";
582f263181SZane Shelley             break;
592f263181SZane Shelley         default:
602f263181SZane Shelley             trace::err("Unsupported attention type: %u", i_attnType);
612f263181SZane Shelley             assert(0);
622f263181SZane Shelley     }
632f263181SZane Shelley     return str;
642f263181SZane Shelley }
652f263181SZane Shelley 
662f263181SZane Shelley //------------------------------------------------------------------------------
672f263181SZane Shelley 
68*cb457383SZane Shelley bool __filterRootCause(const libhei::IsolationData& i_isoData,
69*cb457383SZane Shelley                        libhei::Signature& o_signature)
70097a71adSZane Shelley {
71*cb457383SZane Shelley     // We'll need to make a copy of the list so that the original list is
72*cb457383SZane Shelley     // maintained for the log.
73*cb457383SZane Shelley     std::vector<libhei::Signature> sigList{i_isoData.getSignatureList()};
74*cb457383SZane Shelley 
752f263181SZane Shelley     // For debug, trace out the original list of signatures before filtering.
76*cb457383SZane Shelley     for (const auto& sig : sigList)
772f263181SZane Shelley     {
78f4bd5ff6SZane Shelley         trace::inf("Signature: %s 0x%0" PRIx32 " %s",
79*cb457383SZane Shelley                    util::pdbg::getPath(sig.getChip()), sig.toUint32(),
80f4bd5ff6SZane Shelley                    __attn(sig.getAttnType()));
812f263181SZane Shelley     }
822f263181SZane Shelley 
83097a71adSZane Shelley     // Special and host attentions are not supported by this user application.
84097a71adSZane Shelley     auto newEndItr =
85*cb457383SZane Shelley         std::remove_if(sigList.begin(), sigList.end(), [&](const auto& t) {
86097a71adSZane Shelley             return (libhei::ATTN_TYPE_SP_ATTN == t.getAttnType() ||
87097a71adSZane Shelley                     libhei::ATTN_TYPE_HOST_ATTN == t.getAttnType());
88097a71adSZane Shelley         });
89097a71adSZane Shelley 
90097a71adSZane Shelley     // Shrink the vector, if needed.
91*cb457383SZane Shelley     sigList.resize(std::distance(sigList.begin(), newEndItr));
92097a71adSZane Shelley 
93097a71adSZane Shelley     // START WORKAROUND
94097a71adSZane Shelley     // TODO: Filtering should be determined by the RAS Data Files provided by
95097a71adSZane Shelley     //       the host firmware via the PNOR (similar to the Chip Data Files).
96097a71adSZane Shelley     //       Until that support is available, use a rudimentary filter that
97097a71adSZane Shelley     //       first looks for any recoverable attention, then any unit checkstop,
98097a71adSZane Shelley     //       and then any system checkstop. This is built on the premise that
99097a71adSZane Shelley     //       recoverable errors could be the root cause of an system checkstop
100097a71adSZane Shelley     //       attentions. Fortunately, we just need to sort the list by the
101097a71adSZane Shelley     //       greater attention type value.
102*cb457383SZane Shelley     std::sort(sigList.begin(), sigList.end(),
103097a71adSZane Shelley               [&](const auto& a, const auto& b) {
104097a71adSZane Shelley                   return a.getAttnType() > b.getAttnType();
105097a71adSZane Shelley               });
106097a71adSZane Shelley     // END WORKAROUND
107*cb457383SZane Shelley 
108*cb457383SZane Shelley     // Check if a root cause attention was found.
109*cb457383SZane Shelley     if (!sigList.empty())
110*cb457383SZane Shelley     {
111*cb457383SZane Shelley         // The entry at the front of the list will be the root cause.
112*cb457383SZane Shelley         o_signature = sigList.front();
113*cb457383SZane Shelley         return true;
114*cb457383SZane Shelley     }
115*cb457383SZane Shelley 
116*cb457383SZane Shelley     return false; // default, no active attentions found.
117097a71adSZane Shelley }
118097a71adSZane Shelley 
119097a71adSZane Shelley //------------------------------------------------------------------------------
120097a71adSZane Shelley 
121*cb457383SZane Shelley bool __analyze(const libhei::IsolationData& i_isoData)
1229fb7393eSZane Shelley {
1239fb7393eSZane Shelley     bool attnFound = false;
1249fb7393eSZane Shelley 
125*cb457383SZane Shelley     libhei::Signature rootCause{};
126*cb457383SZane Shelley     attnFound = __filterRootCause(i_isoData, rootCause);
127*cb457383SZane Shelley 
128*cb457383SZane Shelley     if (!attnFound)
1299fb7393eSZane Shelley     {
130*cb457383SZane Shelley         // NOTE: It is possible for TI handling that there will not be an active
131*cb457383SZane Shelley         //       attention. In which case, we will not do anything and let the
132*cb457383SZane Shelley         //       caller of this function determine if this is the expected
133*cb457383SZane Shelley         //       behavior.
1349fb7393eSZane Shelley         trace::inf("No active attentions found");
1359fb7393eSZane Shelley     }
1369fb7393eSZane Shelley     else
1379fb7393eSZane Shelley     {
1389fb7393eSZane Shelley         trace::inf("Root cause attention: %s 0x%0" PRIx32 " %s",
139*cb457383SZane Shelley                    util::pdbg::getPath(rootCause.getChip()),
140*cb457383SZane Shelley                    rootCause.toUint32(), __attn(rootCause.getAttnType()));
141*cb457383SZane Shelley 
142*cb457383SZane Shelley         // TODO: Perform service actions based on the root cause.
143d3b9bac9SZane Shelley 
144d3b9bac9SZane Shelley         // Create and commit a PEL.
145*cb457383SZane Shelley         createPel(rootCause, i_isoData);
1469fb7393eSZane Shelley     }
1479fb7393eSZane Shelley 
1489fb7393eSZane Shelley     return attnFound;
1499fb7393eSZane Shelley }
1509fb7393eSZane Shelley 
1519fb7393eSZane Shelley //------------------------------------------------------------------------------
1529fb7393eSZane Shelley 
1539fb7393eSZane Shelley bool analyzeHardware()
15487eabc65SBen Tyner {
155097a71adSZane Shelley     bool attnFound = false;
15687eabc65SBen Tyner 
1572f263181SZane Shelley     trace::inf(">>> enter analyzeHardware()");
1582f263181SZane Shelley 
1597ae9c8c7SZane Shelley     if (util::pdbg::queryHardwareAnalysisSupported())
1607ae9c8c7SZane Shelley     {
161171a2e04SZane Shelley         // Initialize the isolator and get all of the chips to be analyzed.
162f4bd5ff6SZane Shelley         trace::inf("Initializing the isolator...");
163171a2e04SZane Shelley         std::vector<libhei::Chip> chips;
164f4bd5ff6SZane Shelley         initializeIsolator(chips);
1652e994bcdSZane Shelley 
166097a71adSZane Shelley         // Isolate attentions.
167f4bd5ff6SZane Shelley         trace::inf("Isolating errors: # of chips=%u", chips.size());
168097a71adSZane Shelley         libhei::IsolationData isoData{};
169f4bd5ff6SZane Shelley         libhei::isolate(chips, isoData);
17087eabc65SBen Tyner 
171*cb457383SZane Shelley         // Analyze the isolation data and perform service actions if needed.
172*cb457383SZane Shelley         attnFound = __analyze(isoData);
17387eabc65SBen Tyner 
174097a71adSZane Shelley         // All done, clean up the isolator.
175f4bd5ff6SZane Shelley         trace::inf("Uninitializing isolator...");
176097a71adSZane Shelley         libhei::uninitialize();
1777ae9c8c7SZane Shelley     }
1787ae9c8c7SZane Shelley     else
1797ae9c8c7SZane Shelley     {
1807ae9c8c7SZane Shelley         trace::err("Hardware error analysis is not supported on this system");
1817ae9c8c7SZane Shelley     }
182b1ebfcb1SBen Tyner 
1832f263181SZane Shelley     trace::inf("<<< exit analyzeHardware()");
1842f263181SZane Shelley 
185097a71adSZane Shelley     return attnFound;
1860205f3b3SBen Tyner }
1870205f3b3SBen Tyner 
1880205f3b3SBen Tyner } // namespace analyzer
189