Update root cause filtering to use RAS data flags
Change-Id: I172540905a39533139821d3cb1676424824bd804
Signed-off-by: Caleb Palmer <cnpalmer@us.ibm.com>
diff --git a/analyzer/analyzer_main.cpp b/analyzer/analyzer_main.cpp
index 5295725..19429f4 100644
--- a/analyzer/analyzer_main.cpp
+++ b/analyzer/analyzer_main.cpp
@@ -11,7 +11,6 @@
namespace analyzer
{
-
//------------------------------------------------------------------------------
// Forward references for externally defined functions.
@@ -27,11 +26,13 @@
* @param i_type The type of analysis to perform. See enum for details.
* @param i_isoData The data gathered during isolation (for FFDC).
* @param o_rootCause The returned root cause signature.
+ * @param i_rasData The RAS data parser.
* @return True, if root cause has been found. False, otherwise.
*/
bool filterRootCause(AnalysisType i_type,
const libhei::IsolationData& i_isoData,
- libhei::Signature& o_rootCause);
+ libhei::Signature& o_rootCause,
+ const RasDataParser& i_rasData);
/**
* @brief Will create and submit a PEL using the given data.
@@ -126,7 +127,8 @@
// Filter for root cause attention.
libhei::Signature rootCause{};
- bool attnFound = filterRootCause(i_type, isoData, rootCause);
+ RasDataParser rasData{};
+ bool attnFound = filterRootCause(i_type, isoData, rootCause, rasData);
// If a root cause attention was found, or if this was a system checkstop,
// generate a PEL.
@@ -160,7 +162,6 @@
try
{
// Resolve the root cause attention.
- RasDataParser rasData{};
rasData.getResolution(rootCause)->resolve(servData);
}
catch (const std::exception& e)
diff --git a/analyzer/filter-root-cause.cpp b/analyzer/filter-root-cause.cpp
index 19bbc4d..d81a44d 100644
--- a/analyzer/filter-root-cause.cpp
+++ b/analyzer/filter-root-cause.cpp
@@ -1,6 +1,7 @@
#include <assert.h>
-#include <analyzer_main.hpp>
+#include <analyzer/analyzer_main.hpp>
+#include <analyzer/ras-data/ras-data-parser.hpp>
#include <hei_main.hpp>
#include <hei_util.hpp>
#include <util/pdbg.hpp>
@@ -73,7 +74,8 @@
//------------------------------------------------------------------------------
bool __findMemoryChannelFailure(const std::vector<libhei::Signature>& i_list,
- libhei::Signature& o_rootCause)
+ libhei::Signature& o_rootCause,
+ const RasDataParser& i_rasData)
{
using namespace util::pdbg;
@@ -83,60 +85,98 @@
static const auto mc_dstl_fir = __hash("MC_DSTL_FIR");
static const auto mc_ustl_fir = __hash("MC_USTL_FIR");
static const auto mc_omi_dl_err_rpt = __hash("MC_OMI_DL_ERR_RPT");
+ static const auto srqfir = __hash("SRQFIR");
for (const auto s : i_list)
{
- const auto targetType = getTrgtType(getTrgt(s.getChip()));
- const auto id = s.getId();
- const auto bit = s.getBit();
- const auto attnType = s.getAttnType();
-
- // Look for any unit checkstop attentions from OCMBs.
- if (TYPE_OCMB == targetType)
+ // Version 1 of the RAS data files
+ if (1 == i_rasData.getVersion(s))
{
- // Any unit checkstop attentions will trigger a channel failure.
- if (libhei::ATTN_TYPE_UNIT_CS == attnType)
- {
- static const auto srqfir = __hash("SRQFIR");
+ const auto targetType = getTrgtType(getTrgt(s.getChip()));
+ const auto id = s.getId();
+ const auto bit = s.getBit();
+ const auto attnType = s.getAttnType();
- // If the channel was specifically a firmware initiated channel
- // fail (SRQFIR[25]) check for any IUE bits that are on that
- // would have caused that (RDFFIR[17,37]).
- if ((srqfir == id && 25 == bit) &&
- __findIueTh(i_list, o_rootCause))
+ // Look for any unit checkstop attentions from OCMBs.
+ if (TYPE_OCMB == targetType)
+ {
+ // Any unit checkstop attentions will trigger a channel failure.
+ if (libhei::ATTN_TYPE_UNIT_CS == attnType)
{
+ // If the channel was specifically a firmware initiated
+ // channel fail (SRQFIR[25]) check for any IUE bits that are
+ // on that would have caused that (RDFFIR[17,37]).
+ if ((srqfir == id && 25 == bit) &&
+ __findIueTh(i_list, o_rootCause))
+ {
+ return true;
+ }
+
+ o_rootCause = s;
return true;
}
-
- o_rootCause = s;
- return true;
}
- }
- // Look for channel failure attentions on processors.
- else if (TYPE_PROC == targetType)
- {
- // TODO: All of these channel failure bits are configurable.
- // Eventually, we will need some mechanism to check that
- // config registers for a more accurate analysis. For now,
- // simply check for all bits that could potentially be
- // configured to channel failure.
-
- // Any unit checkstop bit in the MC_DSTL_FIR or MC_USTL_FIR could
- // be a channel failure.
- if (libhei::ATTN_TYPE_UNIT_CS == attnType)
+ // Look for channel failure attentions on processors.
+ else if (TYPE_PROC == targetType)
{
- // Ignore bits MC_DSTL_FIR[0:7] because they simply indicate
- // attentions occurred on the attached OCMBs.
- if ((mc_dstl_fir == id && 8 <= bit) || (mc_ustl_fir == id))
+ // TODO: All of these channel failure bits are configurable.
+ // Eventually, we will need some mechanism to check that
+ // config registers for a more accurate analysis. For now,
+ // simply check for all bits that could potentially be
+ // configured to channel failure.
+
+ // Any unit checkstop bit in the MC_DSTL_FIR or MC_USTL_FIR
+ // could be a channel failure.
+ if (libhei::ATTN_TYPE_UNIT_CS == attnType)
+ {
+ // Ignore bits MC_DSTL_FIR[0:7] because they simply indicate
+ // attentions occurred on the attached OCMBs.
+ if ((mc_dstl_fir == id && 8 <= bit) || (mc_ustl_fir == id))
+ {
+ o_rootCause = s;
+ return true;
+ }
+ }
+
+ // All bits in MC_OMI_DL_ERR_RPT eventually feed into
+ // MC_OMI_DL_FIR[0,20] which are configurable to channel
+ // failure.
+ if (mc_omi_dl_err_rpt == id)
{
o_rootCause = s;
return true;
}
}
+ }
+ // Version 2 and above of the RAS data files
+ else if (2 <= i_rasData.getVersion(s))
+ {
+ if (libhei::ATTN_TYPE_UNIT_CS == s.getAttnType() &&
+ i_rasData.isFlagSet(s, RasDataParser::RasDataFlags::SUE_SOURCE))
+ {
+ // Special Cases:
+ // If the channel fail was specifically a firmware initiated
+ // channel fail (SRQFIR[25]) check for any IUE bits that are on
+ // that would have caused that (RDFFIR[17,37]).
+ if ((srqfir == s.getId() && 25 == s.getBit()) &&
+ __findIueTh(i_list, o_rootCause))
+ {
+ return true;
+ }
- // All bits in MC_OMI_DL_ERR_RPT eventually feed into
- // MC_OMI_DL_FIR[0,20] which are configurable to channel failure.
- if (mc_omi_dl_err_rpt == id)
+ // TODO: The proc side channel failure bits are configurable.
+ // Eventually, we will need some mechanism to check the
+ // config registers for a more accurate analysis. For now,
+ // simply check for all bits that could potentially be
+ // configured to channel failure.
+
+ o_rootCause = s;
+ }
+ // The bits in the MC_OMI_DL_ERR_RPT register are a special case.
+ // They are possible channel fail bits but the MC_OMI_DL_FIR they
+ // feed into can't be set up to report UNIT_CS attentions, so they
+ // report as recoverable instead.
+ else if (mc_omi_dl_err_rpt == s.getId())
{
o_rootCause = s;
return true;
@@ -152,119 +192,136 @@
// Will query if a signature is a potential system checkstop root cause.
// attention. Note that this function excludes memory channel failure attentions
// which are checked in __findMemoryChannelFailure().
-bool __findCsRootCause(const libhei::Signature& i_signature)
+bool __findCsRootCause(const libhei::Signature& i_signature,
+ const RasDataParser& i_rasData)
{
- using namespace util::pdbg;
-
- using func = libhei::NodeId_t (*)(const std::string& i_str);
- func __hash = libhei::hash<libhei::NodeId_t>;
-
- // PROC registers
- static const auto eq_core_fir = __hash("EQ_CORE_FIR");
- static const auto eq_l2_fir = __hash("EQ_L2_FIR");
- static const auto eq_l3_fir = __hash("EQ_L3_FIR");
- static const auto eq_ncu_fir = __hash("EQ_NCU_FIR");
- static const auto iohs_dlp_fir_oc = __hash("IOHS_DLP_FIR_OC");
- static const auto iohs_dlp_fir_smp = __hash("IOHS_DLP_FIR_SMP");
- static const auto nx_cq_fir = __hash("NX_CQ_FIR");
- static const auto nx_dma_eng_fir = __hash("NX_DMA_ENG_FIR");
- static const auto pau_fir_0 = __hash("PAU_FIR_0");
- static const auto pau_fir_1 = __hash("PAU_FIR_1");
- static const auto pau_fir_2 = __hash("PAU_FIR_2");
- static const auto pau_ptl_fir = __hash("PAU_PTL_FIR");
-
- // OCMB registers
- static const auto rdffir = __hash("RDFFIR");
-
- const auto targetType = getTrgtType(getTrgt(i_signature.getChip()));
- const auto id = i_signature.getId();
- const auto bit = i_signature.getBit();
-
- if (TYPE_PROC == targetType)
+ // Version 1 of the RAS data files.
+ if (1 == i_rasData.getVersion(i_signature))
{
- if (eq_core_fir == id &&
- (0 == bit || 2 == bit || 3 == bit || 4 == bit || 5 == bit ||
- 7 == bit || 8 == bit || 9 == bit || 11 == bit || 12 == bit ||
- 13 == bit || 18 == bit || 21 == bit || 22 == bit || 24 == bit ||
- 25 == bit || 29 == bit || 31 == bit || 32 == bit || 36 == bit ||
- 37 == bit || 38 == bit || 43 == bit || 46 == bit || 47 == bit))
- {
- return true;
- }
+ using namespace util::pdbg;
- if (eq_l2_fir == id &&
- (1 == bit || 12 == bit || 13 == bit || 17 == bit || 18 == bit ||
- 20 == bit || 27 == bit))
- {
- return true;
- }
+ using func = libhei::NodeId_t (*)(const std::string& i_str);
+ func __hash = libhei::hash<libhei::NodeId_t>;
- if (eq_l3_fir == id &&
- (2 == bit || 5 == bit || 8 == bit || 11 == bit || 17 == bit))
- {
- return true;
- }
+ // PROC registers
+ static const auto eq_core_fir = __hash("EQ_CORE_FIR");
+ static const auto eq_l2_fir = __hash("EQ_L2_FIR");
+ static const auto eq_l3_fir = __hash("EQ_L3_FIR");
+ static const auto eq_ncu_fir = __hash("EQ_NCU_FIR");
+ static const auto iohs_dlp_fir_oc = __hash("IOHS_DLP_FIR_OC");
+ static const auto iohs_dlp_fir_smp = __hash("IOHS_DLP_FIR_SMP");
+ static const auto nx_cq_fir = __hash("NX_CQ_FIR");
+ static const auto nx_dma_eng_fir = __hash("NX_DMA_ENG_FIR");
+ static const auto pau_fir_0 = __hash("PAU_FIR_0");
+ static const auto pau_fir_1 = __hash("PAU_FIR_1");
+ static const auto pau_fir_2 = __hash("PAU_FIR_2");
+ static const auto pau_ptl_fir = __hash("PAU_PTL_FIR");
- if (eq_ncu_fir == id && (3 == bit || 4 == bit || 5 == bit || 7 == bit ||
- 8 == bit || 10 == bit || 17 == bit))
- {
- return true;
- }
+ // OCMB registers
+ static const auto rdffir = __hash("RDFFIR");
- if (iohs_dlp_fir_oc == id && (54 <= bit && bit <= 61))
- {
- return true;
- }
+ const auto targetType = getTrgtType(getTrgt(i_signature.getChip()));
+ const auto id = i_signature.getId();
+ const auto bit = i_signature.getBit();
- if (iohs_dlp_fir_smp == id && (54 <= bit && bit <= 61))
+ if (TYPE_PROC == targetType)
{
- return true;
- }
+ if (eq_core_fir == id &&
+ (0 == bit || 2 == bit || 3 == bit || 4 == bit || 5 == bit ||
+ 7 == bit || 8 == bit || 9 == bit || 11 == bit || 12 == bit ||
+ 13 == bit || 18 == bit || 21 == bit || 22 == bit ||
+ 24 == bit || 25 == bit || 29 == bit || 31 == bit ||
+ 32 == bit || 36 == bit || 37 == bit || 38 == bit ||
+ 43 == bit || 46 == bit || 47 == bit))
+ {
+ return true;
+ }
- if (nx_cq_fir == id && (7 == bit || 16 == bit || 21 == bit))
- {
- return true;
- }
+ if (eq_l2_fir == id &&
+ (1 == bit || 12 == bit || 13 == bit || 17 == bit || 18 == bit ||
+ 20 == bit || 27 == bit))
+ {
+ return true;
+ }
- if (nx_dma_eng_fir == id && (0 == bit))
- {
- return true;
- }
+ if (eq_l3_fir == id &&
+ (2 == bit || 5 == bit || 8 == bit || 11 == bit || 17 == bit))
+ {
+ return true;
+ }
- if (pau_fir_0 == id &&
- (15 == bit || 18 == bit || 19 == bit || 25 == bit || 26 == bit ||
- 29 == bit || 33 == bit || 34 == bit || 35 == bit || 40 == bit ||
- 42 == bit || 44 == bit || 45 == bit))
- {
- return true;
- }
+ if (eq_ncu_fir == id &&
+ (3 == bit || 4 == bit || 5 == bit || 7 == bit || 8 == bit ||
+ 10 == bit || 17 == bit))
+ {
+ return true;
+ }
- if (pau_fir_1 == id &&
- (13 == bit || 14 == bit || 15 == bit || 37 == bit || 39 == bit ||
- 40 == bit || 41 == bit || 42 == bit))
- {
- return true;
- }
+ if (iohs_dlp_fir_oc == id && (54 <= bit && bit <= 61))
+ {
+ return true;
+ }
- if (pau_fir_2 == id &&
- ((4 <= bit && bit <= 18) || (20 <= bit && bit <= 31) ||
- (36 <= bit && bit <= 41) || 45 == bit || 47 == bit || 48 == bit ||
- 50 == bit || 51 == bit || 52 == bit))
- {
- return true;
- }
+ if (iohs_dlp_fir_smp == id && (54 <= bit && bit <= 61))
+ {
+ return true;
+ }
- if (pau_ptl_fir == id && (4 == bit || 8 == bit))
+ if (nx_cq_fir == id && (7 == bit || 16 == bit || 21 == bit))
+ {
+ return true;
+ }
+
+ if (nx_dma_eng_fir == id && (0 == bit))
+ {
+ return true;
+ }
+
+ if (pau_fir_0 == id &&
+ (15 == bit || 18 == bit || 19 == bit || 25 == bit ||
+ 26 == bit || 29 == bit || 33 == bit || 34 == bit ||
+ 35 == bit || 40 == bit || 42 == bit || 44 == bit || 45 == bit))
+ {
+ return true;
+ }
+
+ if (pau_fir_1 == id &&
+ (13 == bit || 14 == bit || 15 == bit || 37 == bit ||
+ 39 == bit || 40 == bit || 41 == bit || 42 == bit))
+ {
+ return true;
+ }
+
+ if (pau_fir_2 == id &&
+ ((4 <= bit && bit <= 18) || (20 <= bit && bit <= 31) ||
+ (36 <= bit && bit <= 41) || 45 == bit || 47 == bit ||
+ 48 == bit || 50 == bit || 51 == bit || 52 == bit))
+ {
+ return true;
+ }
+
+ if (pau_ptl_fir == id && (4 == bit || 8 == bit))
+ {
+ return true;
+ }
+ }
+ else if (TYPE_OCMB == targetType)
{
- return true;
+ if (rdffir == id &&
+ (14 == bit || 15 == bit || 17 == bit || 37 == bit))
+ {
+ return true;
+ }
}
}
- else if (TYPE_OCMB == targetType)
+ // Version 2 of the RAS data files. Check if the input signature has the
+ // CS_POSSIBLE or SUE_SOURCE flag set.
+ else if (i_rasData.isFlagSet(i_signature,
+ RasDataParser::RasDataFlags::CS_POSSIBLE) ||
+ i_rasData.isFlagSet(i_signature,
+ RasDataParser::RasDataFlags::SUE_SOURCE))
{
- if (rdffir == id && (14 == bit || 15 == bit || 17 == bit || 37 == bit))
- {
- return true;
- }
+ return true;
}
return false; // default, nothing found
@@ -273,7 +330,8 @@
//------------------------------------------------------------------------------
bool __findCsRootCause_RE(const std::vector<libhei::Signature>& i_list,
- libhei::Signature& o_rootCause)
+ libhei::Signature& o_rootCause,
+ const RasDataParser& i_rasData)
{
for (const auto s : i_list)
{
@@ -283,7 +341,7 @@
continue;
}
- if (__findCsRootCause(s))
+ if (__findCsRootCause(s, i_rasData))
{
o_rootCause = s;
return true;
@@ -296,7 +354,8 @@
//------------------------------------------------------------------------------
bool __findCsRootCause_UCS(const std::vector<libhei::Signature>& i_list,
- libhei::Signature& o_rootCause)
+ libhei::Signature& o_rootCause,
+ const RasDataParser& i_rasData)
{
for (const auto s : i_list)
{
@@ -306,7 +365,7 @@
continue;
}
- if (__findCsRootCause(s))
+ if (__findCsRootCause(s, i_rasData))
{
o_rootCause = s;
return true;
@@ -713,7 +772,8 @@
bool filterRootCause(AnalysisType i_type,
const libhei::IsolationData& i_isoData,
- libhei::Signature& o_rootCause)
+ libhei::Signature& o_rootCause,
+ const RasDataParser& i_rasData)
{
// We'll need to make a copy of the list so that the original list is
// maintained for the PEL.
@@ -749,7 +809,7 @@
// Memory channel failure attentions will produce SUEs and likely cause
// downstream attentions, including a system checkstop.
- if (__findMemoryChannelFailure(list, o_rootCause))
+ if (__findMemoryChannelFailure(list, o_rootCause, i_rasData))
{
return true;
}
@@ -759,7 +819,7 @@
// any attention that would generate an SUE. Note that is it possible for
// recoverables to generate unit checkstop attentions so we must check them
// first.
- if (__findCsRootCause_RE(list, o_rootCause))
+ if (__findCsRootCause_RE(list, o_rootCause, i_rasData))
{
return true;
}
@@ -768,7 +828,7 @@
// failures) that have been identified as a potential root cause of a
// system checkstop attention. These would include any attention that would
// generate an SUE.
- if (__findCsRootCause_UCS(list, o_rootCause))
+ if (__findCsRootCause_UCS(list, o_rootCause, i_rasData))
{
return true;
}
diff --git a/analyzer/ras-data/ras-data-parser.cpp b/analyzer/ras-data/ras-data-parser.cpp
index 8ad510d..9a014fd 100644
--- a/analyzer/ras-data/ras-data-parser.cpp
+++ b/analyzer/ras-data/ras-data-parser.cpp
@@ -47,8 +47,47 @@
//------------------------------------------------------------------------------
+bool __checkActionForFlag(const std::string& i_action,
+ const std::string& i_flag,
+ const nlohmann::json& i_data)
+{
+ bool o_isFlagSet = false;
+
+ // Loop through the array of actions.
+ for (const auto& a : i_data.at("actions").at(i_action))
+ {
+ // Get the action type
+ auto type = a.at("type").get<std::string>();
+
+ // If the action is another action, recursively call this function
+ if ("action" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+ o_isFlagSet = __checkActionForFlag(name, i_flag, i_data);
+ if (o_isFlagSet)
+ {
+ break;
+ }
+ }
+ // If the action is a flag, check if it's the one
+ else if ("flag" == type)
+ {
+ auto name = a.at("name").get<std::string>();
+ if (name == i_flag)
+ {
+ o_isFlagSet = true;
+ break;
+ }
+ }
+ }
+
+ return o_isFlagSet;
+}
+
+//------------------------------------------------------------------------------
+
bool RasDataParser::isFlagSet(const libhei::Signature& i_signature,
- const RasDataFlags i_flag)
+ const RasDataFlags i_flag) const
{
bool o_isFlagSet = false;
@@ -66,6 +105,7 @@
{ODP_DATA_CORRUPT_SIDE_EFFECT, "odp_data_corrupt_side_effect"},
{ODP_DATA_CORRUPT_ROOT_CAUSE, "odp_data_corrupt_root_cause"},
};
+ std::string strFlag = flagMap[i_flag];
// If the input flag does not exist in the map, that's a code bug.
assert(0 != flagMap.count(i_flag));
@@ -100,8 +140,7 @@
.get<std::vector<std::string>>();
// Check if the input flag exists
- if (flags.end() !=
- std::find(flags.begin(), flags.end(), flagMap[i_flag]))
+ if (flags.end() != std::find(flags.begin(), flags.end(), strFlag))
{
o_isFlagSet = true;
}
@@ -112,19 +151,7 @@
if (!o_isFlagSet)
{
const auto action = parseSignature(data, i_signature);
- for (const auto& a : data.at("actions").at(action))
- {
- auto type = a.at("type").get<std::string>();
- if ("flag" == type)
- {
- auto name = a.at("name").get<std::string>();
- if (name == flagMap[i_flag])
- {
- o_isFlagSet = true;
- break;
- }
- }
- }
+ __checkActionForFlag(action, strFlag, data);
}
return o_isFlagSet;
@@ -132,6 +159,30 @@
//------------------------------------------------------------------------------
+unsigned int
+ RasDataParser::getVersion(const libhei::Signature& i_signature) const
+{
+ unsigned int o_version = 0;
+
+ nlohmann::json data;
+ try
+ {
+ data = iv_dataFiles.at(i_signature.getChip().getType());
+ }
+ catch (const std::out_of_range& e)
+ {
+ trace::err("No RAS data defined for chip type: 0x%08x",
+ i_signature.getChip().getType());
+ throw; // caught later downstream
+ }
+
+ o_version = data.at("version").get<unsigned int>();
+
+ return o_version;
+}
+
+//------------------------------------------------------------------------------
+
void RasDataParser::initDataFiles()
{
iv_dataFiles.clear(); // initially empty
@@ -221,8 +272,9 @@
//------------------------------------------------------------------------------
-std::string RasDataParser::parseSignature(const nlohmann::json& i_data,
- const libhei::Signature& i_signature)
+std::string
+ RasDataParser::parseSignature(const nlohmann::json& i_data,
+ const libhei::Signature& i_signature) const
{
// Get the signature keys. All are hex (lower case) with no prefix.
char buf[5];
diff --git a/analyzer/ras-data/ras-data-parser.hpp b/analyzer/ras-data/ras-data-parser.hpp
index 17908d4..3f6c6b3 100644
--- a/analyzer/ras-data/ras-data-parser.hpp
+++ b/analyzer/ras-data/ras-data-parser.hpp
@@ -58,7 +58,15 @@
* @return True if the flag is set for the given signature, else false.
*/
bool isFlagSet(const libhei::Signature& i_signature,
- const RasDataFlags i_flag);
+ const RasDataFlags i_flag) const;
+
+ /**
+ * @brief Returns of the version of the relevant RAS data file for the
+ * input signature.
+ * @param i_signature The target error signature.
+ * @return The version of the RAS data file.
+ */
+ unsigned int getVersion(const libhei::Signature& i_signature) const;
private:
/**
@@ -76,7 +84,7 @@
* @return A string representing the target action for the signature.
*/
std::string parseSignature(const nlohmann::json& i_data,
- const libhei::Signature& i_signature);
+ const libhei::Signature& i_signature) const;
/**
* @brief Parses a bus object in the given data file and returns the bus
diff --git a/test/meson.build b/test/meson.build
index 492c96d..fe2cc03 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -48,6 +48,7 @@
# NOTE: Try to limit this, if possible, to prevent duplicate compilation.
test_additional_srcs = [
files(
+ '../analyzer/filter-root-cause.cpp',
'../analyzer/plugins/p10-plugins.cpp',
'../analyzer/plugins/p10-tod-plugins.cpp',
'../cli.cpp',
@@ -64,6 +65,7 @@
'test-pdbg-dts',
'test-pll-unlock',
'test-resolution',
+ 'test-root-cause-filter',
'test-tod-step-check-fault',
'test-cli',
]
diff --git a/test/test-root-cause-filter.cpp b/test/test-root-cause-filter.cpp
new file mode 100644
index 0000000..a870d8f
--- /dev/null
+++ b/test/test-root-cause-filter.cpp
@@ -0,0 +1,61 @@
+#include <stdio.h>
+
+#include <analyzer/analyzer_main.hpp>
+#include <analyzer/plugins/plugin.hpp>
+#include <analyzer/ras-data/ras-data-parser.hpp>
+#include <hei_util.hpp>
+#include <util/pdbg.hpp>
+#include <util/trace.hpp>
+
+#include "gtest/gtest.h"
+
+namespace analyzer
+{
+// Forward reference of filterRootCause
+bool filterRootCause(AnalysisType i_type,
+ const libhei::IsolationData& i_isoData,
+ libhei::Signature& o_rootCause,
+ const RasDataParser& i_rasData);
+} // namespace analyzer
+
+using namespace analyzer;
+
+static const auto eqCoreFir = static_cast<libhei::NodeId_t>(
+ libhei::hash<libhei::NodeId_t>("EQ_CORE_FIR"));
+
+static const auto rdfFir =
+ static_cast<libhei::NodeId_t>(libhei::hash<libhei::NodeId_t>("RDFFIR"));
+
+TEST(RootCauseFilter, Filter1)
+{
+ pdbg_targets_init(nullptr);
+
+ // Checkstop signature on the proc
+ auto proc0 = util::pdbg::getTrgt("/proc0");
+ libhei::Chip procChip0{proc0, P10_20};
+
+ // EQ_CORE_FIR[14]: ME = 0 checkstop
+ libhei::Signature checkstopSig{procChip0, eqCoreFir, 0, 14,
+ libhei::ATTN_TYPE_CHECKSTOP};
+
+ // Root cause signature on the ocmb
+ auto ocmb0 =
+ util::pdbg::getTrgt("proc0/pib/perv12/mc0/mi0/mcc0/omi0/ocmb0");
+ libhei::Chip ocmbChip0{ocmb0, EXPLORER_20};
+
+ // RDFFIR[14]: Mainline read UE
+ libhei::Signature ueSig{ocmbChip0, rdfFir, 0, 14,
+ libhei::ATTN_TYPE_RECOVERABLE};
+
+ // Add the signatures to the isolation data
+ libhei::IsolationData isoData{};
+ isoData.addSignature(checkstopSig);
+ isoData.addSignature(ueSig);
+
+ RasDataParser rasData{};
+ libhei::Signature rootCause;
+ bool attnFound = filterRootCause(AnalysisType::SYSTEM_CHECKSTOP, isoData,
+ rootCause, rasData);
+ EXPECT_TRUE(attnFound);
+ EXPECT_EQ(ueSig.toUint32(), rootCause.toUint32());
+}