1d84ed6e9SZane Shelley #include <assert.h>
287eabc65SBen Tyner #include <libpdbg.h>
39fb7393eSZane Shelley #include <unistd.h>
487eabc65SBen Tyner 
54ed4be56SZane Shelley #include <analyzer/service_data.hpp>
60205f3b3SBen Tyner #include <hei_main.hpp>
79fb7393eSZane Shelley #include <phosphor-logging/log.hpp>
8f4bd5ff6SZane Shelley #include <util/pdbg.hpp>
9d84ed6e9SZane Shelley #include <util/trace.hpp>
100205f3b3SBen Tyner 
11d84ed6e9SZane Shelley #include <algorithm>
1287eabc65SBen Tyner #include <fstream>
1387eabc65SBen Tyner #include <iostream>
14b1ebfcb1SBen Tyner #include <map>
15b1ebfcb1SBen Tyner #include <string>
16b1ebfcb1SBen Tyner 
170205f3b3SBen Tyner namespace analyzer
180205f3b3SBen Tyner {
190205f3b3SBen Tyner 
20f4bd5ff6SZane Shelley //------------------------------------------------------------------------------
21b1ebfcb1SBen Tyner 
22f4bd5ff6SZane Shelley // Forward references for externally defined functions.
2387eabc65SBen Tyner 
24d3b9bac9SZane Shelley /**
25d3b9bac9SZane Shelley  * @brief Will get the list of active chip and initialize the isolator.
26d3b9bac9SZane Shelley  * @param o_chips The returned list of active chips.
27d3b9bac9SZane Shelley  */
28171a2e04SZane Shelley void initializeIsolator(std::vector<libhei::Chip>& o_chips);
2987eabc65SBen Tyner 
30d3b9bac9SZane Shelley /**
31*e5411f0fSZane Shelley  * @brief Apply any RAS actions required by the given data.
32*e5411f0fSZane Shelley  * @param i_servData Data regarding service actions gathered during analysis.
33*e5411f0fSZane Shelley  */
34*e5411f0fSZane Shelley void applyRasActions(ServiceData& io_servData);
35*e5411f0fSZane Shelley 
36*e5411f0fSZane Shelley /**
37d3b9bac9SZane Shelley  * @brief Will create and submit a PEL using the given data.
38d3b9bac9SZane Shelley  * @param i_isoData   The data gathered during isolation (for FFDC).
394ed4be56SZane Shelley  * @param i_servData  Data regarding service actions gathered during analysis.
40d3b9bac9SZane Shelley  */
418af9e46fSZane Shelley void createPel(const libhei::IsolationData& i_isoData,
424ed4be56SZane Shelley                const ServiceData& i_servData);
43d3b9bac9SZane Shelley 
44d84ed6e9SZane Shelley //------------------------------------------------------------------------------
45d84ed6e9SZane Shelley 
462f263181SZane Shelley const char* __attn(libhei::AttentionType_t i_attnType)
472f263181SZane Shelley {
482f263181SZane Shelley     const char* str = "";
492f263181SZane Shelley     switch (i_attnType)
502f263181SZane Shelley     {
512f263181SZane Shelley         case libhei::ATTN_TYPE_CHECKSTOP:
522f263181SZane Shelley             str = "CHECKSTOP";
532f263181SZane Shelley             break;
542f263181SZane Shelley         case libhei::ATTN_TYPE_UNIT_CS:
552f263181SZane Shelley             str = "UNIT_CS";
562f263181SZane Shelley             break;
572f263181SZane Shelley         case libhei::ATTN_TYPE_RECOVERABLE:
582f263181SZane Shelley             str = "RECOVERABLE";
592f263181SZane Shelley             break;
602f263181SZane Shelley         case libhei::ATTN_TYPE_SP_ATTN:
612f263181SZane Shelley             str = "SP_ATTN";
622f263181SZane Shelley             break;
632f263181SZane Shelley         case libhei::ATTN_TYPE_HOST_ATTN:
642f263181SZane Shelley             str = "HOST_ATTN";
652f263181SZane Shelley             break;
662f263181SZane Shelley         default:
672f263181SZane Shelley             trace::err("Unsupported attention type: %u", i_attnType);
682f263181SZane Shelley             assert(0);
692f263181SZane Shelley     }
702f263181SZane Shelley     return str;
712f263181SZane Shelley }
722f263181SZane Shelley 
732f263181SZane Shelley //------------------------------------------------------------------------------
742f263181SZane Shelley 
75cb457383SZane Shelley bool __filterRootCause(const libhei::IsolationData& i_isoData,
76cb457383SZane Shelley                        libhei::Signature& o_signature)
77097a71adSZane Shelley {
78cb457383SZane Shelley     // We'll need to make a copy of the list so that the original list is
79cb457383SZane Shelley     // maintained for the log.
80cb457383SZane Shelley     std::vector<libhei::Signature> sigList{i_isoData.getSignatureList()};
81cb457383SZane Shelley 
822f263181SZane Shelley     // For debug, trace out the original list of signatures before filtering.
83cb457383SZane Shelley     for (const auto& sig : sigList)
842f263181SZane Shelley     {
85f4bd5ff6SZane Shelley         trace::inf("Signature: %s 0x%0" PRIx32 " %s",
86cb457383SZane Shelley                    util::pdbg::getPath(sig.getChip()), sig.toUint32(),
87f4bd5ff6SZane Shelley                    __attn(sig.getAttnType()));
882f263181SZane Shelley     }
892f263181SZane Shelley 
90097a71adSZane Shelley     // Special and host attentions are not supported by this user application.
91097a71adSZane Shelley     auto newEndItr =
92cb457383SZane Shelley         std::remove_if(sigList.begin(), sigList.end(), [&](const auto& t) {
93097a71adSZane Shelley             return (libhei::ATTN_TYPE_SP_ATTN == t.getAttnType() ||
94097a71adSZane Shelley                     libhei::ATTN_TYPE_HOST_ATTN == t.getAttnType());
95097a71adSZane Shelley         });
96097a71adSZane Shelley 
97097a71adSZane Shelley     // Shrink the vector, if needed.
98cb457383SZane Shelley     sigList.resize(std::distance(sigList.begin(), newEndItr));
99097a71adSZane Shelley 
100097a71adSZane Shelley     // START WORKAROUND
101097a71adSZane Shelley     // TODO: Filtering should be determined by the RAS Data Files provided by
102097a71adSZane Shelley     //       the host firmware via the PNOR (similar to the Chip Data Files).
103097a71adSZane Shelley     //       Until that support is available, use a rudimentary filter that
104097a71adSZane Shelley     //       first looks for any recoverable attention, then any unit checkstop,
105097a71adSZane Shelley     //       and then any system checkstop. This is built on the premise that
106097a71adSZane Shelley     //       recoverable errors could be the root cause of an system checkstop
107097a71adSZane Shelley     //       attentions. Fortunately, we just need to sort the list by the
108097a71adSZane Shelley     //       greater attention type value.
109cb457383SZane Shelley     std::sort(sigList.begin(), sigList.end(),
110097a71adSZane Shelley               [&](const auto& a, const auto& b) {
111097a71adSZane Shelley                   return a.getAttnType() > b.getAttnType();
112097a71adSZane Shelley               });
113097a71adSZane Shelley     // END WORKAROUND
114cb457383SZane Shelley 
115cb457383SZane Shelley     // Check if a root cause attention was found.
116cb457383SZane Shelley     if (!sigList.empty())
117cb457383SZane Shelley     {
118cb457383SZane Shelley         // The entry at the front of the list will be the root cause.
119cb457383SZane Shelley         o_signature = sigList.front();
120cb457383SZane Shelley         return true;
121cb457383SZane Shelley     }
122cb457383SZane Shelley 
123cb457383SZane Shelley     return false; // default, no active attentions found.
124097a71adSZane Shelley }
125097a71adSZane Shelley 
126097a71adSZane Shelley //------------------------------------------------------------------------------
127097a71adSZane Shelley 
1289fb7393eSZane Shelley bool analyzeHardware()
12987eabc65SBen Tyner {
130097a71adSZane Shelley     bool attnFound = false;
13187eabc65SBen Tyner 
132*e5411f0fSZane Shelley     if (!util::pdbg::queryHardwareAnalysisSupported())
133*e5411f0fSZane Shelley     {
134*e5411f0fSZane Shelley         trace::err("Hardware error analysis is not supported on this system");
135*e5411f0fSZane Shelley         return attnFound;
136*e5411f0fSZane Shelley     }
137*e5411f0fSZane Shelley 
1382f263181SZane Shelley     trace::inf(">>> enter analyzeHardware()");
1392f263181SZane Shelley 
140171a2e04SZane Shelley     // Initialize the isolator and get all of the chips to be analyzed.
141f4bd5ff6SZane Shelley     trace::inf("Initializing the isolator...");
142171a2e04SZane Shelley     std::vector<libhei::Chip> chips;
143f4bd5ff6SZane Shelley     initializeIsolator(chips);
1442e994bcdSZane Shelley 
145097a71adSZane Shelley     // Isolate attentions.
146f4bd5ff6SZane Shelley     trace::inf("Isolating errors: # of chips=%u", chips.size());
147097a71adSZane Shelley     libhei::IsolationData isoData{};
148f4bd5ff6SZane Shelley     libhei::isolate(chips, isoData);
14987eabc65SBen Tyner 
150*e5411f0fSZane Shelley     // Filter for root cause attention.
151*e5411f0fSZane Shelley     libhei::Signature rootCause{};
152*e5411f0fSZane Shelley     attnFound = __filterRootCause(isoData, rootCause);
153*e5411f0fSZane Shelley 
154*e5411f0fSZane Shelley     if (!attnFound)
155*e5411f0fSZane Shelley     {
156*e5411f0fSZane Shelley         // It is possible for TI handling, or manually initiated analysis via
157*e5411f0fSZane Shelley         // the command line, that there will not be an active attention. In
158*e5411f0fSZane Shelley         // which case, we will do nothing and let the caller of this function
159*e5411f0fSZane Shelley         // determine if this is the expected behavior.
160*e5411f0fSZane Shelley         trace::inf("No active attentions found");
161*e5411f0fSZane Shelley     }
162*e5411f0fSZane Shelley     else
163*e5411f0fSZane Shelley     {
164*e5411f0fSZane Shelley         trace::inf("Root cause attention: %s 0x%0" PRIx32 " %s",
165*e5411f0fSZane Shelley                    util::pdbg::getPath(rootCause.getChip()),
166*e5411f0fSZane Shelley                    rootCause.toUint32(), __attn(rootCause.getAttnType()));
167*e5411f0fSZane Shelley 
168*e5411f0fSZane Shelley         // Perform service actions based on the root cause.
169*e5411f0fSZane Shelley         ServiceData servData{rootCause};
170*e5411f0fSZane Shelley         applyRasActions(servData);
171*e5411f0fSZane Shelley 
172*e5411f0fSZane Shelley         // Create and commit a PEL.
173*e5411f0fSZane Shelley         createPel(isoData, servData);
174*e5411f0fSZane Shelley     }
17587eabc65SBen Tyner 
176097a71adSZane Shelley     // All done, clean up the isolator.
177f4bd5ff6SZane Shelley     trace::inf("Uninitializing isolator...");
178097a71adSZane Shelley     libhei::uninitialize();
179b1ebfcb1SBen Tyner 
1802f263181SZane Shelley     trace::inf("<<< exit analyzeHardware()");
1812f263181SZane Shelley 
182097a71adSZane Shelley     return attnFound;
1830205f3b3SBen Tyner }
1840205f3b3SBen Tyner 
185eea45427SBen Tyner //------------------------------------------------------------------------------
186eea45427SBen Tyner 
187eea45427SBen Tyner /**
188eea45427SBen Tyner  * @brief Get error isolator build information
189eea45427SBen Tyner  *
190eea45427SBen Tyner  * @return Pointer to build information
191eea45427SBen Tyner  */
192eea45427SBen Tyner const char* getBuildInfo()
193eea45427SBen Tyner {
194eea45427SBen Tyner     return libhei::getBuildInfo();
195eea45427SBen Tyner }
196eea45427SBen Tyner 
1970205f3b3SBen Tyner } // namespace analyzer
198