Platform Event Log (PEL) generation support added
Attention events will now generate an associated PEL
Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
Change-Id: I8d2c73657cc7eced93e6465c391c0a600c4278fa
diff --git a/attn/attn_handler.cpp b/attn/attn_handler.cpp
index 8c26bb3..341fe2b 100644
--- a/attn/attn_handler.cpp
+++ b/attn/attn_handler.cpp
@@ -1,12 +1,13 @@
#include <analyzer/analyzer_main.hpp>
#include <attention.hpp>
#include <attn_config.hpp>
+#include <attn_logging.hpp>
#include <bp_handler.hpp>
-#include <logging.hpp>
#include <ti_handler.hpp>
#include <algorithm>
#include <iomanip>
+#include <map>
#include <sstream>
#include <vector>
@@ -14,8 +15,13 @@
{
/** @brief Return codes */
-static constexpr int RC_SUCCESS = 0;
-static constexpr int RC_NOT_SUCCESS = 1;
+enum ReturnCodes
+{
+ RC_SUCCESS = 0,
+ RC_NOT_HANDLED,
+ RC_ANALYZER_ERROR,
+ RC_CFAM_ERROR
+};
/**
* @brief Handle SBE vital attention
@@ -59,24 +65,28 @@
uint32_t proc;
// loop through processors looking for active attentions
- log<level::INFO>("Attention handler started");
+ trace<level::INFO>("Attention handler started");
pdbg_target* target;
pdbg_for_each_class_target("fsi", target)
{
- log<level::INFO>("iterating targets");
+ trace<level::INFO>("iterating targets");
if (PDBG_TARGET_ENABLED == pdbg_target_probe(target))
{
proc = pdbg_target_index(target); // get processor number
std::stringstream ss; // log message stream
ss << "checking processor " << proc;
- log<level::INFO>(ss.str().c_str());
+ trace<level::INFO>(ss.str().c_str());
// get active attentions on processor
if (RC_SUCCESS != fsi_read(target, 0x1007, &isr_val))
{
- log<level::INFO>("Error! cfam read 0x1007 FAILED");
+ // event
+ eventAttentionFail(RC_CFAM_ERROR);
+
+ // trace
+ trace<level::INFO>("Error! cfam read 0x1007 FAILED");
}
else
{
@@ -84,12 +94,16 @@
ss << "cfam 0x1007 = 0x";
ss << std::hex << std::setw(8) << std::setfill('0');
ss << isr_val;
- log<level::INFO>(ss.str().c_str());
+ trace<level::INFO>(ss.str().c_str());
// get interrupt enabled special attentions mask
if (RC_SUCCESS != fsi_read(target, 0x100d, &isr_mask))
{
- log<level::INFO>("Error! cfam read 0x100d FAILED");
+ // event
+ eventAttentionFail(RC_CFAM_ERROR);
+
+ // trace
+ trace<level::INFO>("Error! cfam read 0x100d FAILED");
}
else
{
@@ -97,7 +111,7 @@
ss << "cfam 0x100d = 0x";
ss << std::hex << std::setw(8) << std::setfill('0');
ss << isr_mask;
- log<level::INFO>(ss.str().c_str());
+ trace<level::INFO>(ss.str().c_str());
// bit 0 on "left": bit 30 = SBE vital attention
if (isr_val & isr_mask & 0x00000002)
@@ -138,6 +152,7 @@
// handle highest priority attention, done if successful
if (RC_SUCCESS == active_attentions.front().handle())
{
+ // an attention was handled so we are done
break;
}
@@ -160,16 +175,28 @@
{
int rc = RC_SUCCESS; // assume vital handled
+ trace<level::INFO>("vital handler started");
+
// if vital handling enabled, handle vital attention
if (false == (i_attention->getConfig()->getFlag(enVital)))
{
- log<level::INFO>("vital handling disabled");
- rc = RC_NOT_SUCCESS;
+ trace<level::INFO>("vital handling disabled");
}
else
{
- log<level::INFO>("vital NOT handled");
- rc = RC_NOT_SUCCESS;
+ // TODO need vital attention handling
+
+ // FIXME TEMP CODE - begin
+ if (0)
+ {
+ eventVital();
+ }
+ else
+ {
+ trace<level::INFO>("vital NOT handled"); // enabled but not handled
+ rc = RC_NOT_HANDLED;
+ }
+ // FIXME TEMP CODE -end
}
return rc;
@@ -187,16 +214,33 @@
{
int rc = RC_SUCCESS; // assume checkstop handled
+ trace<level::INFO>("checkstop handler started");
+
// if checkstop handling enabled, handle checkstop attention
if (false == (i_attention->getConfig()->getFlag(enCheckstop)))
{
- log<level::INFO>("Checkstop handling disabled");
- rc = RC_NOT_SUCCESS;
+ trace<level::INFO>("Checkstop handling disabled");
}
else
{
- analyzer::analyzeHardware();
- rc = RC_SUCCESS;
+ // errors that were isolated
+ std::map<std::string, std::string> errors;
+
+ rc = analyzer::analyzeHardware(errors); // analyze hardware
+
+ if (RC_SUCCESS != rc)
+ {
+ rc = RC_ANALYZER_ERROR;
+ }
+ else
+ {
+ std::stringstream ss;
+ ss << "Analyzer isolated " << errors.size() << " error(s)";
+ trace<level::INFO>(ss.str().c_str());
+
+ // add checkstop event to log
+ eventCheckstop(errors);
+ }
}
return rc;
@@ -211,8 +255,11 @@
*/
int handleSpecial(Attention* i_attention)
{
- int rc = RC_NOT_SUCCESS; // assume special attention handling disabled
+ int rc = RC_SUCCESS; // assume special attention handled
+ trace<level::INFO>("special attention handler started");
+
+ // TODO
// Until the special attention chipop is availabe we will treat the special
// attention as a TI. If TI handling is disabled we will treat the special
// attention as a breakpopint.
@@ -220,27 +267,28 @@
// TI attention gets priority over breakpoints, if enabled then handle
if (true == (i_attention->getConfig()->getFlag(enTerminate)))
{
- log<level::INFO>("TI (terminate immediately)");
+ trace<level::INFO>("TI (terminate immediately)");
// Call TI special attention handler
tiHandler();
- rc = RC_SUCCESS;
+
+ // generate log event
+ eventTerminate();
}
else
{
if (true == (i_attention->getConfig()->getFlag(enBreakpoints)))
{
- log<level::INFO>("breakpoint");
+ trace<level::INFO>("breakpoint");
// Call the breakpoint special attention handler
bpHandler();
- rc = RC_SUCCESS;
}
}
if (RC_SUCCESS != rc)
{
- log<level::INFO>("Special attn handling disabled");
+ trace<level::INFO>("Special attn handling disabled");
}
return rc;
diff --git a/attn/attn_logging.cpp b/attn/attn_logging.cpp
new file mode 100644
index 0000000..e164f66
--- /dev/null
+++ b/attn/attn_logging.cpp
@@ -0,0 +1,136 @@
+#include <unistd.h>
+
+#include <attn_logging.hpp>
+#include <phosphor-logging/log.hpp>
+
+namespace attn
+{
+
+/** @brief journal entry of type INFO using phosphor logging */
+template <>
+void trace<INFO>(const char* i_message)
+{
+ phosphor::logging::log<phosphor::logging::level::INFO>(i_message);
+}
+
+/** @brief add an event to the log for PEL generation */
+void event(EventType i_event, std::map<std::string, std::string>& i_additional)
+{
+ bool eventValid = false; // assume no event created
+
+ std::string eventName;
+
+ switch (i_event)
+ {
+ case EventType::Checkstop:
+ eventName = "org.open_power.HwDiags.Error.Checkstop";
+ eventValid = true;
+ break;
+ case EventType::Terminate:
+ eventName = "org.open_power.Attn.Error.Terminate";
+ eventValid = true;
+ break;
+ case EventType::Vital:
+ eventName = "org.open_power.Attn.Error.Vital";
+ eventValid = true;
+ break;
+ case EventType::HwDiagsFail:
+ eventName = "org.open_power.HwDiags.Error.Fail";
+ eventValid = true;
+ break;
+ case EventType::AttentionFail:
+ eventName = "org.open_power.Attn.Error.Fail";
+ eventValid = true;
+ break;
+ default:
+ eventValid = false;
+ break;
+ }
+
+ if (true == eventValid)
+ {
+ // Get access to logging interface and method for creating log
+ auto bus = sdbusplus::bus::new_default_system();
+
+ // using direct create method (for additional data)
+ auto method = bus.new_method_call(
+ "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
+ "xyz.openbmc_project.Logging.Create", "Create");
+
+ // attach additional data
+ method.append(eventName,
+ "xyz.openbmc_project.Logging.Entry.Level.Error",
+ i_additional);
+
+ // log the event
+ auto reply = bus.call(method);
+ }
+}
+
+/** @brief commit checkstop event to log */
+void eventCheckstop(std::map<std::string, std::string>& i_errors)
+{
+ std::map<std::string, std::string> additionalData;
+
+ // TODO need multi-error/multi-callout stuff here
+
+ // if analyzer isolated errors
+ if (!(i_errors.empty()))
+ {
+ // FIXME TEMP CODE - begin
+
+ std::string signature = i_errors.begin()->first;
+ std::string chip = i_errors.begin()->second;
+
+ additionalData["_PID"] = std::to_string(getpid());
+ additionalData["SIGNATURE"] = signature;
+ additionalData["CHIP_ID"] = chip;
+
+ // FIXME TEMP CODE -end
+
+ event(EventType::Checkstop, additionalData);
+ }
+}
+
+/** @brief commit special attention TI event to log */
+void eventTerminate()
+{
+ std::map<std::string, std::string> additionalData;
+
+ additionalData["_PID"] = std::to_string(getpid());
+
+ event(EventType::Terminate, additionalData);
+}
+
+/** @brief commit SBE vital event to log */
+void eventVital()
+{
+ std::map<std::string, std::string> additionalData;
+
+ additionalData["_PID"] = std::to_string(getpid());
+
+ event(EventType::Vital, additionalData);
+}
+
+/** @brief commit analyzer failure event to log */
+void eventHwDiagsFail(int i_error)
+{
+ std::map<std::string, std::string> additionalData;
+
+ additionalData["_PID"] = std::to_string(getpid());
+
+ event(EventType::HwDiagsFail, additionalData);
+}
+
+/** @brief commit attention handler failure event to log */
+void eventAttentionFail(int i_error)
+{
+ std::map<std::string, std::string> additionalData;
+
+ additionalData["_PID"] = std::to_string(getpid());
+ additionalData["ERROR_CODE"] = std::to_string(i_error);
+
+ event(EventType::AttentionFail, additionalData);
+}
+
+} // namespace attn
diff --git a/attn/attn_logging.hpp b/attn/attn_logging.hpp
new file mode 100644
index 0000000..2446ba6
--- /dev/null
+++ b/attn/attn_logging.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <cstddef> // for size_t
+#include <map>
+#include <string>
+
+namespace attn
+{
+
+/** @brief Logging level types */
+enum level
+{
+ INFO
+};
+
+/** @brief Logging event types */
+enum class EventType
+{
+ Checkstop = 0,
+ Terminate = 1,
+ Vital = 2,
+ HwDiagsFail = 3,
+ AttentionFail = 4
+};
+
+/** @brief Maximum length of a single trace event message */
+static const size_t trace_msg_max_len = 255;
+
+/** @brief create trace message */
+template <level L>
+void trace(const char* i_message);
+
+/** @brief commit checkstop event to log */
+void eventCheckstop(std::map<std::string, std::string>& i_errors);
+
+/** @brief commit special attention TI event to log */
+void eventTerminate();
+
+/** @brief commit SBE vital event to log */
+void eventVital();
+
+/** @brief commit analyzer failure event to log */
+void eventHwDiagsFail(int i_error);
+
+/** @brief commit attention handler failure event to log */
+void eventAttentionFail(int i_error);
+
+} // namespace attn
diff --git a/attn/attn_monitor.cpp b/attn/attn_monitor.cpp
index 25bdce4..31766c4 100644
--- a/attn/attn_monitor.cpp
+++ b/attn/attn_monitor.cpp
@@ -1,8 +1,6 @@
-#include "attn_monitor.hpp"
-
-#include "attn_handler.hpp"
-
-#include <logging.hpp>
+#include <attn_handler.hpp>
+#include <attn_logging.hpp>
+#include <attn_monitor.hpp>
namespace attn
{
@@ -11,7 +9,7 @@
void AttnMonitor::scheduleGPIOEvent()
{
std::string logMessage = "... waiting for events ...";
- log<level::INFO>(logMessage.c_str());
+ trace<level::INFO>(logMessage.c_str());
// Register async callback, note that callback is a
// lambda function with "this" pointer captured
@@ -22,11 +20,12 @@
{
std::string logMessage =
"GPIO Async wait error: " + std::string(ec.message());
- log<level::INFO>(logMessage.c_str());
+ trace<level::INFO>(logMessage.c_str());
}
else
{
- log<level::INFO>("Attention monitor detected active attention");
+ trace<level::INFO>(
+ "Attention monitor detected active attention");
handleGPIOEvent(); // gpio trigger detected
}
return;
@@ -43,7 +42,7 @@
&gpioEvent) < 0)
{
logMessage = "GPIO line read failed";
- log<level::INFO>(logMessage.c_str());
+ trace<level::INFO>(logMessage.c_str());
}
else
{
@@ -52,20 +51,20 @@
// active attention when gpio == 0
case 0:
logMessage = "Attention monitor calling attention handler";
- log<level::INFO>(logMessage.c_str());
+ trace<level::INFO>(logMessage.c_str());
attnHandler(iv_config);
break;
// gpio == 1, GPIO handler should not be executing
case 1:
logMessage = "GPIO handler out of sync";
- log<level::INFO>(logMessage.c_str());
+ trace<level::INFO>(logMessage.c_str());
break;
// unexpected value
default:
logMessage = "GPIO line unexpected value";
- log<level::INFO>(logMessage.c_str());
+ trace<level::INFO>(logMessage.c_str());
}
}
scheduleGPIOEvent(); // continue monitoring gpio
@@ -77,7 +76,7 @@
if (0 != gpiod_line_request(iv_gpioLine, &iv_gpioConfig, 0))
{
std::string logMessage = "failed request for GPIO";
- log<level::INFO>(logMessage.c_str());
+ trace<level::INFO>(logMessage.c_str());
}
else
{
@@ -87,7 +86,7 @@
if (gpioLineFd < 0)
{
std::string logMessage = "failed to get file descriptor";
- log<level::INFO>(logMessage.c_str());
+ trace<level::INFO>(logMessage.c_str());
}
else
{
diff --git a/attn/bp_handler.cpp b/attn/bp_handler.cpp
index 4ab734d..72e03f2 100644
--- a/attn/bp_handler.cpp
+++ b/attn/bp_handler.cpp
@@ -1,4 +1,4 @@
-#include <logging.hpp>
+#include <attn_logging.hpp>
#include <sdbusplus/bus.hpp>
namespace attn
@@ -13,7 +13,7 @@
void bpHandler()
{
// trace message
- log<level::INFO>("Notify Cronus");
+ trace<level::INFO>("Notify Cronus");
// notify Cronus over dbus
auto bus = sdbusplus::bus::new_system();
diff --git a/attn/logging.cpp b/attn/logging.cpp
deleted file mode 100644
index 423e9ca..0000000
--- a/attn/logging.cpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <logging.hpp>
-#include <phosphor-logging/log.hpp>
-
-namespace attn
-{
-
-/** @brief Log message of type INFO using phosphor logging */
-template <>
-void log<INFO>(const char* i_message)
-{
- phosphor::logging::log<phosphor::logging::level::INFO>(i_message);
-}
-
-} // namespace attn
diff --git a/attn/logging.hpp b/attn/logging.hpp
deleted file mode 100644
index 9a4b0dc..0000000
--- a/attn/logging.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-namespace attn
-{
-
-/** @brief Logging level types */
-enum level
-{
- INFO
-};
-
-/**
- * @brief Log message of different types
- *
- * Log messages of different types (level) such as informational, debug,
- * errors etc.
- */
-template <level L>
-void log(const char* i_message);
-
-} // namespace attn
diff --git a/attn/meson.build b/attn/meson.build
index 92254db..5d53674 100644
--- a/attn/meson.build
+++ b/attn/meson.build
@@ -28,7 +28,7 @@
# see if phosphor-logging is available, if not use test case logging code
h = 'phosphor-logging/log.hpp'
if cmplr.compiles('#include <@0@>'.format(h), name : '#include <@0@>'.format(h))
- logging_src = 'logging.cpp'
+ logging_src = 'attn_logging.cpp'
else
logging_src = '../test/end2end/logging.cpp'
endif
diff --git a/attn/ti_handler.cpp b/attn/ti_handler.cpp
index b991b6e..4801f2c 100644
--- a/attn/ti_handler.cpp
+++ b/attn/ti_handler.cpp
@@ -1,4 +1,4 @@
-#include <logging.hpp>
+#include <attn_logging.hpp>
#include <sdbusplus/bus.hpp>
namespace attn
@@ -8,7 +8,7 @@
void tiHandler()
{
// trace message
- log<level::INFO>("start host diagnostic mode service");
+ trace<level::INFO>("start host diagnostic mode service");
// Use the systemd service manager object interface to call the start unit
// method with the obmc-host-diagnostic-mode target.