Attn: use phal library for get TI info calls
Switch from using pdbg library sbe_mpipl_get_ti_info() to using phal
library getTiInfo() for retrieving pointer to TI info shared memory
region.
Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
Change-Id: I916d9195493b2759eed1695b36b9ae156b37be7e
diff --git a/attn/attn_handler.cpp b/attn/attn_handler.cpp
index 566b2f7..718828a 100644
--- a/attn/attn_handler.cpp
+++ b/attn/attn_handler.cpp
@@ -4,6 +4,10 @@
#include <libpdbg_sbe.h>
}
+#ifdef CONFIG_PHAL_API
+#include <libphal.H>
+#endif
+
#include <analyzer/analyzer_main.hpp>
#include <attn/attention.hpp>
#include <attn/attn_common.hpp>
@@ -47,6 +51,18 @@
/** @brief Determine if attention is active and not masked */
bool activeAttn(uint32_t i_val, uint32_t i_mask, uint32_t i_attn);
+#ifdef CONFIG_PHAL_API
+/** @brief Handle phal sbe exception */
+void phalSbeExceptionHandler(openpower::phal::exception::SbeError& e,
+ uint32_t procNum);
+#endif
+
+/** @brief Get static TI info data based on host state */
+void getStaticTiInfo(uint8_t*& tiInfoPtr);
+
+/** @brief Check if TI info data is valid */
+bool tiInfoValid(uint8_t* tiInfo);
+
/**
* @brief The main attention handler logic
*
@@ -260,9 +276,31 @@
bool tiInfoStatic = false; // assume TI info was provided (not created)
- if (attnProc != nullptr)
+ // need proc target to get dynamic TI info
+ if (nullptr != attnProc)
{
- // The processor PIB target is required for get TI info chipop
+#ifdef CONFIG_PHAL_API
+ trace<level::INFO>("using libphal to get TI info");
+
+ // phal library uses proc target for get ti info
+ if (PDBG_TARGET_ENABLED == pdbg_target_probe(attnProc))
+ {
+ try
+ {
+ // get dynamic TI info
+ openpower::phal::sbe::getTiInfo(attnProc, &tiInfo, &tiInfoLen);
+ }
+ catch (openpower::phal::exception::SbeError& e)
+ {
+ // library threw an exception
+ uint32_t procNum = pdbg_target_index(attnProc);
+ phalSbeExceptionHandler(e, procNum);
+ }
+ }
+#else
+ trace<level::INFO>("using libpdbg to get TI info");
+
+ // pdbg library uses pib target for get ti info
char path[16];
sprintf(path, "/proc%d/pib", pdbg_target_index(attnProc));
pdbg_target* tiInfoTarget = pdbg_target_from_path(nullptr, path);
@@ -272,99 +310,30 @@
if (PDBG_TARGET_ENABLED == pdbg_target_probe(tiInfoTarget))
{
sbe_mpipl_get_ti_info(tiInfoTarget, &tiInfo, &tiInfoLen);
-
- // If TI info not available use default based on host state
- if (nullptr == tiInfo)
- {
- trace<level::INFO>("TI info data ptr is invalid");
-
- util::dbus::HostRunningState runningState =
- util::dbus::hostRunningState();
-
- std::string stateString = "host state unknown";
-
- if ((util::dbus::HostRunningState::Started ==
- runningState) ||
- (util::dbus::HostRunningState::Unknown == runningState))
- {
- if (util::dbus::HostRunningState::Started ==
- runningState)
- {
- stateString = "host started";
- }
- tiInfo = (uint8_t*)defaultPhypTiInfo;
- }
- else
- {
- stateString = "host not started";
- tiInfo = (uint8_t*)defaultHbTiInfo;
- }
-
- // trace host state
- trace<level::INFO>(stateString.c_str());
-
- tiInfoStatic = true; // using our TI info
- }
}
}
+#endif
}
- bool tiInfoValid = false; // TI area data not valid or not available
-
- // If TI area exists and is marked valid we can assume TI occurred
- if ((nullptr != tiInfo) && (0 != tiInfo[0]))
+ // dynamic TI info is not available
+ if (nullptr == tiInfo)
{
- TiDataArea* tiDataArea = (TiDataArea*)tiInfo;
-
- std::stringstream ss; // string stream object for tracing
- std::string strobj; // string object for tracing
-
- // trace a few known TI data area values
- ss.str(std::string()); // empty the stream
- ss.clear(); // clear the stream
- ss << "TI data command = 0x" << std::setw(2) << std::setfill('0')
- << std::hex << (int)tiDataArea->command;
- strobj = ss.str();
- trace<level::INFO>(strobj.c_str());
-
- // Another check for valid TI Info since it has been seen that
- // tiInfo[0] != 0 but TI info is not valid
- if (0xa1 == tiDataArea->command)
- {
- tiInfoValid = true;
-
- // trace some more data since TI info appears valid
- ss.str(std::string()); // empty the stream
- ss.clear(); // clear the stream
- ss << "TI data term-type = 0x" << std::setw(2) << std::setfill('0')
- << std::hex << (int)tiDataArea->hbTerminateType;
- strobj = ss.str();
- trace<level::INFO>(strobj.c_str());
-
- ss.str(std::string()); // empty the stream
- ss.clear(); // clear the stream
- ss << "TI data SRC format = 0x" << std::setw(2) << std::setfill('0')
- << std::hex << (int)tiDataArea->srcFormat;
- strobj = ss.str();
- trace<level::INFO>(strobj.c_str());
-
- ss.str(std::string()); // empty the stream
- ss.clear(); // clear the stream
- ss << "TI data source = 0x" << std::setw(2) << std::setfill('0')
- << std::hex << (int)tiDataArea->source;
- strobj = ss.str();
- trace<level::INFO>(strobj.c_str());
-
- if (true == (i_attention->getConfig()->getFlag(enTerminate)))
- {
- // Call TI special attention handler
- rc = tiHandler(tiDataArea);
- }
- }
+ trace<level::INFO>("TI info data ptr is invalid");
+ getStaticTiInfo(tiInfo);
+ tiInfoStatic = true;
}
- // TI area is available but was not valid data
- if (false == tiInfoValid)
+ // check TI info for validity and handle
+ if (true == tiInfoValid(tiInfo))
+ {
+ // TI info is valid handle TI if support enabled
+ if (true == (i_attention->getConfig()->getFlag(enTerminate)))
+ {
+ // Call TI special attention handler
+ rc = tiHandler((TiDataArea*)tiInfo);
+ }
+ }
+ else
{
trace<level::INFO>("TI info NOT valid");
@@ -375,10 +344,10 @@
if (true == (i_attention->getConfig()->getFlag(enTerminate)))
{
// Call TI special attention handler
- rc = tiHandler(nullptr);
+ rc = tiHandler((TiDataArea*)tiInfo);
}
}
- // breakpoint is default special attention when TI info NOT valid
+ // configured to handle breakpoint as default special attention
else
{
// breakpoint handling may be disabled
@@ -390,12 +359,17 @@
}
}
- // release TI data buffer
- if ((nullptr != tiInfo) && (false == tiInfoStatic))
+ // release TI data buffer if not ours
+ if (false == tiInfoStatic)
{
- free(tiInfo);
+ // sanity check
+ if (nullptr != tiInfo)
+ {
+ free(tiInfo);
+ }
}
+ // trace non-successful exit condition
if (RC_SUCCESS != rc)
{
trace<level::INFO>("Special attn not handled");
@@ -463,4 +437,117 @@
return rc;
}
+
+#ifdef CONFIG_PHAL_API
+/**
+ * @brief Handle phal sbe exception
+ *
+ * @param[in] e - exception object
+ * @param[in] procNum - processor number associated with sbe exception
+ */
+void phalSbeExceptionHandler(openpower::phal::exception::SbeError& e,
+ uint32_t procNum)
+{
+ // trace exception details
+ std::string traceMsg = std::string(e.what());
+ trace<level::ERROR>(traceMsg.c_str());
+
+ // Handle SBE chipop timeout error
+ if (e.errType() == openpower::phal::exception::SBE_CHIPOP_NOT_ALLOWED)
+ {
+ eventPhalSbeChipop(procNum);
+ }
+}
+#endif
+
+/**
+ * @brief Get static TI info data based on host state
+ *
+ * @param[out] tiInfo - pointer to static TI info data
+ */
+void getStaticTiInfo(uint8_t*& tiInfo)
+{
+ util::dbus::HostRunningState runningState = util::dbus::hostRunningState();
+
+ // assume host state is unknown
+ std::string stateString = "host state unknown";
+
+ if ((util::dbus::HostRunningState::Started == runningState) ||
+ (util::dbus::HostRunningState::Unknown == runningState))
+ {
+ if (util::dbus::HostRunningState::Started == runningState)
+ {
+ stateString = "host started";
+ }
+ tiInfo = (uint8_t*)defaultPhypTiInfo;
+ }
+ else
+ {
+ stateString = "host not started";
+ tiInfo = (uint8_t*)defaultHbTiInfo;
+ }
+
+ // trace host state
+ trace<level::INFO>(stateString.c_str());
+}
+
+/**
+ * @brief Check if TI info data is valid
+ *
+ * @param[in] tiInfo - pointer to TI info data
+ * @return true if TI info data is valid, else false
+ */
+bool tiInfoValid(uint8_t* tiInfo)
+{
+ bool tiInfoValid = false; // assume TI info invalid
+
+ // TI info data[0] non-zero indicates TI info valid (usually)
+ if ((nullptr != tiInfo) && (0 != tiInfo[0]))
+ {
+ TiDataArea* tiDataArea = (TiDataArea*)tiInfo;
+
+ std::stringstream ss; // string stream object for tracing
+ std::string strobj; // string object for tracing
+
+ // trace a few known TI data area values
+ ss.str(std::string()); // empty the stream
+ ss.clear(); // clear the stream
+ ss << "TI data command = 0x" << std::setw(2) << std::setfill('0')
+ << std::hex << (int)tiDataArea->command;
+ strobj = ss.str();
+ trace<level::INFO>(strobj.c_str());
+
+ // Another check for valid TI Info since it has been seen that
+ // tiInfo[0] != 0 but TI info is not valid
+ if (0xa1 == tiDataArea->command)
+ {
+ tiInfoValid = true;
+
+ // trace some more data since TI info appears valid
+ ss.str(std::string()); // empty the stream
+ ss.clear(); // clear the stream
+ ss << "TI data term-type = 0x" << std::setw(2) << std::setfill('0')
+ << std::hex << (int)tiDataArea->hbTerminateType;
+ strobj = ss.str();
+ trace<level::INFO>(strobj.c_str());
+
+ ss.str(std::string()); // empty the stream
+ ss.clear(); // clear the stream
+ ss << "TI data SRC format = 0x" << std::setw(2) << std::setfill('0')
+ << std::hex << (int)tiDataArea->srcFormat;
+ strobj = ss.str();
+ trace<level::INFO>(strobj.c_str());
+
+ ss.str(std::string()); // empty the stream
+ ss.clear(); // clear the stream
+ ss << "TI data source = 0x" << std::setw(2) << std::setfill('0')
+ << std::hex << (int)tiDataArea->source;
+ strobj = ss.str();
+ trace<level::INFO>(strobj.c_str());
+ }
+ }
+
+ return tiInfoValid;
+}
+
} // namespace attn
diff --git a/attn/attn_logging.cpp b/attn/attn_logging.cpp
index 8aed00f..55c782b 100644
--- a/attn/attn_logging.cpp
+++ b/attn/attn_logging.cpp
@@ -365,6 +365,10 @@
eventName = "org.open_power.Attn.Error.Fail";
eventValid = true;
break;
+ case EventType::PhalSbeChipop:
+ eventName = "org.open_power.Processor.Error.SbeChipOpFailure";
+ eventValid = true;
+ break;
default:
eventValid = false;
break;
@@ -498,6 +502,26 @@
}
/**
+ * Commit SBE timeout event to log
+ *
+ * Create an event log indicating an SBE operation timed out.
+ *
+ * @param proc - processor that encountered the error
+ */
+void eventPhalSbeChipop(uint32_t proc)
+{
+ trace<level::ERROR>("SBE error while getting TI info");
+
+ // report proc number in event log entry
+ std::map<std::string, std::string> additionalData;
+ additionalData.emplace("SRC6", std::to_string(proc << 16));
+
+ // create event with additional data and no ffdc
+ event(EventType::PhalSbeChipop, additionalData,
+ createFFDCFiles(nullptr, 0));
+}
+
+/**
* Parse systemd journal message field
*
* Parse the journal looking for the specified field and return the journal
diff --git a/attn/attn_logging.hpp b/attn/attn_logging.hpp
index e790d94..84c986b 100644
--- a/attn/attn_logging.hpp
+++ b/attn/attn_logging.hpp
@@ -30,7 +30,8 @@
Terminate = 1,
Vital = 2,
HwDiagsFail = 3,
- AttentionFail = 4
+ AttentionFail = 4,
+ PhalSbeChipop = 5
};
/** @brief Maximum length of a single trace event message */
@@ -50,4 +51,7 @@
/** @brief Commit attention handler failure event to log */
void eventAttentionFail(int i_error);
+/** @brief Commit sbe chipop event to log */
+void eventPhalSbeChipop(uint32_t proc);
+
} // namespace attn
diff --git a/attn/meson.build b/attn/meson.build
index c366182..8430c07 100644
--- a/attn/meson.build
+++ b/attn/meson.build
@@ -65,6 +65,11 @@
sdbusplus_dep,
]
+# conditional library dependencies
+if get_option('phal').enabled()
+ attn_deps += libphal_dep
+endif
+
# Create static library.
attn_lib = static_library(
'attn_lib',
diff --git a/meson.build b/meson.build
index 842b539..9837e17 100644
--- a/meson.build
+++ b/meson.build
@@ -61,6 +61,10 @@
libpdbg_dep = cmplr.find_library('pdbg')
+if get_option('phal').enabled()
+ libphal_dep = cmplr.find_library('phal')
+endif
+
# See if phosphor-logging is available, if not use test case logging code. This
# allows for local builds outside of CI test sandbox.
h = 'phosphor-logging/log.hpp'
diff --git a/test/end2end/logging.cpp b/test/end2end/logging.cpp
index d75625e..9fe119e 100644
--- a/test/end2end/logging.cpp
+++ b/test/end2end/logging.cpp
@@ -48,4 +48,9 @@
return 0;
}
+void eventPhalSbeChipop(uint32_t proc)
+{
+ std::cout << "event: sbe timeout proc " << proc << std::endl;
+}
+
} // namespace attn