Update primary SRC field based on callout list
Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: I41f3eda5c27b8ec74d6329b8f145181f400547f8
diff --git a/analyzer/callout.hpp b/analyzer/callout.hpp
index 2e04d48..adb2fd4 100644
--- a/analyzer/callout.hpp
+++ b/analyzer/callout.hpp
@@ -72,6 +72,29 @@
return m.at(i_priority);
}
+/** These SRC subsystem values are defined by the PEL spec. */
+enum class SrcSubsystem
+{
+ // Can also reference `extensions/openpower-pels/pel_values.cpp` from
+ // `openbmc/phosphor-logging` for the full list of these values.
+
+ PROCESSOR = 0x10,
+ PROCESSOR_UNIT = 0x13,
+ PROCESSOR_BUS = 0x14,
+
+ MEMORY = 0x20,
+ MEMORY_BUS = 0x22,
+ MEMORY_DIMM = 0x23,
+
+ PHB = 0x38,
+
+ CEC_HARDWARE = 0x50,
+ CEC_CLOCKS = 0x58,
+ CEC_TOD = 0x5A,
+
+ OTHERS = 0x70,
+};
+
/** @brief Container class for procedure callout service actions. */
class Procedure
{
@@ -85,21 +108,33 @@
* @param i_string The string representation of the procedure used for
* callouts.
*/
- explicit Procedure(const std::string& i_string) : iv_string(i_string) {}
+ Procedure(const std::string& i_string, const SrcSubsystem i_subsystem) :
+ iv_string(i_string), iv_subsystem(i_subsystem)
+ {}
private:
/** The string representation of the procedure used for callouts. */
const std::string iv_string;
+ /** The associated SRC subsystem of the procedure. */
+ const SrcSubsystem iv_subsystem;
+
public:
/** iv_string accessor */
std::string getString() const
{
return iv_string;
}
+
+ /** iv_subsystem accessor */
+ SrcSubsystem getSrcSubsystem() const
+ {
+ return iv_subsystem;
+ }
};
-inline const Procedure Procedure::NEXTLVL{"next_level_support"};
+inline const Procedure Procedure::NEXTLVL{"next_level_support",
+ SrcSubsystem::OTHERS};
/** @brief Container class for bus callout service actions. */
class BusType
@@ -117,16 +152,22 @@
* @param i_string The string representation of the procedure used for
* callouts.
*/
- explicit BusType(const std::string& i_string) : iv_string(i_string) {}
+ BusType(const std::string& i_string, const SrcSubsystem i_subsystem) :
+ iv_string(i_string), iv_subsystem(i_subsystem)
+ {}
private:
/** The string representation of the procedure used for callouts. */
const std::string iv_string;
+ /** The associated SRC subsystem of the bus. */
+ const SrcSubsystem iv_subsystem;
+
public:
bool operator==(const BusType& r) const
{
- return this->iv_string == r.iv_string;
+ return ((this->iv_string == r.iv_string) &&
+ (this->iv_subsystem == r.iv_subsystem));
}
/** iv_string accessor */
@@ -134,10 +175,16 @@
{
return iv_string;
}
+
+ /** iv_subsystem accessor */
+ SrcSubsystem getSrcSubsystem() const
+ {
+ return iv_subsystem;
+ }
};
-inline const BusType BusType::SMP_BUS{"SMP_BUS"};
-inline const BusType BusType::OMI_BUS{"OMI_BUS"};
+inline const BusType BusType::SMP_BUS{"SMP_BUS", SrcSubsystem::PROCESSOR_BUS};
+inline const BusType BusType::OMI_BUS{"OMI_BUS", SrcSubsystem::MEMORY_BUS};
/** @brief Container class for clock callout service actions. */
class ClockType
@@ -158,23 +205,36 @@
* @param i_string The string representation of the procedure used for
* callouts.
*/
- explicit ClockType(const std::string& i_string) : iv_string(i_string) {}
+ ClockType(const std::string& i_string, const SrcSubsystem i_subsystem) :
+ iv_string(i_string), iv_subsystem(i_subsystem)
+ {}
private:
/** The string representation of the procedure used for callouts. */
const std::string iv_string;
+ /** The associated SRC subsystem of the clock. */
+ const SrcSubsystem iv_subsystem;
+
public:
/** iv_string accessor */
std::string getString() const
{
return iv_string;
}
+
+ /** iv_subsystem accessor */
+ SrcSubsystem getSrcSubsystem() const
+ {
+ return iv_subsystem;
+ }
};
-inline const ClockType ClockType::OSC_REF_CLOCK_0{"OSC_REF_CLOCK_0"};
-inline const ClockType ClockType::OSC_REF_CLOCK_1{"OSC_REF_CLOCK_1"};
-inline const ClockType ClockType::TOD_CLOCK{"TOD_CLOCK"};
+inline const ClockType ClockType::OSC_REF_CLOCK_0{"OSC_REF_CLOCK_0",
+ SrcSubsystem::CEC_CLOCKS};
+inline const ClockType ClockType::OSC_REF_CLOCK_1{"OSC_REF_CLOCK_1",
+ SrcSubsystem::CEC_CLOCKS};
+inline const ClockType ClockType::TOD_CLOCK{"TOD_CLOCK", SrcSubsystem::CEC_TOD};
/** @brief Container class for part callout service actions. */
class PartType
@@ -188,16 +248,22 @@
* @brief Constructor from components.
* @param i_string The string representation of the part callout.
*/
- explicit PartType(const std::string& i_string) : iv_string(i_string) {}
+ PartType(const std::string& i_string, const SrcSubsystem i_subsystem) :
+ iv_string(i_string), iv_subsystem(i_subsystem)
+ {}
private:
/** The string representation of the part callout. */
const std::string iv_string;
+ /** The associated SRC subsystem of the part. */
+ const SrcSubsystem iv_subsystem;
+
public:
bool operator==(const PartType& r) const
{
- return this->iv_string == r.iv_string;
+ return ((this->iv_string == r.iv_string) &&
+ (this->iv_subsystem == r.iv_subsystem));
}
/** iv_string accessor */
@@ -205,9 +271,15 @@
{
return iv_string;
}
+
+ /** iv_subsystem accessor */
+ SrcSubsystem getSrcSubsystem() const
+ {
+ return iv_subsystem;
+ }
};
-inline const PartType PartType::PNOR{"PNOR"};
+inline const PartType PartType::PNOR{"PNOR", SrcSubsystem::CEC_HARDWARE};
/** @brief Container class for guard service actions. */
class GuardType
diff --git a/analyzer/create_pel.cpp b/analyzer/create_pel.cpp
index a5982ea..cb9610b 100644
--- a/analyzer/create_pel.cpp
+++ b/analyzer/create_pel.cpp
@@ -330,6 +330,9 @@
// until the PEL is submitted.
std::vector<util::FFDCFile> userDataFiles;
+ // Set the subsystem in the primary SRC.
+ i_servData.addSrcSubsystem(logData);
+
// Set words 6-9 of the SRC.
__setSrc(i_servData.getRootCause(), logData);
diff --git a/analyzer/meson.build b/analyzer/meson.build
index 3d34630..12f5100 100644
--- a/analyzer/meson.build
+++ b/analyzer/meson.build
@@ -18,6 +18,7 @@
# Library dependencies.
analyzer_deps = [
dbus_interfaces_dep,
+ fmt_dep,
libhei_dep,
nlohmann_json_dep,
sdbusplus_dep,
diff --git a/analyzer/service_data.cpp b/analyzer/service_data.cpp
index c13bc8b..2a7d5f5 100644
--- a/analyzer/service_data.cpp
+++ b/analyzer/service_data.cpp
@@ -18,6 +18,7 @@
ffdc["Priority"] = callout::getStringFFDC(i_priority);
ffdc["Guard"] = i_guard;
addCalloutFFDC(ffdc);
+ setSrcSubsystem(getTargetSubsystem(i_target), i_priority);
}
//------------------------------------------------------------------------------
@@ -41,6 +42,7 @@
ffdc["Priority"] = callout::getStringFFDC(i_priority);
ffdc["Guard"] = i_guard;
addCalloutFFDC(ffdc);
+ setSrcSubsystem(getTargetSubsystem(txTarget), i_priority);
}
//------------------------------------------------------------------------------
@@ -71,6 +73,7 @@
ffdc["Priority"] = callout::getStringFFDC(i_priority);
ffdc["Guard"] = i_guard;
addCalloutFFDC(ffdc);
+ setSrcSubsystem(i_busType.getSrcSubsystem(), i_priority);
}
//------------------------------------------------------------------------------
@@ -91,6 +94,7 @@
ffdc["Clock Type"] = i_clockType.getString();
ffdc["Priority"] = callout::getStringFFDC(i_priority);
addCalloutFFDC(ffdc);
+ setSrcSubsystem(i_clockType.getSrcSubsystem(), i_priority);
}
//------------------------------------------------------------------------------
@@ -110,6 +114,7 @@
ffdc["Procedure"] = i_procedure.getString();
ffdc["Priority"] = callout::getStringFFDC(i_priority);
addCalloutFFDC(ffdc);
+ setSrcSubsystem(i_procedure.getSrcSubsystem(), i_priority);
}
//------------------------------------------------------------------------------
@@ -135,6 +140,7 @@
ffdc["Part Type"] = i_part.getString();
ffdc["Priority"] = callout::getStringFFDC(i_priority);
addCalloutFFDC(ffdc);
+ setSrcSubsystem(i_part.getSrcSubsystem(), i_priority);
}
//------------------------------------------------------------------------------
@@ -235,4 +241,78 @@
//------------------------------------------------------------------------------
+void ServiceData::setSrcSubsystem(callout::SrcSubsystem i_subsystem,
+ callout::Priority i_priority)
+{
+ // clang-format off
+ static const std::map<callout::Priority, unsigned int> m =
+ {
+ // Note that all medium priorities, including groups A, B, and C, are
+ // the same priority.
+ {callout::Priority::HIGH, 3},
+ {callout::Priority::MED, 2},
+ {callout::Priority::MED_A, 2},
+ {callout::Priority::MED_B, 2},
+ {callout::Priority::MED_C, 2},
+ {callout::Priority::LOW, 1},
+ };
+ // clang-format on
+
+ // The default subsystem is CEC_HARDWARE with LOW priority. Change the
+ // subsystem if the given subsystem has a higher priority or if the stored
+ // subsystem is still the default.
+ if (m.at(iv_srcSubsystem.second) < m.at(i_priority) ||
+ (callout::SrcSubsystem::CEC_HARDWARE == iv_srcSubsystem.first &&
+ callout::Priority::LOW == iv_srcSubsystem.second))
+ {
+ iv_srcSubsystem.first = i_subsystem;
+ iv_srcSubsystem.second = i_priority;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+callout::SrcSubsystem ServiceData::getTargetSubsystem(pdbg_target* i_target)
+{
+ using TargetType_t = util::pdbg::TargetType_t;
+
+ // Default the subsystem to CEC_HARDWARE
+ callout::SrcSubsystem o_subSys = callout::SrcSubsystem::CEC_HARDWARE;
+
+ // clang-format off
+ static const std::map<uint8_t, callout::SrcSubsystem> subSysMap =
+ {
+ {TargetType_t::TYPE_DIMM, callout::SrcSubsystem::MEMORY_DIMM },
+ {TargetType_t::TYPE_PROC, callout::SrcSubsystem::PROCESSOR },
+ {TargetType_t::TYPE_CORE, callout::SrcSubsystem::PROCESSOR_UNIT},
+ {TargetType_t::TYPE_EQ, callout::SrcSubsystem::PROCESSOR },
+ {TargetType_t::TYPE_PEC, callout::SrcSubsystem::PHB },
+ {TargetType_t::TYPE_PHB, callout::SrcSubsystem::PHB },
+ {TargetType_t::TYPE_MC, callout::SrcSubsystem::MEMORY },
+ {TargetType_t::TYPE_IOLINK, callout::SrcSubsystem::CEC_HARDWARE },
+ {TargetType_t::TYPE_OMI, callout::SrcSubsystem::MEMORY },
+ {TargetType_t::TYPE_MCC, callout::SrcSubsystem::MEMORY },
+ {TargetType_t::TYPE_OMIC, callout::SrcSubsystem::MEMORY },
+ {TargetType_t::TYPE_OCMB, callout::SrcSubsystem::MEMORY },
+ {TargetType_t::TYPE_MEM_PORT, callout::SrcSubsystem::MEMORY },
+ {TargetType_t::TYPE_NMMU, callout::SrcSubsystem::PROCESSOR },
+ {TargetType_t::TYPE_PAU, callout::SrcSubsystem::PROCESSOR_BUS },
+ {TargetType_t::TYPE_IOHS, callout::SrcSubsystem::PROCESSOR_BUS },
+ {TargetType_t::TYPE_PAUC, callout::SrcSubsystem::PROCESSOR },
+ };
+ // clang-format on
+
+ auto targetType = util::pdbg::getTrgtType(i_target);
+
+ // If the type of the input target exists in the map, update the output
+ if (subSysMap.count(targetType) > 0)
+ {
+ o_subSys = subSysMap.at(targetType);
+ }
+
+ return o_subSys;
+}
+
+//------------------------------------------------------------------------------
+
} // namespace analyzer
diff --git a/analyzer/service_data.hpp b/analyzer/service_data.hpp
index 90ebf2f..c1f681e 100644
--- a/analyzer/service_data.hpp
+++ b/analyzer/service_data.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include <fmt/format.h>
+
#include <analyzer/analyzer_main.hpp>
#include <analyzer/callout.hpp>
#include <hei_main.hpp>
@@ -156,6 +158,23 @@
return iv_calloutFFDC;
}
+ /**
+ * @brief Adds the SRC subsystem to the given additional PEL data.
+ * @param io_additionalData The additional PEL data.
+ */
+ void addSrcSubsystem(
+ std::map<std::string, std::string>& io_additionalData) const
+ {
+ io_additionalData["PEL_SUBSYSTEM"] =
+ fmt::format("0x{:02x}", iv_srcSubsystem.first);
+ }
+
+ /** @brief Accessor to iv_srcSubsystem. */
+ const std::pair<callout::SrcSubsystem, callout::Priority> getSubsys() const
+ {
+ return iv_srcSubsystem;
+ }
+
private:
/**
* @brief Add callout information to the callout list.
@@ -189,6 +208,31 @@
* @param i_priority The callout priority.
*/
void addBackplaneCallout(callout::Priority i_priority);
+
+ private:
+ /**
+ * @brief Compares the current SRC subsystem type with the given SRC
+ * subsystem type and stores the highest priority callout subsystem.
+ * If the two subsystems are of equal priority. The stored subsystem
+ * is used.
+ * @param i_subsystem The given subsystem type.
+ * @param i_priority The callout priority associated with the given
+ * subsystem.
+ */
+ void setSrcSubsystem(callout::SrcSubsystem i_subsystem,
+ callout::Priority i_priority);
+
+ /**
+ * @brief Returns the appropriate SRC subsystem based on the input target.
+ * @param i_trgt The given pdbg target.
+ */
+ callout::SrcSubsystem getTargetSubsystem(pdbg_target* i_target);
+
+ /** The SRC subsystem field (2nd byte of the primary SRC) is based on the
+ * callouts the PEL. As callouts are to the service data, we'll need to
+ * keep track of the highest priority callout subsystem. */
+ std::pair<callout::SrcSubsystem, callout::Priority> iv_srcSubsystem = {
+ callout::SrcSubsystem::CEC_HARDWARE, callout::Priority::LOW};
};
} // namespace analyzer
diff --git a/meson.build b/meson.build
index deee608..6ee92ce 100644
--- a/meson.build
+++ b/meson.build
@@ -61,6 +61,8 @@
libpdbg_dep = cmplr.find_library('pdbg')
+fmt_dep = dependency('fmt')
+
if get_option('phal').enabled()
libphal_dep = cmplr.find_library('phal')
endif
diff --git a/test/test-resolution.cpp b/test/test-resolution.cpp
index e9b2104..35f6307 100644
--- a/test/test-resolution.cpp
+++ b/test/test-resolution.cpp
@@ -65,6 +65,14 @@
l1->resolve(sd1);
l2->resolve(sd2);
+ // Verify the subsystems
+ std::pair<callout::SrcSubsystem, callout::Priority> subsys = {
+ callout::SrcSubsystem::PROCESSOR, callout::Priority::HIGH};
+ EXPECT_EQ(sd1.getSubsys(), subsys);
+
+ subsys = {callout::SrcSubsystem::PROCESSOR, callout::Priority::HIGH};
+ EXPECT_EQ(sd2.getSubsys(), subsys);
+
// Start verifying
nlohmann::json j{};
std::string s{};
@@ -146,6 +154,11 @@
c1->resolve(sd);
+ // Verify the subsystem
+ std::pair<callout::SrcSubsystem, callout::Priority> subsys = {
+ callout::SrcSubsystem::MEMORY, callout::Priority::MED_A};
+ EXPECT_EQ(sd.getSubsys(), subsys);
+
nlohmann::json j{};
std::string s{};
@@ -201,6 +214,11 @@
c2->resolve(sd);
c3->resolve(sd);
+ // Verify the subsystem
+ std::pair<callout::SrcSubsystem, callout::Priority> subsys = {
+ callout::SrcSubsystem::CEC_HARDWARE, callout::Priority::MED_A};
+ EXPECT_EQ(sd.getSubsys(), subsys);
+
// Callout list
j = sd.getCalloutList();
s = R"([
@@ -287,6 +305,11 @@
c2->resolve(sd);
c3->resolve(sd);
+ // Verify the subsystem
+ std::pair<callout::SrcSubsystem, callout::Priority> subsys = {
+ callout::SrcSubsystem::MEMORY, callout::Priority::MED_A};
+ EXPECT_EQ(sd.getSubsys(), subsys);
+
// Callout list
j = sd.getCalloutList();
s = R"([
@@ -358,6 +381,11 @@
c1->resolve(sd);
+ // Verify the subsystem
+ std::pair<callout::SrcSubsystem, callout::Priority> subsys = {
+ callout::SrcSubsystem::CEC_CLOCKS, callout::Priority::HIGH};
+ EXPECT_EQ(sd.getSubsys(), subsys);
+
nlohmann::json j{};
std::string s{};
@@ -399,6 +427,11 @@
c1->resolve(sd);
+ // Verify the subsystem
+ std::pair<callout::SrcSubsystem, callout::Priority> subsys = {
+ callout::SrcSubsystem::OTHERS, callout::Priority::LOW};
+ EXPECT_EQ(sd.getSubsys(), subsys);
+
nlohmann::json j{};
std::string s{};
@@ -438,6 +471,11 @@
c1->resolve(sd);
+ // Verify the subsystem
+ std::pair<callout::SrcSubsystem, callout::Priority> subsys = {
+ callout::SrcSubsystem::CEC_HARDWARE, callout::Priority::MED};
+ EXPECT_EQ(sd.getSubsys(), subsys);
+
nlohmann::json j{};
std::string s{};
diff --git a/util/pdbg.hpp b/util/pdbg.hpp
index b8af56f..cd8c737 100644
--- a/util/pdbg.hpp
+++ b/util/pdbg.hpp
@@ -23,11 +23,23 @@
/** Chip target types. */
enum TargetType_t : uint8_t
{
- TYPE_PROC = 0x05,
- TYPE_IOLINK = 0x47,
- TYPE_OMI = 0x48,
- TYPE_OCMB = 0x4b,
- TYPE_IOHS = 0x51,
+ TYPE_DIMM = 0x03,
+ TYPE_PROC = 0x05,
+ TYPE_CORE = 0x07,
+ TYPE_EQ = 0x23,
+ TYPE_PEC = 0x2d,
+ TYPE_PHB = 0x2e,
+ TYPE_MC = 0x44,
+ TYPE_IOLINK = 0x47,
+ TYPE_OMI = 0x48,
+ TYPE_MCC = 0x49,
+ TYPE_OMIC = 0x4a,
+ TYPE_OCMB = 0x4b,
+ TYPE_MEM_PORT = 0x4c,
+ TYPE_NMMU = 0x4f,
+ TYPE_PAU = 0x50,
+ TYPE_IOHS = 0x51,
+ TYPE_PAUC = 0x52,
};
/** @return The target associated with the given chip. */