1 #include <assert.h>
2 
3 #include <analyzer/analyzer_main.hpp>
4 #include <analyzer/ras-data/ras-data-parser.hpp>
5 #include <hei_main.hpp>
6 #include <hei_util.hpp>
7 #include <util/pdbg.hpp>
8 
9 #include <algorithm>
10 #include <limits>
11 #include <string>
12 
13 namespace analyzer
14 {
15 //------------------------------------------------------------------------------
16 
17 bool __findRcsOscError(const std::vector<libhei::Signature>& i_list,
18                        libhei::Signature& o_rootCause)
19 {
20     // TODO: Consider returning all of them instead of one as root cause.
21     auto itr = std::find_if(i_list.begin(), i_list.end(), [&](const auto& t) {
22         return (libhei::hash<libhei::NodeId_t>("TP_LOCAL_FIR") == t.getId() &&
23                 (42 == t.getBit() || 43 == t.getBit()));
24     });
25 
26     if (i_list.end() != itr)
27     {
28         o_rootCause = *itr;
29         return true;
30     }
31 
32     return false;
33 }
34 
35 //------------------------------------------------------------------------------
36 
37 bool __findPllUnlock(const std::vector<libhei::Signature>& i_list,
38                      libhei::Signature& o_rootCause)
39 {
40     // TODO: Consider returning all of them instead of one as root cause.
41     auto itr = std::find_if(i_list.begin(), i_list.end(), [&](const auto& t) {
42         return (libhei::hash<libhei::NodeId_t>("PLL_UNLOCK") == t.getId() &&
43                 (0 == t.getBit() || 1 == t.getBit()));
44     });
45 
46     if (i_list.end() != itr)
47     {
48         o_rootCause = *itr;
49         return true;
50     }
51 
52     return false;
53 }
54 
55 //------------------------------------------------------------------------------
56 
57 bool __findIueTh(const std::vector<libhei::Signature>& i_list,
58                  libhei::Signature& o_rootCause)
59 {
60     // TODO: These bit values propbably changed in Odyssey. Will need to
61     //       consider flags instead of arbitrary values.
62     auto itr = std::find_if(i_list.begin(), i_list.end(), [&](const auto& t) {
63         return (libhei::hash<libhei::NodeId_t>("RDFFIR") == t.getId() &&
64                 (17 == t.getBit() || 37 == t.getBit()));
65     });
66 
67     if (i_list.end() != itr)
68     {
69         o_rootCause = *itr;
70         return true;
71     }
72 
73     return false;
74 }
75 
76 //------------------------------------------------------------------------------
77 
78 bool __findMemoryChannelFailure(const std::vector<libhei::Signature>& i_list,
79                                 libhei::Signature& o_rootCause,
80                                 const RasDataParser& i_rasData)
81 {
82     using namespace util::pdbg;
83 
84     using func  = libhei::NodeId_t (*)(const std::string& i_str);
85     func __hash = libhei::hash<libhei::NodeId_t>;
86 
87     static const auto mc_dstl_fir       = __hash("MC_DSTL_FIR");
88     static const auto mc_ustl_fir       = __hash("MC_USTL_FIR");
89     static const auto mc_omi_dl_err_rpt = __hash("MC_OMI_DL_ERR_RPT");
90     static const auto srqfir            = __hash("SRQFIR");
91 
92     // First, look for any chip checkstops from the connected OCMBs.
93     for (const auto& s : i_list)
94     {
95         if (TYPE_OCMB != getTrgtType(getTrgt(s.getChip())))
96         {
97             continue; // OCMBs only
98         }
99 
100         // TODO: The chip data for Explorer chips currently report chip
101         //       checkstops as unit checkstops. Once the chip data has been
102         //       updated, the check for unit checkstops here will need to be
103         //       removed.
104         if (libhei::ATTN_TYPE_CHIP_CS == s.getAttnType() ||
105             libhei::ATTN_TYPE_UNIT_CS == s.getAttnType())
106         {
107             // Special Case:
108             // If the channel fail was specifically a firmware initiated
109             // channel fail (SRQFIR[25]) check for any IUE bits that are on
110             // that would have caused that (RDFFIR[17,37]).
111             // TODO: These bit values probably changed in Odyssey. Will need to
112             //       consider flags instead of arbitrary values.
113             if ((srqfir == s.getId() && 25 == s.getBit()) &&
114                 __findIueTh(i_list, o_rootCause))
115             {
116                 return true;
117             }
118 
119             o_rootCause = s;
120             return true;
121         }
122     }
123 
124     // Now, look for any channel failure attentions on the processor side of the
125     // memory bus.
126     for (const auto& s : i_list)
127     {
128         if (TYPE_PROC != getTrgtType(getTrgt(s.getChip())))
129         {
130             continue; // processors only
131         }
132 
133         // Any unit checkstop attentions that originated from the MC_DSTL_FIR or
134         // MC_USTLFIR are considered a channel failure attention.
135         // TODO: The "channel failure" designation is actually configurable via
136         //       other registers. We just happen to expect anything that is
137         //       configured to channel failure to also be configured to unit
138         //       checkstop. Eventually, we will need some mechanism to check the
139         //       configuration registers for a more accurate analysis.
140         if (libhei::ATTN_TYPE_UNIT_CS == s.getAttnType() &&
141             (mc_dstl_fir == s.getId() || mc_ustl_fir == s.getId()) &&
142             !i_rasData.isFlagSet(s,
143                                  RasDataParser::RasDataFlags::ATTN_FROM_OCMB))
144         {
145             o_rootCause = s;
146             return true;
147         }
148         // Any signatures from MC_OMI_DL_ERR_RPT feed into the only bits in
149         // MC_OMI_DL_FIR that are hardwired to channel failure.
150         else if (mc_omi_dl_err_rpt == s.getId())
151         {
152             o_rootCause = s;
153             return true;
154         }
155     }
156 
157     return false; // default, nothing found
158 }
159 
160 //------------------------------------------------------------------------------
161 
162 // Will query if a signature is a potential system checkstop root cause.
163 // attention. Note that this function excludes memory channel failure attentions
164 // which are checked in __findMemoryChannelFailure().
165 bool __findCsRootCause(const libhei::Signature& i_signature,
166                        const RasDataParser& i_rasData)
167 {
168     // Check if the input signature has the CS_POSSIBLE or SUE_SOURCE flag set.
169     if (i_rasData.isFlagSet(i_signature,
170                             RasDataParser::RasDataFlags::CS_POSSIBLE) ||
171         i_rasData.isFlagSet(i_signature,
172                             RasDataParser::RasDataFlags::SUE_SOURCE))
173     {
174         return true;
175     }
176 
177     return false; // default, nothing found
178 }
179 
180 //------------------------------------------------------------------------------
181 
182 bool __findCsRootCause_RE(const std::vector<libhei::Signature>& i_list,
183                           libhei::Signature& o_rootCause,
184                           const RasDataParser& i_rasData)
185 {
186     for (const auto& s : i_list)
187     {
188         // Only looking for recoverable attentions.
189         if (libhei::ATTN_TYPE_RECOVERABLE != s.getAttnType())
190         {
191             continue;
192         }
193 
194         if (__findCsRootCause(s, i_rasData))
195         {
196             o_rootCause = s;
197             return true;
198         }
199     }
200 
201     return false; // default, nothing found
202 }
203 
204 //------------------------------------------------------------------------------
205 
206 bool __findCsRootCause_UCS(const std::vector<libhei::Signature>& i_list,
207                            libhei::Signature& o_rootCause,
208                            const RasDataParser& i_rasData)
209 {
210     for (const auto& s : i_list)
211     {
212         // Only looking for unit checkstop attentions.
213         if (libhei::ATTN_TYPE_UNIT_CS != s.getAttnType())
214         {
215             continue;
216         }
217 
218         if (__findCsRootCause(s, i_rasData))
219         {
220             o_rootCause = s;
221             return true;
222         }
223     }
224 
225     return false; // default, nothing found
226 }
227 
228 //------------------------------------------------------------------------------
229 
230 bool __findOcmbAttnBits(const std::vector<libhei::Signature>& i_list,
231                         libhei::Signature& o_rootCause,
232                         const RasDataParser& i_rasData)
233 {
234     using namespace util::pdbg;
235 
236     // If we have any attentions from an OCMB, assume isolation to the OCMBs
237     // was successful and the ATTN_FROM_OCMB flag does not need to be checked.
238     for (const auto& s : i_list)
239     {
240         if (TYPE_OCMB == getTrgtType(getTrgt(s.getChip())))
241         {
242             return false;
243         }
244     }
245 
246     for (const auto& s : i_list)
247     {
248         if (i_rasData.isFlagSet(s, RasDataParser::RasDataFlags::ATTN_FROM_OCMB))
249         {
250             o_rootCause = s;
251             return true;
252         }
253     }
254 
255     return false; // default, nothing found
256 }
257 
258 //------------------------------------------------------------------------------
259 
260 bool __findNonExternalCs(const std::vector<libhei::Signature>& i_list,
261                          libhei::Signature& o_rootCause)
262 {
263     using namespace util::pdbg;
264 
265     static const auto pb_ext_fir = libhei::hash<libhei::NodeId_t>("PB_EXT_FIR");
266 
267     for (const auto& s : i_list)
268     {
269         const auto targetType = getTrgtType(getTrgt(s.getChip()));
270         const auto id         = s.getId();
271         const auto attnType   = s.getAttnType();
272 
273         // Find any processor with chip checkstop attention that did not
274         // originate from the PB_EXT_FIR.
275         if ((TYPE_PROC == targetType) &&
276             (libhei::ATTN_TYPE_CHIP_CS == attnType) && (pb_ext_fir != id))
277         {
278             o_rootCause = s;
279             return true;
280         }
281     }
282 
283     return false; // default, nothing found
284 }
285 
286 //------------------------------------------------------------------------------
287 
288 bool __findTiRootCause(const std::vector<libhei::Signature>& i_list,
289                        libhei::Signature& o_rootCause)
290 {
291     using namespace util::pdbg;
292 
293     using func  = libhei::NodeId_t (*)(const std::string& i_str);
294     func __hash = libhei::hash<libhei::NodeId_t>;
295 
296     // PROC registers
297     static const auto tp_local_fir        = __hash("TP_LOCAL_FIR");
298     static const auto occ_fir             = __hash("OCC_FIR");
299     static const auto pbao_fir            = __hash("PBAO_FIR");
300     static const auto n0_local_fir        = __hash("N0_LOCAL_FIR");
301     static const auto int_cq_fir          = __hash("INT_CQ_FIR");
302     static const auto nx_cq_fir           = __hash("NX_CQ_FIR");
303     static const auto nx_dma_eng_fir      = __hash("NX_DMA_ENG_FIR");
304     static const auto vas_fir             = __hash("VAS_FIR");
305     static const auto n1_local_fir        = __hash("N1_LOCAL_FIR");
306     static const auto mcd_fir             = __hash("MCD_FIR");
307     static const auto pb_station_fir_en_1 = __hash("PB_STATION_FIR_EN_1");
308     static const auto pb_station_fir_en_2 = __hash("PB_STATION_FIR_EN_2");
309     static const auto pb_station_fir_en_3 = __hash("PB_STATION_FIR_EN_3");
310     static const auto pb_station_fir_en_4 = __hash("PB_STATION_FIR_EN_4");
311     static const auto pb_station_fir_es_1 = __hash("PB_STATION_FIR_ES_1");
312     static const auto pb_station_fir_es_2 = __hash("PB_STATION_FIR_ES_2");
313     static const auto pb_station_fir_es_3 = __hash("PB_STATION_FIR_ES_3");
314     static const auto pb_station_fir_es_4 = __hash("PB_STATION_FIR_ES_4");
315     static const auto pb_station_fir_eq   = __hash("PB_STATION_FIR_EQ");
316     static const auto psihb_fir           = __hash("PSIHB_FIR");
317     static const auto pbaf_fir            = __hash("PBAF_FIR");
318     static const auto lpc_fir             = __hash("LPC_FIR");
319     static const auto eq_core_fir         = __hash("EQ_CORE_FIR");
320     static const auto eq_l2_fir           = __hash("EQ_L2_FIR");
321     static const auto eq_l3_fir           = __hash("EQ_L3_FIR");
322     static const auto eq_ncu_fir          = __hash("EQ_NCU_FIR");
323     static const auto eq_local_fir        = __hash("EQ_LOCAL_FIR");
324     static const auto eq_qme_fir          = __hash("EQ_QME_FIR");
325     static const auto iohs_local_fir      = __hash("IOHS_LOCAL_FIR");
326     static const auto iohs_dlp_fir_oc     = __hash("IOHS_DLP_FIR_OC");
327     static const auto iohs_dlp_fir_smp    = __hash("IOHS_DLP_FIR_SMP");
328     static const auto mc_local_fir        = __hash("MC_LOCAL_FIR");
329     static const auto mc_fir              = __hash("MC_FIR");
330     static const auto mc_dstl_fir         = __hash("MC_DSTL_FIR");
331     static const auto mc_ustl_fir         = __hash("MC_USTL_FIR");
332     static const auto nmmu_cq_fir         = __hash("NMMU_CQ_FIR");
333     static const auto nmmu_fir            = __hash("NMMU_FIR");
334     static const auto mc_omi_dl           = __hash("MC_OMI_DL");
335     static const auto pau_local_fir       = __hash("PAU_LOCAL_FIR");
336     static const auto pau_ptl_fir         = __hash("PAU_PTL_FIR");
337     static const auto pau_phy_fir         = __hash("PAU_PHY_FIR");
338     static const auto pau_fir_0           = __hash("PAU_FIR_0");
339     static const auto pau_fir_2           = __hash("PAU_FIR_2");
340     static const auto pci_local_fir       = __hash("PCI_LOCAL_FIR");
341     static const auto pci_iop_fir         = __hash("PCI_IOP_FIR");
342     static const auto pci_nest_fir        = __hash("PCI_NEST_FIR");
343 
344     // OCMB registers
345     static const auto ocmb_lfir = __hash("OCMB_LFIR");
346     static const auto mmiofir   = __hash("MMIOFIR");
347     static const auto srqfir    = __hash("SRQFIR");
348     static const auto rdffir    = __hash("RDFFIR");
349     static const auto tlxfir    = __hash("TLXFIR");
350     static const auto omi_dl    = __hash("OMI_DL");
351 
352     for (const auto& signature : i_list)
353     {
354         const auto targetType = getTrgtType(getTrgt(signature.getChip()));
355         const auto attnType   = signature.getAttnType();
356         const auto id         = signature.getId();
357         const auto bit        = signature.getBit();
358 
359         // Only looking for recoverable or unit checkstop attentions.
360         if (libhei::ATTN_TYPE_RECOVERABLE != attnType &&
361             libhei::ATTN_TYPE_UNIT_CS != attnType)
362         {
363             continue;
364         }
365 
366         // Ignore attentions that should not be blamed as root cause of a TI.
367         // This would include informational only FIRs or correctable errors.
368         if (TYPE_PROC == targetType)
369         {
370             if (tp_local_fir == id &&
371                 (0 == bit || 1 == bit || 2 == bit || 3 == bit || 4 == bit ||
372                  5 == bit || 7 == bit || 8 == bit || 9 == bit || 10 == bit ||
373                  11 == bit || 20 == bit || 22 == bit || 23 == bit ||
374                  24 == bit || 38 == bit || 40 == bit || 41 == bit ||
375                  46 == bit || 47 == bit || 48 == bit || 55 == bit ||
376                  56 == bit || 57 == bit || 58 == bit || 59 == bit))
377             {
378                 continue;
379             }
380 
381             if (occ_fir == id &&
382                 (9 == bit || 10 == bit || 15 == bit || 20 == bit || 21 == bit ||
383                  22 == bit || 23 == bit || 32 == bit || 33 == bit ||
384                  34 == bit || 36 == bit || 42 == bit || 43 == bit ||
385                  46 == bit || 47 == bit || 48 == bit || 51 == bit ||
386                  52 == bit || 53 == bit || 54 == bit || 57 == bit))
387             {
388                 continue;
389             }
390 
391             if (pbao_fir == id &&
392                 (0 == bit || 1 == bit || 2 == bit || 8 == bit || 11 == bit ||
393                  13 == bit || 15 == bit || 16 == bit || 17 == bit))
394             {
395                 continue;
396             }
397 
398             if ((n0_local_fir == id || n1_local_fir == id ||
399                  iohs_local_fir == id || mc_local_fir == id ||
400                  pau_local_fir == id || pci_local_fir == id) &&
401                 (0 == bit || 1 == bit || 2 == bit || 3 == bit || 4 == bit ||
402                  5 == bit || 6 == bit || 7 == bit || 8 == bit || 9 == bit ||
403                  10 == bit || 11 == bit || 20 == bit || 21 == bit))
404             {
405                 continue;
406             }
407 
408             if (int_cq_fir == id &&
409                 (0 == bit || 3 == bit || 5 == bit || 7 == bit || 36 == bit ||
410                  47 == bit || 48 == bit || 49 == bit || 50 == bit ||
411                  58 == bit || 59 == bit || 60 == bit))
412             {
413                 continue;
414             }
415 
416             if (nx_cq_fir == id &&
417                 (1 == bit || 4 == bit || 18 == bit || 32 == bit || 33 == bit))
418             {
419                 continue;
420             }
421 
422             if (nx_dma_eng_fir == id &&
423                 (4 == bit || 6 == bit || 9 == bit || 10 == bit || 11 == bit ||
424                  34 == bit || 35 == bit || 36 == bit || 37 == bit || 39 == bit))
425             {
426                 continue;
427             }
428 
429             if (vas_fir == id &&
430                 (8 == bit || 9 == bit || 11 == bit || 12 == bit || 13 == bit))
431             {
432                 continue;
433             }
434 
435             if (mcd_fir == id && (0 == bit))
436             {
437                 continue;
438             }
439 
440             if ((pb_station_fir_en_1 == id || pb_station_fir_en_2 == id ||
441                  pb_station_fir_en_3 == id || pb_station_fir_en_4 == id ||
442                  pb_station_fir_es_1 == id || pb_station_fir_es_2 == id ||
443                  pb_station_fir_es_3 == id || pb_station_fir_es_4 == id ||
444                  pb_station_fir_eq == id) &&
445                 (9 == bit))
446             {
447                 continue;
448             }
449 
450             if (psihb_fir == id && (0 == bit || 23 == bit))
451             {
452                 continue;
453             }
454 
455             if (pbaf_fir == id &&
456                 (0 == bit || 1 == bit || 3 == bit || 4 == bit || 5 == bit ||
457                  6 == bit || 7 == bit || 8 == bit || 9 == bit || 10 == bit ||
458                  11 == bit || 19 == bit || 20 == bit || 21 == bit ||
459                  28 == bit || 29 == bit || 30 == bit || 31 == bit ||
460                  32 == bit || 33 == bit || 34 == bit || 35 == bit || 36 == bit))
461             {
462                 continue;
463             }
464 
465             if (lpc_fir == id && (5 == bit))
466             {
467                 continue;
468             }
469 
470             if (eq_core_fir == id &&
471                 (0 == bit || 2 == bit || 4 == bit || 7 == bit || 9 == bit ||
472                  11 == bit || 13 == bit || 18 == bit || 21 == bit ||
473                  24 == bit || 29 == bit || 31 == bit || 37 == bit ||
474                  43 == bit || 56 == bit || 57 == bit))
475             {
476                 continue;
477             }
478 
479             if (eq_l2_fir == id &&
480                 (0 == bit || 6 == bit || 11 == bit || 19 == bit || 36 == bit))
481             {
482                 continue;
483             }
484 
485             if (eq_l3_fir == id &&
486                 (3 == bit || 4 == bit || 7 == bit || 10 == bit || 13 == bit))
487             {
488                 continue;
489             }
490 
491             if (eq_ncu_fir == id && (9 == bit))
492             {
493                 continue;
494             }
495 
496             if (eq_local_fir == id &&
497                 (0 == bit || 1 == bit || 2 == bit || 3 == bit || 5 == bit ||
498                  6 == bit || 7 == bit || 8 == bit || 9 == bit || 10 == bit ||
499                  11 == bit || 12 == bit || 13 == bit || 14 == bit ||
500                  15 == bit || 16 == bit || 20 == bit || 21 == bit ||
501                  22 == bit || 23 == bit || 24 == bit || 25 == bit ||
502                  26 == bit || 27 == bit || 28 == bit || 29 == bit ||
503                  30 == bit || 31 == bit || 32 == bit || 33 == bit ||
504                  34 == bit || 35 == bit || 36 == bit || 37 == bit ||
505                  38 == bit || 39 == bit))
506             {
507                 continue;
508             }
509 
510             if (eq_qme_fir == id && (7 == bit || 25 == bit))
511             {
512                 continue;
513             }
514 
515             if (iohs_dlp_fir_oc == id &&
516                 (6 == bit || 7 == bit || 8 == bit || 9 == bit || 10 == bit ||
517                  48 == bit || 49 == bit || 52 == bit || 53 == bit))
518             {
519                 continue;
520             }
521 
522             if (iohs_dlp_fir_smp == id &&
523                 (6 == bit || 7 == bit || 14 == bit || 15 == bit || 16 == bit ||
524                  17 == bit || 38 == bit || 39 == bit || 44 == bit ||
525                  45 == bit || 50 == bit || 51 == bit))
526             {
527                 continue;
528             }
529 
530             if (mc_fir == id &&
531                 (5 == bit || 8 == bit || 15 == bit || 16 == bit))
532             {
533                 continue;
534             }
535 
536             if (mc_dstl_fir == id &&
537                 (0 == bit || 1 == bit || 2 == bit || 3 == bit || 4 == bit ||
538                  5 == bit || 6 == bit || 7 == bit || 14 == bit || 15 == bit))
539             {
540                 continue;
541             }
542 
543             if (mc_ustl_fir == id &&
544                 (6 == bit || 20 == bit || 33 == bit || 34 == bit))
545             {
546                 continue;
547             }
548 
549             if (nmmu_cq_fir == id && (8 == bit || 11 == bit || 14 == bit))
550             {
551                 continue;
552             }
553 
554             if (nmmu_fir == id &&
555                 (0 == bit || 3 == bit || 8 == bit || 9 == bit || 10 == bit ||
556                  11 == bit || 12 == bit || 13 == bit || 14 == bit ||
557                  15 == bit || 30 == bit || 31 == bit || 41 == bit))
558             {
559                 continue;
560             }
561 
562             if (mc_omi_dl == id && (2 == bit || 3 == bit || 6 == bit ||
563                                     7 == bit || 9 == bit || 10 == bit))
564             {
565                 continue;
566             }
567 
568             if (pau_ptl_fir == id && (5 == bit || 9 == bit))
569             {
570                 continue;
571             }
572 
573             if (pau_phy_fir == id &&
574                 (2 == bit || 3 == bit || 6 == bit || 7 == bit || 15 == bit))
575             {
576                 continue;
577             }
578 
579             if (pau_fir_0 == id && (13 == bit || 30 == bit || 41 == bit))
580             {
581                 continue;
582             }
583 
584             if (pau_fir_2 == id && (19 == bit || 46 == bit || 49 == bit))
585             {
586                 continue;
587             }
588 
589             if (pci_iop_fir == id &&
590                 (0 == bit || 2 == bit || 4 == bit || 6 == bit || 7 == bit ||
591                  8 == bit || 10 == bit))
592             {
593                 continue;
594             }
595 
596             if (pci_nest_fir == id && (2 == bit || 5 == bit))
597             {
598                 continue;
599             }
600         }
601         else if (TYPE_OCMB == targetType)
602         {
603             if (ocmb_lfir == id &&
604                 (0 == bit || 1 == bit || 2 == bit || 8 == bit || 23 == bit ||
605                  37 == bit || 63 == bit))
606             {
607                 continue;
608             }
609 
610             if (mmiofir == id && (2 == bit))
611             {
612                 continue;
613             }
614 
615             if (srqfir == id &&
616                 (2 == bit || 4 == bit || 14 == bit || 15 == bit || 23 == bit ||
617                  25 == bit || 28 == bit))
618             {
619                 continue;
620             }
621 
622             if (rdffir == id &&
623                 (0 == bit || 1 == bit || 2 == bit || 3 == bit || 4 == bit ||
624                  5 == bit || 6 == bit || 7 == bit || 8 == bit || 9 == bit ||
625                  18 == bit || 38 == bit || 40 == bit || 41 == bit ||
626                  45 == bit || 46 == bit))
627             {
628                 continue;
629             }
630 
631             if (tlxfir == id && (0 == bit || 9 == bit || 26 == bit))
632             {
633                 continue;
634             }
635 
636             if (omi_dl == id && (2 == bit || 3 == bit || 6 == bit || 7 == bit ||
637                                  9 == bit || 10 == bit))
638             {
639                 continue;
640             }
641         }
642 
643         // At this point, the attention has not been explicitly ignored. So
644         // return this signature and exit.
645         o_rootCause = signature;
646         return true;
647     }
648 
649     return false; // default, nothing found
650 }
651 
652 //------------------------------------------------------------------------------
653 
654 bool filterRootCause(AnalysisType i_type,
655                      const libhei::IsolationData& i_isoData,
656                      libhei::Signature& o_rootCause,
657                      const RasDataParser& i_rasData)
658 {
659     // We'll need to make a copy of the list so that the original list is
660     // maintained for the PEL.
661     std::vector<libhei::Signature> list{i_isoData.getSignatureList()};
662 
663     // START WORKAROUND
664     // TODO: Filtering should be data driven. Until that support is available,
665     //       use the following isolation rules.
666 
667     // Ensure the list is not empty before continuing.
668     if (list.empty())
669     {
670         return false; // nothing more to do
671     }
672 
673     // First, look for any RCS OSC errors. This must always be first because
674     // they can cause downstream PLL unlock attentions.
675     if (__findRcsOscError(list, o_rootCause))
676     {
677         return true;
678     }
679 
680     // Second, look for any PLL unlock attentions. This must always be second
681     // because PLL unlock attentions can cause any number of downstream
682     // attentions, including a system checkstop.
683     if (__findPllUnlock(list, o_rootCause))
684     {
685         return true;
686     }
687 
688     // Regardless of the analysis type, always look for anything that could be
689     // blamed as the root cause of a system checkstop.
690 
691     // Memory channel failure attentions will produce SUEs and likely cause
692     // downstream attentions, including a system checkstop.
693     if (__findMemoryChannelFailure(list, o_rootCause, i_rasData))
694     {
695         return true;
696     }
697 
698     // Look for any recoverable attentions that have been identified as a
699     // potential root cause of a system checkstop attention. These would include
700     // any attention that would generate an SUE. Note that is it possible for
701     // recoverables to generate unit checkstop attentions so we must check them
702     // first.
703     if (__findCsRootCause_RE(list, o_rootCause, i_rasData))
704     {
705         return true;
706     }
707 
708     // Look for any unit checkstop attentions (other than memory channel
709     // failures) that have been identified as a potential root cause of a
710     // system checkstop attention. These would include any attention that would
711     // generate an SUE.
712     if (__findCsRootCause_UCS(list, o_rootCause, i_rasData))
713     {
714         return true;
715     }
716 
717     // If no other viable root cause has been found, check for any signatures
718     // with the ATTN_FROM_OCMB flag in case there was an attention from an
719     // inaccessible OCMB.
720     if (__findOcmbAttnBits(list, o_rootCause, i_rasData))
721     {
722         return true;
723     }
724 
725     // Look for any system checkstop attentions that originated from within the
726     // chip that reported the attention. In other words, no external checkstop
727     // attentions.
728     if (__findNonExternalCs(list, o_rootCause))
729     {
730         return true;
731     }
732 
733     if (AnalysisType::SYSTEM_CHECKSTOP != i_type)
734     {
735         // No system checkstop root cause attentions were found. Next, look for
736         // any recoverable or unit checkstop attentions that could be associated
737         // with a TI.
738         if (__findTiRootCause(list, o_rootCause))
739         {
740             return true;
741         }
742 
743         if (AnalysisType::TERMINATE_IMMEDIATE != i_type)
744         {
745             // No attentions associated with a system checkstop or TI were
746             // found. Simply, return the first entry in the list.
747             o_rootCause = list.front();
748             return true;
749         }
750     }
751 
752     // END WORKAROUND
753 
754     return false; // default, no active attentions found.
755 }
756 
757 //------------------------------------------------------------------------------
758 
759 } // namespace analyzer
760