blob: 218d38d1466e1824edea5e9fa98f0e197f603395 [file] [log] [blame]
#include <assert.h>
#include <unistd.h>
#include <analyzer/analyzer_main.hpp>
#include <analyzer/ras-data/ras-data-parser.hpp>
#include <analyzer/service_data.hpp>
#include <attn/attn_dump.hpp>
#include <hei_main.hpp>
#include <util/pdbg.hpp>
#include <util/trace.hpp>
namespace analyzer
{
//------------------------------------------------------------------------------
// Forward references for externally defined functions.
/**
* @brief Will get the list of active chip and initialize the isolator.
* @param o_chips The returned list of active chips.
*/
void initializeIsolator(std::vector<libhei::Chip>& o_chips);
/**
* @brief Will get the list of active chip and initialize the isolator.
* @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,
const RasDataParser& i_rasData);
/**
* @brief Will create and submit a PEL using the given data.
* @param i_servData Data regarding service actions gathered during analysis.
* @return The platform log ID. Will return zero if no PEL is generated.
*/
uint32_t commitPel(const ServiceData& i_servData);
//------------------------------------------------------------------------------
const char* __attn(libhei::AttentionType_t i_type)
{
const char* str = "";
switch (i_type)
{
case libhei::ATTN_TYPE_CHIP_CS:
str = "CHIP_CS";
break;
case libhei::ATTN_TYPE_UNIT_CS:
str = "UNIT_CS";
break;
case libhei::ATTN_TYPE_RECOVERABLE:
str = "RECOVERABLE";
break;
case libhei::ATTN_TYPE_SP_ATTN:
str = "SP_ATTN";
break;
case libhei::ATTN_TYPE_HOST_ATTN:
str = "HOST_ATTN";
break;
default:
trace::err("Unsupported attention type: %u", i_type);
assert(0);
}
return str;
}
//------------------------------------------------------------------------------
const char* __analysisType(AnalysisType i_type)
{
const char* str = "";
switch (i_type)
{
case AnalysisType::SYSTEM_CHECKSTOP:
str = "SYSTEM_CHECKSTOP";
break;
case AnalysisType::TERMINATE_IMMEDIATE:
str = "TERMINATE_IMMEDIATE";
break;
case AnalysisType::MANUAL:
str = "MANUAL";
break;
default:
trace::err("Unsupported analysis type: %u", i_type);
assert(0);
}
return str;
}
//------------------------------------------------------------------------------
uint32_t analyzeHardware(AnalysisType i_type, attn::DumpParameters& o_dump)
{
uint32_t o_plid = 0; // default, zero indicates PEL was not created
if (!util::pdbg::queryHardwareAnalysisSupported())
{
trace::err("Hardware error analysis is not supported on this system");
return o_plid;
}
trace::inf(">>> enter analyzeHardware(%s)", __analysisType(i_type));
// Initialize the isolator and get all of the chips to be analyzed.
trace::inf("Initializing the isolator...");
std::vector<libhei::Chip> chips;
initializeIsolator(chips);
// Isolate attentions.
trace::inf("Isolating errors: # of chips=%u", chips.size());
libhei::IsolationData isoData{};
libhei::isolate(chips, isoData);
// For debug, trace out the original list of signatures before filtering.
for (const auto& sig : isoData.getSignatureList())
{
trace::inf("Signature: %s 0x%0" PRIx32 " %s",
util::pdbg::getPath(sig.getChip()), sig.toUint32(),
__attn(sig.getAttnType()));
}
// Filter for root cause attention.
libhei::Signature rootCause{};
RasDataParser rasData{};
bool attnFound = false;
try
{
attnFound = filterRootCause(i_type, isoData, rootCause, rasData);
}
catch (const std::exception& e)
{
trace::err("Exception caught during root cause filtering");
trace::err(e.what());
attnFound = false; // just in case
}
// If a root cause attention was found, or if this was a system checkstop,
// generate a PEL.
if (attnFound || AnalysisType::SYSTEM_CHECKSTOP == i_type)
{
if (attnFound)
{
trace::inf("Root cause attention: %s 0x%0" PRIx32 " %s",
util::pdbg::getPath(rootCause.getChip()),
rootCause.toUint32(), __attn(rootCause.getAttnType()));
}
else
{
// This is bad. Analysis should have found a root cause attention
// for a system checkstop. Issues could range from code bugs to SCOM
// errors. Regardless, generate a PEL with FFDC to assist with
// debug.
trace::err("System checkstop with no root cause attention");
rootCause = libhei::Signature{}; // just in case
}
// Start building the service data.
ServiceData servData{rootCause, i_type, isoData};
// Apply any service actions, if needed. Note that there are no
// resolutions for manual analysis.
if (AnalysisType::MANUAL != i_type)
{
if (attnFound)
{
try
{
// Resolve the root cause attention.
rasData.getResolution(rootCause)->resolve(servData);
}
catch (const std::exception& e)
{
trace::err("Exception caught during root cause analysis");
trace::err(e.what());
// We'll still want to create a PEL for the FFDC, but
// since the analysis failed, we need to callout Level 2
// Support.
servData.calloutProcedure(callout::Procedure::NEXTLVL,
callout::Priority::HIGH);
}
}
else
{
// Analysis failed so callout the Level 2 Support.
servData.calloutProcedure(callout::Procedure::NEXTLVL,
callout::Priority::HIGH);
}
}
// Create and commit a PEL.
o_plid = commitPel(servData);
if (0 == o_plid)
{
trace::err("Failed to create PEL");
}
else
{
trace::inf("PEL created: PLID=0x%0" PRIx32, o_plid);
// Gather/return information needed for dump. A hardware dump will
// always be used for system checkstop attenions. Software dumps
// will be reserved for MP-IPLs during TI analysis.
// TODO: Need ID from root cause. At the moment, HUID does not exist
// in devtree. Will need a better ID definition.
o_dump.unitId = 0;
o_dump.dumpType = attn::DumpType::Hardware;
}
}
else
{
// It is possible for TI handling, or manually initiated analysis via
// the command line, that there will not be an active attention. In
// which case, we will do nothing and let the caller of this function
// determine if this is the expected behavior.
trace::inf("No active attentions found");
}
// All done, clean up the isolator.
trace::inf("Uninitializing isolator...");
libhei::uninitialize();
trace::inf("<<< exit analyzeHardware()");
return o_plid;
}
//------------------------------------------------------------------------------
} // namespace analyzer