1d84ed6e9SZane Shelley #include <assert.h>
287eabc65SBen Tyner #include <libpdbg.h>
39fb7393eSZane Shelley #include <unistd.h>
487eabc65SBen Tyner 
5a9b44344SZane Shelley #include <analyzer/ras-data/ras-data-parser.hpp>
64ed4be56SZane Shelley #include <analyzer/service_data.hpp>
7*7029e525SBen Tyner #include <attn/attn_dump.hpp>
80205f3b3SBen Tyner #include <hei_main.hpp>
99fb7393eSZane Shelley #include <phosphor-logging/log.hpp>
10f4bd5ff6SZane Shelley #include <util/pdbg.hpp>
11d84ed6e9SZane Shelley #include <util/trace.hpp>
120205f3b3SBen Tyner 
13d84ed6e9SZane Shelley #include <algorithm>
1487eabc65SBen Tyner #include <fstream>
1587eabc65SBen Tyner #include <iostream>
16b1ebfcb1SBen Tyner #include <map>
17b1ebfcb1SBen Tyner #include <string>
18b1ebfcb1SBen Tyner 
190205f3b3SBen Tyner namespace analyzer
200205f3b3SBen Tyner {
210205f3b3SBen Tyner 
22f4bd5ff6SZane Shelley //------------------------------------------------------------------------------
23b1ebfcb1SBen Tyner 
24f4bd5ff6SZane Shelley // Forward references for externally defined functions.
2587eabc65SBen Tyner 
26d3b9bac9SZane Shelley /**
27d3b9bac9SZane Shelley  * @brief Will get the list of active chip and initialize the isolator.
28d3b9bac9SZane Shelley  * @param o_chips The returned list of active chips.
29d3b9bac9SZane Shelley  */
30171a2e04SZane Shelley void initializeIsolator(std::vector<libhei::Chip>& o_chips);
3187eabc65SBen Tyner 
32d3b9bac9SZane Shelley /**
33d3b9bac9SZane Shelley  * @brief Will create and submit a PEL using the given data.
34d3b9bac9SZane Shelley  * @param i_isoData   The data gathered during isolation (for FFDC).
354ed4be56SZane Shelley  * @param i_servData  Data regarding service actions gathered during analysis.
36*7029e525SBen Tyner  * @return Tuple of BMC log id, platform log id
37d3b9bac9SZane Shelley  */
38*7029e525SBen Tyner std::tuple<uint32_t, uint32_t> createPel(const libhei::IsolationData& i_isoData,
394ed4be56SZane Shelley                                          const ServiceData& i_servData);
40d3b9bac9SZane Shelley 
41d84ed6e9SZane Shelley //------------------------------------------------------------------------------
42d84ed6e9SZane Shelley 
432f263181SZane Shelley const char* __attn(libhei::AttentionType_t i_attnType)
442f263181SZane Shelley {
452f263181SZane Shelley     const char* str = "";
462f263181SZane Shelley     switch (i_attnType)
472f263181SZane Shelley     {
482f263181SZane Shelley         case libhei::ATTN_TYPE_CHECKSTOP:
492f263181SZane Shelley             str = "CHECKSTOP";
502f263181SZane Shelley             break;
512f263181SZane Shelley         case libhei::ATTN_TYPE_UNIT_CS:
522f263181SZane Shelley             str = "UNIT_CS";
532f263181SZane Shelley             break;
542f263181SZane Shelley         case libhei::ATTN_TYPE_RECOVERABLE:
552f263181SZane Shelley             str = "RECOVERABLE";
562f263181SZane Shelley             break;
572f263181SZane Shelley         case libhei::ATTN_TYPE_SP_ATTN:
582f263181SZane Shelley             str = "SP_ATTN";
592f263181SZane Shelley             break;
602f263181SZane Shelley         case libhei::ATTN_TYPE_HOST_ATTN:
612f263181SZane Shelley             str = "HOST_ATTN";
622f263181SZane Shelley             break;
632f263181SZane Shelley         default:
642f263181SZane Shelley             trace::err("Unsupported attention type: %u", i_attnType);
652f263181SZane Shelley             assert(0);
662f263181SZane Shelley     }
672f263181SZane Shelley     return str;
682f263181SZane Shelley }
692f263181SZane Shelley 
702f263181SZane Shelley //------------------------------------------------------------------------------
712f263181SZane Shelley 
72cb457383SZane Shelley bool __filterRootCause(const libhei::IsolationData& i_isoData,
73cb457383SZane Shelley                        libhei::Signature& o_signature)
74097a71adSZane Shelley {
75cb457383SZane Shelley     // We'll need to make a copy of the list so that the original list is
76cb457383SZane Shelley     // maintained for the log.
77cb457383SZane Shelley     std::vector<libhei::Signature> sigList{i_isoData.getSignatureList()};
78cb457383SZane Shelley 
792f263181SZane Shelley     // For debug, trace out the original list of signatures before filtering.
80cb457383SZane Shelley     for (const auto& sig : sigList)
812f263181SZane Shelley     {
82f4bd5ff6SZane Shelley         trace::inf("Signature: %s 0x%0" PRIx32 " %s",
83cb457383SZane Shelley                    util::pdbg::getPath(sig.getChip()), sig.toUint32(),
84f4bd5ff6SZane Shelley                    __attn(sig.getAttnType()));
852f263181SZane Shelley     }
862f263181SZane Shelley 
87097a71adSZane Shelley     // Special and host attentions are not supported by this user application.
88097a71adSZane Shelley     auto newEndItr =
89cb457383SZane Shelley         std::remove_if(sigList.begin(), sigList.end(), [&](const auto& t) {
90097a71adSZane Shelley             return (libhei::ATTN_TYPE_SP_ATTN == t.getAttnType() ||
91097a71adSZane Shelley                     libhei::ATTN_TYPE_HOST_ATTN == t.getAttnType());
92097a71adSZane Shelley         });
93097a71adSZane Shelley 
94097a71adSZane Shelley     // Shrink the vector, if needed.
95cb457383SZane Shelley     sigList.resize(std::distance(sigList.begin(), newEndItr));
96097a71adSZane Shelley 
97097a71adSZane Shelley     // START WORKAROUND
98097a71adSZane Shelley     // TODO: Filtering should be determined by the RAS Data Files provided by
99097a71adSZane Shelley     //       the host firmware via the PNOR (similar to the Chip Data Files).
100097a71adSZane Shelley     //       Until that support is available, use a rudimentary filter that
101097a71adSZane Shelley     //       first looks for any recoverable attention, then any unit checkstop,
102097a71adSZane Shelley     //       and then any system checkstop. This is built on the premise that
103097a71adSZane Shelley     //       recoverable errors could be the root cause of an system checkstop
104097a71adSZane Shelley     //       attentions. Fortunately, we just need to sort the list by the
105097a71adSZane Shelley     //       greater attention type value.
106cb457383SZane Shelley     std::sort(sigList.begin(), sigList.end(),
107097a71adSZane Shelley               [&](const auto& a, const auto& b) {
108097a71adSZane Shelley                   return a.getAttnType() > b.getAttnType();
109097a71adSZane Shelley               });
110097a71adSZane Shelley     // END WORKAROUND
111cb457383SZane Shelley 
112cb457383SZane Shelley     // Check if a root cause attention was found.
113cb457383SZane Shelley     if (!sigList.empty())
114cb457383SZane Shelley     {
115cb457383SZane Shelley         // The entry at the front of the list will be the root cause.
116cb457383SZane Shelley         o_signature = sigList.front();
117cb457383SZane Shelley         return true;
118cb457383SZane Shelley     }
119cb457383SZane Shelley 
120cb457383SZane Shelley     return false; // default, no active attentions found.
121097a71adSZane Shelley }
122097a71adSZane Shelley 
123097a71adSZane Shelley //------------------------------------------------------------------------------
124097a71adSZane Shelley 
125*7029e525SBen Tyner bool analyzeHardware(attn::DumpParameters& o_dumpParameters)
12687eabc65SBen Tyner {
127097a71adSZane Shelley     bool attnFound = false;
12887eabc65SBen Tyner 
129e5411f0fSZane Shelley     if (!util::pdbg::queryHardwareAnalysisSupported())
130e5411f0fSZane Shelley     {
131e5411f0fSZane Shelley         trace::err("Hardware error analysis is not supported on this system");
132e5411f0fSZane Shelley         return attnFound;
133e5411f0fSZane Shelley     }
134e5411f0fSZane Shelley 
1352f263181SZane Shelley     trace::inf(">>> enter analyzeHardware()");
1362f263181SZane Shelley 
137171a2e04SZane Shelley     // Initialize the isolator and get all of the chips to be analyzed.
138f4bd5ff6SZane Shelley     trace::inf("Initializing the isolator...");
139171a2e04SZane Shelley     std::vector<libhei::Chip> chips;
140f4bd5ff6SZane Shelley     initializeIsolator(chips);
1412e994bcdSZane Shelley 
142097a71adSZane Shelley     // Isolate attentions.
143f4bd5ff6SZane Shelley     trace::inf("Isolating errors: # of chips=%u", chips.size());
144097a71adSZane Shelley     libhei::IsolationData isoData{};
145f4bd5ff6SZane Shelley     libhei::isolate(chips, isoData);
14687eabc65SBen Tyner 
147e5411f0fSZane Shelley     // Filter for root cause attention.
148e5411f0fSZane Shelley     libhei::Signature rootCause{};
149e5411f0fSZane Shelley     attnFound = __filterRootCause(isoData, rootCause);
150e5411f0fSZane Shelley 
151e5411f0fSZane Shelley     if (!attnFound)
152e5411f0fSZane Shelley     {
153e5411f0fSZane Shelley         // It is possible for TI handling, or manually initiated analysis via
154e5411f0fSZane Shelley         // the command line, that there will not be an active attention. In
155e5411f0fSZane Shelley         // which case, we will do nothing and let the caller of this function
156e5411f0fSZane Shelley         // determine if this is the expected behavior.
157e5411f0fSZane Shelley         trace::inf("No active attentions found");
158e5411f0fSZane Shelley     }
159e5411f0fSZane Shelley     else
160e5411f0fSZane Shelley     {
161e5411f0fSZane Shelley         trace::inf("Root cause attention: %s 0x%0" PRIx32 " %s",
162e5411f0fSZane Shelley                    util::pdbg::getPath(rootCause.getChip()),
163e5411f0fSZane Shelley                    rootCause.toUint32(), __attn(rootCause.getAttnType()));
164e5411f0fSZane Shelley 
165e5411f0fSZane Shelley         // Perform service actions based on the root cause.
166a9b44344SZane Shelley         RasDataParser rasData{};
167ca496198SZane Shelley         ServiceData servData{rootCause, isoData.queryCheckstop()};
168a9b44344SZane Shelley         rasData.getResolution(rootCause)->resolve(servData);
169e5411f0fSZane Shelley 
170e5411f0fSZane Shelley         // Create and commit a PEL.
171*7029e525SBen Tyner         uint32_t logId = std::get<1>(createPel(isoData, servData));
172*7029e525SBen Tyner 
173*7029e525SBen Tyner         // Populate dump parameters
174*7029e525SBen Tyner         o_dumpParameters.logId    = logId;
175*7029e525SBen Tyner         o_dumpParameters.unitId   = 0;
176*7029e525SBen Tyner         o_dumpParameters.dumpType = attn::DumpType::Hardware;
177e5411f0fSZane Shelley     }
17887eabc65SBen Tyner 
179097a71adSZane Shelley     // All done, clean up the isolator.
180f4bd5ff6SZane Shelley     trace::inf("Uninitializing isolator...");
181097a71adSZane Shelley     libhei::uninitialize();
182b1ebfcb1SBen Tyner 
1832f263181SZane Shelley     trace::inf("<<< exit analyzeHardware()");
1842f263181SZane Shelley 
185097a71adSZane Shelley     return attnFound;
1860205f3b3SBen Tyner }
1870205f3b3SBen Tyner 
188eea45427SBen Tyner //------------------------------------------------------------------------------
189eea45427SBen Tyner 
190eea45427SBen Tyner /**
191eea45427SBen Tyner  * @brief Get error isolator build information
192eea45427SBen Tyner  *
193eea45427SBen Tyner  * @return Pointer to build information
194eea45427SBen Tyner  */
195eea45427SBen Tyner const char* getBuildInfo()
196eea45427SBen Tyner {
197eea45427SBen Tyner     return libhei::getBuildInfo();
198eea45427SBen Tyner }
199eea45427SBen Tyner 
2000205f3b3SBen Tyner } // namespace analyzer
201